Spring MVC 實踐
標簽 : Java與Web
Spring Web MVC
Spring-Web-MVC是一種基于請求驅動的 輕量級Web-MVC設計模式框架, Spring MVC使用MVC架構思想, 對Web層進行職責解耦 ,使用請求-響應 模型將數據 、業務 與視圖 進行分離, 簡化開發.
MVC
MVC(模型-視圖-控制器)是一個以設計界面應用程序為基礎 的架構模式,通過分離模型-視圖-控制器在應用中的角色將業務邏輯從界面中解耦:
模型負責封裝應用數據和業務邏輯; 視圖僅負責展示數據; 控制器負責接收用戶請求,并調用模型(Service/Manger/DAO)來處理業務邏輯.模型可能會返回一些數據需要在視圖層展示,控制器就需要整理模型數據并調用視圖展示.
MVC模式的核心思想就是將業務邏輯從界面中分離出來,允許它們單獨改變而不會相互影響.
Spring MVC
Spring MVC框架是基于Java語言的MVC架構具體實現.他的設計圍繞DispatcherServlet展開,DispatcherServlet負責將請求分派給指定的Controller(Handler),通過可配置的HandlerMapping、HandlAdapter、Controller、ViewResolver來處理請求 拿到數據并填充對應的視圖View :
組件名稱描述 DispatcherServlet 調度器/前端控制器 DispatcherServlet是前端控制器 模式的具體實現(詳細可參考Front Controller),他提供了整個Web應用的集中訪問點,截獲請求并將其分派給指定的Controller,相當于MVC中的C. 他的存在降低了組件之間的耦合性. HandlerMapping 處理器映射器 HandlerMapping負責根據用戶請求URI找到對應的Controller與Interceptor,并將它們封裝在HandlerExecutionChain中返回給DispatcherServlet. HandlAdapter 處理器適配器 Spring MVC通過HandlerAdapter執行Controller,這是適配器模式 的應用,通過擴展適配器可以執行更多類型的Controller. Controller 處理器 Controller(又稱Handler)是繼DispatcherServlet前端控制器之后的后端控制器 ,在DispatcherServlet的控制下Controller對具體的用戶請求進行處理. ViewResolver 視圖解析器 負責將Model數據填充到View, 組合生成視圖展示:他首先將邏輯視圖名 解析成物理視圖名 ,生成View視圖對象,最后對View進行渲染(填充數據). Spring默認提供了針對JSP/Velocity/PFD等視圖的ViewResolver實現.
初識Spring MVC
需求: 用戶列表查詢.
mvn archetype:generate -DgroupId=com.fq.mvc -
DartifactId =MVC
-
DarchetypeArtifactId =maven-archetype-webapp
-
DinteractiveMode =false
-
DarchetypeCatalog =internal
依賴管理 在pom.xml中添加Spring 、Spring MVC 、 Sevlet 及Velocity 依賴:
<dependency > <groupId > org.springframework
</groupId > <artifactId > spring-core
</artifactId > <version > ${spring.version}
</version >
</dependency >
<dependency > <groupId > org.springframework
</groupId > <artifactId > spring-context
</artifactId > <version > ${spring.version}
</version >
</dependency >
<dependency > <groupId > org.springframework
</groupId > <artifactId > spring-context-support
</artifactId > <version > ${spring.version}
</version >
</dependency >
<dependency > <groupId > org.springframework
</groupId > <artifactId > spring-beans
</artifactId > <version > ${spring.version}
</version >
</dependency >
<dependency > <groupId > org.springframework
</groupId > <artifactId > spring-expression
</artifactId > <version > ${spring.version}
</version >
</dependency >
<dependency > <groupId > org.springframework
</groupId > <artifactId > spring-web
</artifactId > <version > ${spring.version}
</version >
</dependency >
<dependency > <groupId > org.springframework
</groupId > <artifactId > spring-test
</artifactId > <version > ${spring.version}
</version >
</dependency >
<dependency > <groupId > javax.servlet
</groupId > <artifactId > javax.servlet-api
</artifactId > <version > ${servlet.version}
</version >
</dependency >
<dependency > <groupId > org.springframework
</groupId > <artifactId > spring-webmvc
</artifactId > <version > ${spring.version}
</version >
</dependency >
<dependency > <groupId > org.apache.velocity
</groupId > <artifactId > velocity
</artifactId > <version > ${velocity.version}
</version >
</dependency >
<dependency > <groupId > org.apache.velocity
</groupId > <artifactId > velocity-tools
</artifactId > <version > ${velocity.tools.version}
</version >
</dependency >
配置DispatcherServlet(web.xml)
<?xml version="1.0" encoding="UTF-8"?>
<web-app version ="3.0" xmlns ="http://java.sun.com/xml/ns/javaee" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" > <display-name > MVC
</display-name > <servlet > <servlet-name > mvc
</servlet-name > <servlet-class > org.springframework.web.servlet.DispatcherServlet
</servlet-class > <init-param > <param-name > contextConfigLocation
</param-name > <param-value > classpath:spring/mvc-servlet.xml
</param-value > </init-param > <load-on-startup > 1
</load-on-startup > </servlet > <servlet-mapping > <servlet-name > mvc
</servlet-name > <url-pattern > *.do
</url-pattern > </servlet-mapping >
</web-app >
配置HandlerMapping/HandlerAdapter(mvc-servlet.xml)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd" > <bean class ="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" /> <bean class ="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
</beans >
/*** @author jifang* @since 16/3/15 下午4:40.*/
public class UserController implements Controller {@Override public ModelAndView
handleRequest (HttpServletRequest request, HttpServletResponse response)
throws Exception {List<User> users =
new ArrayList<>();users.add(
new User(
1 ,
"翡青" ,
new Date(),
1 ,
"浙江-杭州" ));users.add(
new User(
2 ,
"小芳" ,
new Date(),
2 ,
"山東-青島" ));ModelAndView result =
new ModelAndView();result.addObject(
"users" , users);result.setViewName(
"users" );
return result;}
}
<bean name ="/mvc/users.do" class ="com.fq.mvc.controller.UserController" />
配置ViewResolver(mvc-servlet.xml) 由于我們視圖選用的是Velocity ,因此配置VelocityViewResolver:
<bean id ="viewResolver" class ="org.springframework.web.servlet.view.velocity.VelocityViewResolver" > <property name ="suffix" value =".vm" /> <property name ="contentType" value ="text/html;charset=UTF-8" /> <property name ="dateToolAttribute" value ="dateTool" /> <property name ="numberToolAttribute" value ="numberTool" /> <property name ="exposeRequestAttributes" value ="false" /> <property name ="exposeSessionAttributes" value ="true" />
</bean >
<bean id ="velocityConfigurer" class ="org.springframework.web.servlet.view.velocity.VelocityConfigurer" > <property name ="resourceLoaderPath" value ="views" /> <property name ="velocityProperties" > <props > <prop key ="input.encoding" > UTF-8
</prop > <prop key ="output.encoding" > UTF-8
</prop > </props > </property >
</bean >
<html >
<head > <title > 用戶列表
</title > <link rel ="stylesheet" href ="/css/main.css" > <meta http-equiv ="content-type" content ="text/html; charset=UTF-8" />
</head >
<body >
<div id ="global" > <fieldset > <legend > 用戶列表:
</legend > <table width ="100%" border =0 > <tr > <td > ID
</td > <td > username
</td > <td > birthday
</td > <td > sex
</td > <td > address
</td > </tr > #foreach($user in $users)
<tr > <td > ${user.id}
</td > <td > ${user.name}
</td > <td > ${user.birthday}
</td > #if(${user.sex} == 1)
<td > 男
</td > #else
<td > 女
</td > #end
<td > ${user.address}
</td > </tr > #end
</table > </fieldset >
</div >
</body >
</html >
參考: main.css地址:OSChina
小結
前端控制器 Spring MVC DispatcherServlet的url-pattern有兩種配置方式:
*.do: 攔截所有以.do結尾的URI. / : 攔截 所有 URI. 處理器映射器 BeanNameUrlHandlerMapping指定將Bean的Name作為URI映射; Spring還提供了SimpleUrlHandlerMapping將URI和Controller的id統一映射配置.
處理器適配器 SimpleControllerHandlerAdapter對所有實現了Controller接口的JavaBean適配.Spring還提供HttpRequestHandlerAdapter對所有實現了HttpRequestHandler接口的JavaBean適配.
視圖解析器 前面使用Velocity 作為視圖展示,如果使用的是JSP的話, 需要配置另一種視圖解析器InternalResourceViewResolver:
<bean class ="org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name ="viewClass" value ="org.springframework.web.servlet.view.JstlView" /> <property name ="prefix" value ="/views" /> <property name ="suffix" value =".jsp" />
</bean >
注解初步
從2.5版本開始, Spring引入了注解開發:
注解驅動(mvc-servlet.xml) 從3.1版本開始,Spring MVC使用RequestMappingHandlerMapping 注解式處理器映射器 對標有@ResquestMapping的方法進行映射 . 從3.1版本開始,Spring MVC使用RequestMappingHandlerAdapter 注解式處理器適配器 對標記有@ResquestMapping的方法進行適配 . Spring MVC使用<mvc:annotation-driven/> 注解驅動 自動加載RequestMappingHandlerMapping和RequestMappingHandlerAdapter及其他相關配置. 因此在mvc-servlet.xml最簡單有效的配置方式是使用<mvc:annotation-driven/>替代注解處理器和適配器:
<mvc:annotation-driven />
盡管<mvc:annotation-driven/>很小, 但他具有足夠的威力, 它注冊了很多的特性, 包括對JSR-303校驗、信息轉換以及對域格式化的支持.
組件掃描(mvc-servlet.xml): 使用Spring的組件掃描來省去為每個Controller注冊的麻煩:
<
context :
component -scan base-
package =
"com.fq.mvc.controller" />
@Controller
@RequestMapping (
"/mvc" )
public class UserController {@RequestMapping (
"/users.do" )
public ModelAndView
users () {List<User> users =
new ArrayList<>();users.add(
new User(
1 ,
"翡青" ,
new Date(),
1 ,
"浙江-杭州" ));users.add(
new User(
2 ,
"小芳" ,
new Date(),
2 ,
"山東-青島" ));ModelAndView result =
new ModelAndView();result.addObject(
"users" , users);result.setViewName(
"users" );
return result;}
}
使用基于注解的`Controller`有以下優點:- 基于注解的`Controller`請求映射關系不存儲在配置文件中,使用`@RequestMappeing`便可以對一個方法進行映射.- 一個`Controller`內可以有多個處理方法,可以響應多個動作,這樣就允許將同一模塊的多個操作寫在同一個`Controller`里面,便于模塊劃分,且減少類的數量.
集成MyBatis
通過Spring將各層整合: 持久層DAO(MyBatis的Mapper)注冊到Spring容器中. 業務層Service/Manager從Spring容器中拿到DAO接口, 并注冊Service服務. 表現層Controller從Spring容器中拿到Service接口, 通過Spring MVC進行數據展示.
需求: 展示所有用戶數據(由于數據模型較簡單, 因此從DAO到Controller只使用一個DO對象-User).
<dependency > <groupId > org.springframework
</groupId > <artifactId > spring-core
</artifactId > <version > ${spring.version}
</version >
</dependency >
<dependency > <groupId > org.springframework
</groupId > <artifactId > spring-context
</artifactId > <version > ${spring.version}
</version >
</dependency >
<dependency > <groupId > org.springframework
</groupId > <artifactId > spring-context-support
</artifactId > <version > ${spring.version}
</version >
</dependency >
<dependency > <groupId > org.springframework
</groupId > <artifactId > spring-beans
</artifactId > <version > ${spring.version}
</version >
</dependency >
<dependency > <groupId > org.springframework
</groupId > <artifactId > spring-expression
</artifactId > <version > ${spring.version}
</version >
</dependency >
<dependency > <groupId > org.springframework
</groupId > <artifactId > spring-web
</artifactId > <version > ${spring.version}
</version >
</dependency >
<dependency > <groupId > org.springframework
</groupId > <artifactId > spring-test
</artifactId > <version > ${spring.version}
</version >
</dependency >
<dependency > <groupId > org.springframework
</groupId > <artifactId > spring-aop
</artifactId > <version > ${spring.version}
</version >
</dependency >
<dependency > <groupId > org.springframework
</groupId > <artifactId > spring-aspects
</artifactId > <version > ${spring.version}
</version >
</dependency >
<dependency > <groupId > javax.servlet
</groupId > <artifactId > javax.servlet-api
</artifactId > <version > ${servlet.version}
</version >
</dependency >
<dependency > <groupId > org.springframework
</groupId > <artifactId > spring-webmvc
</artifactId > <version > ${spring.version}
</version >
</dependency >
<dependency > <groupId > org.apache.velocity
</groupId > <artifactId > velocity
</artifactId > <version > ${velocity.version}
</version >
</dependency >
<dependency > <groupId > org.apache.velocity
</groupId > <artifactId > velocity-tools
</artifactId > <version > ${velocity.tools.version}
</version >
</dependency >
<dependency > <groupId > org.mybatis
</groupId > <artifactId > mybatis
</artifactId > <version > 3.3.0
</version >
</dependency >
<dependency > <groupId > mysql
</groupId > <artifactId > mysql-connector-java
</artifactId > <version > ${mysql.version}
</version >
</dependency >
<dependency > <groupId > com.zaxxer
</groupId > <artifactId > HikariCP
</artifactId > <version > ${hikaricp.version}
</version >
</dependency >
<dependency > <groupId > org.springframework
</groupId > <artifactId > spring-jdbc
</artifactId > <version > ${spring.version}
</version >
</dependency >
<dependency > <groupId > org.springframework
</groupId > <artifactId > spring-tx
</artifactId > <version > ${spring.version}
</version >
</dependency >
<dependency > <groupId > org.mybatis
</groupId > <artifactId > mybatis-spring
</artifactId > <version > ${mybatis.spring.version}
</version >
</dependency >
<dependency > <groupId > ch.qos.logback
</groupId > <artifactId > logback-classic
</artifactId > <version > ${logback.version}
</version >
</dependency >
集成MyBatis
mybatis-configuration.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration > <mappers > <mapper resource ="mybatis/mapper/UserDAO.xml" /> </mappers >
</configuration >
/*** @author jifang.* @since 2016/5/26 11:16.*/
public class User {private int id;
private String name;
private Date birthday;
private int sex;
private String address;
public User () {}
public User (
int id, String name, Date birthday,
int sex, String address) {
this .id = id;
this .name = name;
this .birthday = birthday;
this .sex = sex;
this .address = address;}
public int getId () {
return id;}
public void setId (
int id) {
this .id = id;}
public String
getName () {
return name;}
public void setName (String name) {
this .name = name;}
public Date
getBirthday () {
return birthday;}
public void setBirthday (Date birthday) {
this .birthday = birthday;}
public int getSex () {
return sex;}
public void setSex (
int sex) {
this .sex = sex;}
public String
getAddress () {
return address;}
public void setAddress (String address) {
this .address = address;}
}
/*** @author jifang* @since 16/3/20 下午5:47.*/
public interface UserDAO {List<User> selectAllUsers();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace ="com.fq.mvc.dao.UserDAO" > <select id ="selectAllUsers" resultType ="com.fq.mvc.domain.User" > SELECT *FROM user;
</select > </mapper >
applicationContext-datasource.xml(配置數據源)
<beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:context ="http://www.springframework.org/schema/context" xsi:schemaLocation ="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd" > <context:property-placeholder location ="classpath:db.properties" /> <bean id ="hikariConfig" class ="com.zaxxer.hikari.HikariConfig" > <property name ="driverClassName" value ="${mysql.driver.class}" /> <property name ="jdbcUrl" value ="${mysql.url}" /> <property name ="username" value ="${mysql.user}" /> <property name ="password" value ="${mysql.password}" /> <property name ="maximumPoolSize" value ="5" /> <property name ="maxLifetime" value ="700000" /> <property name ="idleTimeout" value ="600000" /> <property name ="connectionTimeout" value ="10000" /> <property name ="dataSourceProperties" > <props > <prop key ="dataSourceClassName" > com.mysql.jdbc.jdbc2.optional.MysqlDataSource
</prop > <prop key ="cachePrepStmts" > true
</prop > <prop key ="prepStmtCacheSize" > 250
</prop > <prop key ="prepStmtCacheSqlLimit" > 2048
</prop > </props > </property > </bean > <bean id ="dataSource" class ="com.zaxxer.hikari.HikariDataSource" destroy-method ="close" > <constructor-arg ref ="hikariConfig" /> </bean > <bean id ="sqlSessionFactory" class ="org.mybatis.spring.SqlSessionFactoryBean" > <property name ="dataSource" ref ="dataSource" /> <property name ="configLocation" value ="classpath:mybatis/mybatis-configuration.xml" /> </bean > <bean class ="org.mybatis.spring.mapper.MapperScannerConfigurer" > <property name ="basePackage" value ="com.fq.mvc.dao" /> <property name ="sqlSessionFactoryBeanName" value ="sqlSessionFactory" /> </bean > <bean id ="transactionManager" class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" > <property name ="dataSource" ref ="dataSource" /> </bean > </beans >
## Data Source
mysql
.driver .class =
com .mysql .jdbc .Driver
mysql
.url =jdbc:mysql://host:port/db?characterEncoding=utf-
8
mysql
.user =user
mysql
.password =password
集成Service
public interface UserService {List<User> getAllUsers();
}
@Service
public class UserServiceImpl implements UserService {@Autowired private UserDAO dao;
@Override public List<User>
getAllUsers () {
return dao.selectAllUsers();}
}
applicationContext.xml(配置組件掃描與事務控制)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:context ="http://www.springframework.org/schema/context" xmlns:tx ="http://www.springframework.org/schema/tx" xmlns:aop ="http://www.springframework.org/schema/aop" xsi:schemaLocation ="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd" > <import resource ="applicationContext-datasource.xml" /> <context:component-scan base-package ="com.fq.mvc.service" /> <bean id ="transactionManager" class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" > <property name ="dataSource" ref ="dataSource" /> </bean > <tx:advice id ="txAdvice" transaction-manager ="transactionManager" > <tx:attributes > <tx:method name ="select*" timeout ="-1" propagation ="REQUIRED" read-only ="true" /> </tx:attributes > </tx:advice > <aop:config > <aop:advisor advice-ref ="txAdvice" pointcut ="execution(* com.fq.mvc.service.impl.UserServiceImpl.*(..))" /> </aop:config > </beans >
集成MVC
@Controller
@RequestMapping (
"/mvc" )
public class UserController {@Autowired private UserService service;
@RequestMapping (value =
"/user.do" )
public ModelAndView
users () {List<User> users = service.getAllUsers();
return new ModelAndView(
"users" ,
"users" , users);}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc ="http://www.springframework.org/schema/mvc" xmlns:context ="http://www.springframework.org/schema/context" xsi:schemaLocation ="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd" > <mvc:annotation-driven /> <context:component-scan base-package ="com.fq.mvc.controller" /> <bean id ="viewResolver" class ="org.springframework.web.servlet.view.velocity.VelocityViewResolver" > <property name ="suffix" value =".vm" /> <property name ="contentType" value ="text/html;charset=UTF-8" /> <property name ="dateToolAttribute" value ="dateTool" /> <property name ="numberToolAttribute" value ="numberTool" /> <property name ="exposeRequestAttributes" value ="false" /> <property name ="exposeSessionAttributes" value ="true" /> </bean > <bean id ="velocityConfigurer" class ="org.springframework.web.servlet.view.velocity.VelocityConfigurer" > <property name ="resourceLoaderPath" value ="views" /> <property name ="velocityProperties" > <props > <prop key ="input.encoding" > UTF-8
</prop > <prop key ="output.encoding" > UTF-8
</prop > </props > </property > </bean >
</beans >
<?xml version="1.0" encoding="UTF-8"?>
<web-app version ="3.0" xmlns ="http://java.sun.com/xml/ns/javaee" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" > <display-name > MVC
</display-name > <listener > <listener-class > org.springframework.web.context.ContextLoaderListener
</listener-class > </listener > <context-param > <param-name > contextConfigLocation
</param-name > <param-value > classpath:spring/applicationContext.xml
</param-value > </context-param > <servlet > <servlet-name > mvc
</servlet-name > <servlet-class > org.springframework.web.servlet.DispatcherServlet
</servlet-class > <init-param > <param-name > contextConfigLocation
</param-name > <param-value > classpath:spring/mvc-servlet.xml
</param-value > </init-param > <load-on-startup > 1
</load-on-startup > </servlet > <servlet-mapping > <servlet-name > mvc
</servlet-name > <url-pattern > *.do
</url-pattern > </servlet-mapping >
</web-app >
集成log
為了能夠看到Spring MVC的運行時信息 , 最好在應用中集成一種Log實現, 在此選用LogBack :
<configuration > <property name ="log_root_dir" value ="/data/logs/mvc/" /> <property name ="log_pattern" value ="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{0} - %msg%n" /> <appender name ="STD_OUT" class ="ch.qos.logback.core.ConsoleAppender" > <encoder > <pattern > ${log_pattern}
</pattern > </encoder > </appender > <appender name ="FILE_OUT" class ="ch.qos.logback.core.rolling.RollingFileAppender" > <rollingPolicy class ="ch.qos.logback.core.rolling.TimeBasedRollingPolicy" > <fileNamePattern > ${log_root_dir}/mvc-server.%d{YY-MM-dd}.log
</fileNamePattern > <maxHistory > 7
</maxHistory > </rollingPolicy > <encoder > <pattern > ${log_pattern}
</pattern > </encoder > </appender > <root level ="DEBUG" > <appender-ref ref ="STD_OUT" /> <appender-ref ref ="FILE_OUT" /> </root > </configuration >
注解開發
需求: 實現User添加.
<html >
<head > <title > 用戶添加
</title > <link rel ="stylesheet" href ="/css/main.css" > <meta http-equiv ="content-type" content ="text/html; charset=UTF-8" />
</head >
<body >
<div id ="global" > <fieldset > <legend > Add a User
</legend > <form action ="/mvc/add_user.do" method ="post" > <p > <label for ="name" > username:
</label > <input type ="text" name ="name" tabindex ="1" > </p > <p > <label for ="birthday" > birthday:
</label > <input type ="text" name ="birthday" tabindex ="2" /> </p > <p > <label for ="sex" > sex:
</label > <select name ="sex" tabindex ="3" > <option value ="1" > 男
</option > <option value ="2" > 女
</option > </select > </p > <p > <label form ="address" > address:
</label > <input type ="text" name ="address" tabindex ="4" > </p > <p id ="buttons" > <input type ="reset" tabindex ="5" > <input type ="submit" tabindex ="6" value ="Add User" > </p > </form > </fieldset >
</div >
</body >
</html >
@RequestMapping (
"/add_user.do" )
public String
addUser (User user){service.addUser(user);
return "redirect: users.do" ;
}
請求參數解析
在傳統的Servlet編程中, 可以使用HttpServletRequest的getParameter()方法來獲取請求參數值, 而在Spring MVC中, 它會調用請求參數解析組件 將客戶端傳過來的String字符串 解析為指定的Java對象 并傳遞給Controller, 這個過程稱為請求參數解析 .
Spring MVC默認提供了很多參數解析組件 , 因此Controller的請求處理方法默認就可以接收很多不同類型:
JavaEEJavaSESpring ServletRequest / HttpServletRequest InputStream / Reader WebRequest / NativeWebRequest ServletResponse / HttpServletResponse OutputStream / Writer Model / ModelMap HttpSession 命令或表單對象 (如String / Integer / User) RedirectAttributes HttpEntity<?> Array / List / Map Errors / BindingResult 帶@PathVariable / @MatrixVariable注解的對象 @RequestParam / @RequestHeader / @RequestBody / @RequestPart Principal / Locale SessionStatus UriComponentsBuilder
注: 1. 如果Controller形參名與URI中name不一致, 可使用@RequestParam注解對其進行修飾. 2. Spring MVC還支持路徑變量映射 (路徑變量類似于請求參數, 但沒有key部分, 只是一個值, 詳細可參考博客Spring MVC URL 路徑映射).
ModelAttribute
Spring MVC會在每次調用請求處理方法時都創建一個Model對象, 若打算使用該實例, 則可以在方法的形參添加一個Model形參. 其實還可以使用@ModelAttribute注解來訪問Model實例: 使用@ModelAttribute注解標注參數或方法,該方法會將其輸入的或創建的參數對象添加到Model對象中:
@RequestMapping (
"/check_id.do" )
public String
checkId (@
ModelAttribute ("id") String id, Model model){
return "check_id" ;
}
String實例將以id做key添加到Model對象中(如果key未命名,則默認使用類型的名稱(如string)做key).
@ModelAttribute標注方法 @ModelAttribute的第二個用途是標注一個非請求處理方法 : 被@ModelAttribute標注的方法會在每次調用Controller的請求處理方法時調用.該方法可以返回對象或void:
如果返回對象, 該對象會自動添加到Model中:
@ModelAttribute
private List<User>
addUser () {
return service.getAllUsers();
}
若返回void, 則必須添加一個Model類型參數, 自行將實例添加到Model中:
@ModelAttribute
private void addUser (Model model) {model.addAttribute(
"users" , service.getAllUsers());
}
重定向與Flash屬性
使用重定向的一個重要場景是避免用戶重新加載頁面再次調用相同動作 . 比如add_user.do: 當用戶提交表單時會將用戶信息插入數據庫. 但如果在提交表單后重新加載頁面, add_user.do會被再次調用, 相同的用戶可能會被再次添加.為了避免這種情況, 最好的辦法是在提交表單后將用戶重定向到一個不同的頁面,這個頁面任意重新加載都沒有副作用.
但使用重定向的一個不便之處在于: 無法輕松的給目標頁面傳值 . 如果采用轉發, 可屬性添加到Model, 使得目標視圖可以輕松訪問. 但用戶重定向需要經過客戶端, 所以Model的一切內容都會在重定向中丟失. 幸運的是, 在Spring 3.1之后,可以通過Flash屬性提供重定向傳值的方法:
要使用Flash屬性, 必須要有<annotation-driven/>注解驅動支持, 然后在方法上添加一個新的參數類型RedirectAttributes:
@RequestMapping (
"/add_user.do" )
public String
addUser (User user, RedirectAttributes attributes){service.addUser(user);attributes.addAttribute(
"message" ,
"new user has been saved to DB." );
return "redirect: /views/message.vm" ;
}
Controller返回值
應用了@Controller與@RequestMapping注解之后,Controller不再需要implements特定的接口, 因此Controller的返回值也變得多種多樣:
返回值描述 ModelAndView 包含視圖名與Model數據 Model Map 包含模型的屬性 View String 代表邏輯視圖名 void 可以在參數中傳入request/response完成對參數的解析, 對客戶端的響應 HttpEntity/ResponseEntity 提供對Servlet的訪問, 以響應HTTP頭部和內容 Callable DeferredResult 其他任意類型 常與響應JSON/XML結合
新人創作打卡挑戰賽 發博客就能抽獎!定制產品紅包拿不停!
總結
以上是生活随笔 為你收集整理的Spring MVC 实践 - Base 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。