Spring MVC 实践 - Base
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
需求: 用户列表查询.
- 创建Maven Web项目
mvn archetype:generate -DgroupId=com.fq.mvc -DartifactId=MVC
-DarchetypeArtifactId=maven-archetype-webapp
-DinteractiveMode=false
-DarchetypeCatalog=internal
- 依赖管理
在pom.xml中添加Spring、Spring MVC、 Sevlet及Velocity依赖:
<!-- Spring -->
<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><!-- WEB -->
<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><!-- Velocity -->
<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><!-- 配置SpringMVC --><servlet><servlet-name>mvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><!-- contextConfigLocation: 指定MVC配置文件位置 --><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><!-- 拦截所有以.do结尾的URL --><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>
Controller
/*** @author jifang* @since 16/3/15 下午4:40.*/
public class UserController implements Controller {@Overridepublic 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;}
}
<!-- 装配 Controller -->
<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><!-- 配置Velocity -->
<bean id="velocityConfigurer"class="org.springframework.web.servlet.view.velocity.VelocityConfigurer"><!-- 设置VM模板放置位置--><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>
- View(/views/users.vm)
<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 MVCDispatcherServlet
的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"><!-- "JstlView"表示可以在JSP页面JSTL标签库,所以需要在项目中添加JSTL依赖 --><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/>
替代注解处理器和适配器:
- 从3.1版本开始,Spring MVC使用
<mvc:annotation-driven/>
尽管<mvc:annotation-driven/>
很小, 但他具有足够的威力, 它注册了很多的特性, 包括对JSR-303校验、信息转换以及对域格式化的支持.
- 组件扫描(mvc-servlet.xml):
使用Spring的组件扫描来省去为每个Controller
注册的麻烦:
<context:component-scan base-package="com.fq.mvc.controller"/>
- 注解
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).
- 依赖管理
<!-- Spring -->
<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><!-- AOP -->
<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><!-- WEB -->
<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><!-- Velocity -->
<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><!-- DB -->
<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><!-- Spring DB支持 -->
<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><!-- log -->
<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>
- domain: User
/*** @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;}
}
- UserDAO
/*** @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><!-- 配置SqlSessionFactory --><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"/><property name="configLocation" value="classpath:mybatis/mybatis-configuration.xml"/></bean><!-- 基于包扫描的mapper配置 --><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>
- db.properties
## 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 {@Autowiredprivate UserDAO dao;@Overridepublic 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
@Controller
@RequestMapping("/mvc")
public class UserController {@Autowiredprivate UserService service;@RequestMapping(value = "/user.do")public ModelAndView users() {List<User> users = service.getAllUsers();return new ModelAndView("users", "users", users);}
}
- 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"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><!-- 配置Velocity --><bean id="velocityConfigurer"class="org.springframework.web.servlet.view.velocity.VelocityConfigurer"><!-- 设置VM模板放置位置--><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>
- 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><!-- 加载Spring --><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><!-- 加载SpringMVC --><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>
- View视图同前
集成log
为了能够看到Spring MVC的运行时信息, 最好在应用中集成一种Log实现, 在此选用LogBack:
- logback.xml
<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添加.
- add_user.vm
<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>
- Controller
@RequestMapping("/add_user.do")
public String addUser(User user){service.addUser(user);return "redirect: users.do";
}
- Service/DAO实现简单,不再赘述.
请求参数解析
在传统的Servlet编程中, 可以使用
HttpServletRequest
的getParameter()
方法来获取请求参数值, 而在Spring MVC中, 它会调用请求参数解析组件将客户端传过来的String
字符串解析为指定的Java对象并传递给Controller
, 这个过程称为请求参数解析.
Spring MVC默认提供了很多参数解析组件, 因此Controller
的请求处理方法默认就可以接收很多不同类型:
JavaEE | JavaSE | Spring |
---|---|---|
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
对象中:
@ModelAttribute
标注形参
@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相关推荐
- Spring MVC 实践 - Component
Spring MVC 实践 标签 : Java与Web Converter Spring MVC的数据绑定并非没有任何限制, 有案例表明: Spring在如何正确绑定数据方面是杂乱无章的. 比如: S ...
- Spring MVC 实践笔记
1.了解 Maven 的用法:http://spring.io/guides/gs/maven/ .这篇英文非常详细的演示了 Maven 的用法,在命令行下执行.注意,运行Maven的时候,Maven ...
- JSR-303 Bean Validation 介绍及 Spring MVC 服务端验证最佳实践
任何时候,当要处理一个应用程序的业务逻辑,数据校验是你必须要考虑和面对的事情. 应用程序必须通过某种手段来确保输入参数在上下文来说是正确的. 分层的应用在很多时候,同样的数据验证逻辑会出现在不同的层, ...
- spring mvc xss html,note/SpringMvc防御XSS实践.md at master · yangc91/note · GitHub
SpringMvc防御XSS实践 项目在漏洞扫描时发现xss漏洞, 本以为是常见漏洞,网上有很多解决方案,应该能很快搞定,但实际上文章看了不少,却并未找到十分"顺手"的解决方案. ...
- 搭建Spring4+Spring MVC web工程的最佳实践
Spring是个非常非常非常优秀的java框架,主要是用它的IOC容器帮我们依赖注入和管理一些程序中的Bean组件,实现低耦合关联,最终提高系统可扩展性和可维护性,用它来辅助我们构建web工程将 ...
- springboot templates读取不到_整合spring mvc + mybatis,其实很简单,spring boot实践(5)
01 spring boot读取配置信息 02 多环境配置 03 处理全局异常 04 spring boot admin 主要通过spring boot整合spring mvc 以及mybatis实现 ...
- 看透 Spring MVC 源代码分析与实践 —— 俯视 Spring MVC
Spring MVC Spring MVC 之初体验 环境搭建 在 IDEA 中新建一个 web 项目,用 Maven 管理项目的话,在 pom.xml 中加入 Spring MVC 和 Servle ...
- 在Spring MVC中使用Apache Shiro安全框架
我们在这里将对一个集成了Spring MVC+Hibernate+Apache Shiro的项目进行了一个简单说明.这个项目将展示如何在Spring MVC 中使用Apache Shiro来构建我们的 ...
- Spring MVC防御CSRF、XSS和SQL注入攻击
本文说一下SpringMVC如何防御CSRF(Cross-site request forgery跨站请求伪造)和XSS(Cross site script跨站脚本攻击). 说说CSRF 对CSRF来 ...
最新文章
- python开发环境安装
- 简易数字频率计(verilog HDL设计)(2020维护版本)
- 洛谷 P1516 青蛙的约会
- 这是从云栖大会指挥部发回的现场报道
- 关于SAP CRM中间件系统搭建中遇到的一些问题
- Mysql对字符串去掉前后空格(trim)或者指定字符
- kernel module required key not available
- java 多重注解_Java注解-元数据、注解分类、内置注解和自定义注解
- loadrunner——关联
- C Programming Style 总结
- apple 苹果官方的demo 下载地址
- java 中rest,Java中的REST调用
- Servlet学习笔记
- 内存屏障 Memery Barrier
- JS将字符串转数组、转数字、转对象;将数组转字符串、转对象;将对象转数组、转字符串
- c#教程之通过数据绑定修改数据
- 桥接,NAT,Host Only的区别
- @components问题
- 怎样在php中制作电子相册,免费电子相册制作软件 怎样把照片制作成电子相册并加背景音乐?...
- oralc 中图片的存储与读取
热门文章
- 操作系统之进程管理:8、进程互斥的软件实现方法(单标志、双标志、Peterson)
- Linux系统编程11:进程入门之详细阐述进程的一些状态区分僵尸状态和孤儿状态动图演示
- 215.数组中的第K个最大元素/347. 前 K 个高频元素
- zmq 接口函数之 :zmq_socket_monitor - 注册一个监控回调函数
- Android Studio 3.1.4 报错Failed to find style 'coordinatorLayoutStyle' in current theme
- 【线性代数】2-5:逆(Inverse)
- c#计算 坐标点与坐标点之间的距离
- netty 发送 http请求
- createPattern() 自定义宽高
- start running 开始跑步减肥