SpringMVC
第一章 springmvc基础知识
1.1. 什么是springmvc
springmvc是spring框架的一个模块,springmvc和spring无需通过中间整合层进行整合。
springmvc是一个mvc的web框架,mvc是一个设计模式:model、view、control
<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" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd "> </bean>
1.2. springmvc框架原理
主要有前端控制器、处理器映射器、处理器适配器、视图解析器。
1.2.1. 前端控制器DispatcherServlet
接收请求,响应结果,相当于转发器,减少其他组件之间的耦合度。
web.xml: <!-- springmvc前端控制器 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- contextConfigLocation配置springmvc加载的配置文件 如果不配置contextConfigLocation,默认加载/WEB-INF/servlet名称-servlet.xml(springmvc-servlet.xml) --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <!-- 第一种:*.action,访问以*.action结尾的DispatcherServlet进行解析 第二种:/ 所有访问的地址都由DispatcherServlet进行解析,对于静态文件的解析需要配置不让DispatcherServlet解析 使用这种方法可以进行RESTful风格的url 第三种:/* 这样配置不对,使用这种配置,最终要转发到jsp页面时,仍然由DispatcherServlet解析jsp地址, 不能根据jsp页面找到Handler,会报错 --> <url-pattern>*.action</url-pattern> </servlet-mapping>
1.2.2. 处理器映射器HandlerMapping
根据请求url查找Handler
<!-- 处理器映射器 --> <!-- 根据bean的name进行查找Handler 将action的url配置在bean的name中 --> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" /> <bean name="/queryItem.action" class="cn.kai.ssm.controller.ItemsController1"/>
<!-- 简单映射器 --> <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <!-- <prop key="/queryItem.action">itemsController1</prop> --> <prop key="/queryItem1.action">itemsController1</prop> <prop key="/queryItem2.action">itemsController2</prop> </props> </property> </bean> <bean name="itemsController1" class="cn.kai.ssm.controller.ItemsController1"/> <bean name="itemsController2" class="cn.kai.ssm.controller.ItemsController2"/>
<!--注解映射器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> <!-- 注解的handler --> <bean class="cn.kai.ssm.controller.ItemsController3"/>
@Controller
public class ItemsController3{
@RequestMapping("/queryItem")
public ModelAndView queryItem(HttpServletRequest request, HttpServletResponse response) {
1.2.3. 处理器适配器handlerAdapter
按照特定规则去执行Handler
<!-- 处理器适配器
所有处理器适配器都实现HandlerAdapter接口,controller需要实现Controller
-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!-- controller需要实现HttpRequestHandler -->
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>
<!--注解适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
<!-- 使用 mvc:annotation-driven代替上边注解映射器和注解适配器配置
mvc:annotation-driven默认加载很多的参数绑定方法,
比如json转换解析器就默认加载了,如果使用mvc:annotation-driven不用配置上边的RequestMappingHandlerMapping和RequestMappingHandlerAdapter
实际开发时使用mvc:annotation-driven
-->
<mvc:annotation-driven></mvc:annotation-driven>
1.2.4. 处理器Handler
编写Handler时按照HandlerAdapter的要求,适配器才可以正确执行handler,需要程序员开发。
<bean name="itemsController1" class="cn.kai.ssm.controller.ItemsController1"/>
1.2.5. 视图解析器View resolver
进行视图解析,根据逻辑视图名解析成真正的视图
<!-- 视图解析器 解析jsp解析,默认使用jstl标签,classpath下的jstl的包 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <!-- jsp路径前缀 --> <property name="prefix" value="/WEB-INF/jsp/"/> <!-- jsp路径后缀 --> <property name="suffix" value=".jsp"/> </bean>
1.2.6. 视图View
view是一个接口,实现类支持不同的view类型jsp、freemarker、pdf...需要程序员开发。
1.3. springmvc注解开发
常用注解:
<!--注解映射器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<!--注解适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
参数绑定(简单类型、pojo、集合类型)
自定义参数绑定
对标记@Controller类中标识有@RequestMapping的方法进行映射。在@RequestMapping里边定义映射的url。使用注解的映射器不用在xml中配置url和Handler的映射关系。
注解处理器适配器和注解的处理器映射器是配对使用。理解为不能使用非注解映射器进行映射。
1.4. springmvc 和struts2区别
1、springmvc基于方法开发的,struts2基于类开发的。
2、springmvc可以进行单例开发,并且建议使用单例开发,struts2通过类的成员变量接收参数,无法使用单例,只能使用多例。
经过实际测试,struts2速度慢,在于使用struts标签,如果使用struts建议使用jstl。
第二章 springmvc整合mybatis
2.1. 事务控制
2.1.1. 注解式事务
spring+mybatis 事务配置:
<!-- 定义事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!--使用注释事务 -->
<tx:annotation-driven transaction-manager="transactionManager" />
spring+hibernate 事务配置:
<!-- 事务管理器配置,单数据源事务 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- 使用annotation定义事务 --> <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
@Transactional:
把这个注解放在类名称上面了,这样你配置的这个@Transactional 对这个类中的所有public方法都起作用
@Transactional 方法方法名上,只对这个方法有作用,同样必须是public的方法
事务的传播性:@Transactional(propagation=Propagation.REQUIRED)
事务的超时性:@Transactional(timeout=30) //默认是30秒
事务的隔离级别:@Transactional(isolation = Isolation.READ_UNCOMMITTED)
回滚:
指定单一异常类:@Transactional(rollbackFor=RuntimeException.class)
指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, Exception.class})
该属性用于设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚。
要想所有异常都回滚,要加上 @Transactional( rollbackFor={Exception.class,其它异常})
@Transactional(rollbackFor=Exception.class) //指定回滚,遇到异常Exception时回滚
只读:@Transactional(readOnly=true)
在spring配置文件中引入<tx:>命名空间:xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
2.1.2. AOP的方式实现事务的配置
<!-- 定义事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 下面使用aop切面的方式来实现 --> <tx:advice id="TestAdvice" transaction-manager="transactionManager"> <!--配置事务传播性,隔离级别以及超时回滚等问题 --> <tx:attributes> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="del*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="*" rollback-for="Exception" /> </tx:attributes> </tx:advice> <aop:config> <!--配置事务切点 --> <aop:pointcut id="services" expression="execution(* com.website.service.*.*(..))" /> <aop:advisor pointcut-ref="services" advice-ref="TestAdvice" /> </aop:config>
在spring 配置文件中引入:xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
tx:attribute标签所配置的是作为事务的方法的命名类型。 如<tx:method name="save*" propagation="REQUIRED"/> 其中*为通配符,即代表以save为开头的所有方法,即表示符合此命名规则的方法作为一个事务。propagation="REQUIRED"代表支持当前事务,如果当前没有事务,就新建一个事务。
aop:pointcut标签配置参与事务的类,由于是在Service中进行数据库业务操作,配的应该是包含那些作为事务的方法的Service类。
expression="execution(* com.test.testAda.test.model.service.*.*(..))"
其中第一个*代表返回值,第二*代表service下子包,第三个*代表方法名,“(..)”代表方法参数。
2.2. 乱码
POST:
<!-- 提交 数据乱码处理 --> <filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
GET:
new String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")
2.3. @RequestMapping
URL路径映射
@RequestMapping(value="/item")或@RequestMapping("/item")
value的值是数组,可以将多个url映射到同一个方法
窄化请求映射
@RequestMapping放在类名上边,设置请求前缀
@RequestMapping("/item")
@RequestMapping放在方法名上边,如下:
@RequestMapping("/queryItemsList ")
访问地址为:/item/queryItemsList
2.4. 参数绑定
注解适配器对RequestMapping标记的方法进行适配,对方法中的形参会进行参数绑定,早期springmvc采用PropertyEditor(属性编辑器)进行参数绑定将request请求的参数绑定到方法形参上,3.X之后springmvc就开始使用Converter进行参数绑定。
默认支持的参数类型:HttpServletRequest、HttpServletResponse、HttpSession、Model/ModelMap
2.4.1. 简单类型
整型,字符串,单精度/双精度,布尔型
@RequestParam常用于处理简单类型的绑定:
public String editItem(@RequestParam(value="item_id",required=true) String id) {
}
value:参数名字
required:是否必须,默认是true
defaultValue:默认值
多个参数需要多个@RequestParam
2.4.2. 简单pojo
将pojo对象中的属性名于传递进来的属性名对应,如果传进来的参数名称和对象中的属性名称一致则将参数值设置在pojo对象中
<input type="text" name="name"/>
<input type="text" name="price"/>
public String editItemSubmit(Items items)throws Exception
2.4.3. 自定义参数绑定
public class DateFormatConverters implements Converter<String, Date>{
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
<!-- 自定义参数绑定 --> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="converters"> <!-- 需要绑定的列表 --> <list> <!-- 日期格式绑定 --> <bean class="cn.kai.sm.controller.converters.DateFormatConverters"/> </list> </property> </bean>
<!--注解适配器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> <property name="webBindingInitializer" ref="customBinder"></property> </bean>
<!-- 自定义webBinder -->
<bean id="customBinder"
class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="conversionService" ref="conversionService" />
</bean>
<!-- conversionService --> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <!-- 转换器 --> <property name="converters"> <list> <bean class="cn.kai.sm.controller.converters.DateFormatConverters"/> </list> </property> </bean>
第三章 springmvc高级应用
3.1. 参数绑定
3.1.1. 包装类型pojo参数绑定
商品名称:<input type="text" name="items.name" />
items 要和包装类中属性一致
// 查询商品列表
@RequestMapping(value = "/queryItemsList")
public ModelAndView queryItemsList(ItemsQueryVo itemsQueryVo) throws Exception
3.1.2. 数组绑定
<input type="checkbox" name="items_id" value="${item.id }"/>
function deleteItems(){
document.itemsForm.action="${pageContext.request.contextPath }/items/deleteItemsList.action"
document.itemsForm.submit();
}
//批量删除商品信息
@RequestMapping("/deleteItemsList")
public String deleteItemsList(Integer[] items_id) throws Exception{
//处理删除
return "success";
}
3.1.3. list绑定
public class ItemsQueryVo {
public List<Items> itemsList;
<td><input name="itemsList[${status.index }].name" value="${item.name }"/></td>
<td><input name="itemsList[${status.index }].price" value="${item.price }"/></td>
//批量修改信
@RequestMapping("/updateItemsList")
public String updateItemsList(ItemsQueryVo itemsQueryVo) throws Exception{
3.1.4. map绑定
public class ItemsQueryVo {
private Map<String, String> itemsMap;
<input type="text" name="itemsMap['name'] " value="test"/>
<input type="text" name="itemsMap['price'] " value="1000"/>
@RequestMapping("/updateItemsList")
public String updateItemsList(ItemsQueryVo itemsQueryVo) throws Exception{
Map<String,String> itemsMap = itemsQueryVo.getItemsMap();
3.2. 数据回显
提交后,如果出现错误,将刚才提交的数据回显到刚才的提交页面:
- 如果页面属性名和传入参数属性名相同时自动回显
- 在参数前加@ModelAttribute("items"),其中items为页面所用属性名
@ModelAttribute("items") ItemsQueryVo itemsQueryVo
3. 利用model/ModelAndView
model.addAttribute("items", items);
modelAndView.addObject("itemsList", items);
4. @ModelAttribute("itemsType")
//商品类型 @ModelAttribute("itemsType") public Map<String,String> getItemsType(){ Map<String,String> itemsType = new HashMap<String,String>(); itemsType.put("01", "日用"); itemsType.put("02", "家电"); return itemsType; }
3.3. springmvc校验
3.3.1. 配置校验器
方法一:
<!-- 校验错误信息配置文件 --> <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <!-- 资源文件名 --> <property name="basenames"> <list> <value>classpath:CustomValidationMessages</value> </list> </property> <!-- 资源文件编码格式 --> <property name="fileEncodings" value="utf-8" /> <!-- 对资源文件内容缓存时间,单位秒 --> <property name="cacheSeconds" value="120" /> </bean>
<!--校验器注入-->
<mvc:annotation-driven conversion-service="conversionService" validator="validator"></mvc:annotation-driven>
方法二:
<!-- 自定义webBinder --> <bean id="customBinder" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer"> <property name="validator" ref="validator" /> </bean> <!-- 注解适配器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> <property name="webBindingInitializer" ref="customBinder"></property> </bean>
3.3.2. 注解的方法添加校验规则
@Size(min = 1,max = 30,message = "{items.name.length.error}")
private String name;
@NotNull(message = "{items.createtime.isNull}")
private Date createtime;
3.3.3. CustomValidationMessages.properties
#validator message
items.name.length.error=商品名的长度为(1,30)个字符
items.createtime.isNull=商品生成日期不能为空
3.3.4. 捕获校验错误信息
public String updateItems(Model model,Integer id,@Validated Items items,BindingResult result) throws Exception { if (result.hasErrors()) { List<ObjectError> errors = result.getAllErrors(); for (ObjectError error:errors) { System.out.println(error.getDefaultMessage()); } model.addAttribute("itemsErrors", errors); return "items/editItems"; }
@Validated和BindingResult bindingResult是成对出现,并且形参顺序是固定,BindingResult在紧接着的pojo类后面
3.3.5. 页面显示
<c:if test="${itemsErrors!=null}"> <c:forEach items="${itemsErrors}" var="error"> ${error.defaultMessage } <br/> </c:forEach> </c:if>
3.3.6. 分组校验
public interface ValidGroup1 {
//对不同的校验进行分组,不需要实现类
}
归纳为ValidGroup1校验:
@Size(min = 1,max = 30,message = "{items.name.length.error}",groups = {ValidGroup1.class})
private String name;
只校验ValidGroup1的校验:
@Validated(value = {ValidGroup1.class}) Items items,BindingResult result
3.4. 异常处理
3.4.1. 处理思路
3.4.2. 自定义异常
public class ParamVlidationException extends Exception { private static final long serialVersionUID = -3142200140109183920L; public String message; public ParamVlidationException(String messgae) { super(messgae); this.message = messgae; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
3.4.3. 全局异常处理器
实现HandlerExceptionResolver接口:
public class OverallExceptionResolver implements HandlerExceptionResolver { List customException; @Override public ModelAndView resolveException(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception ex) { ParamVlidationException paramVlidationException = null; if (ex instanceof ParamVlidationException) { paramVlidationException = (ParamVlidationException) ex; } else { paramVlidationException = new ParamVlidationException("未定义异常!"); } String message = paramVlidationException.getMessage(); ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("message", message); modelAndView.setViewName("error"); return modelAndView; } }
3.4.4. springmvc.xml配置全局异常处理器
只要实现HandlerExceptionResolver接口,会加载且仅加载一个全局异常处理器
<bean class="cn.kai.sm.exception.OverallExceptionResolver"/>
3.5. 上传图片
form中提交enctype="multipart/form-data"的数据时,需要springmvc对multipart类型的数据进行解析
<!-- 文件上传 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置上传文件的最大尺寸为5MB -->
<property name="maxUploadSize">
<value>5242880</value>
</property>
</bean>
创建图片虚拟目录存储图片
tomcat界面添加:
配置文件添加:
在tomcat下conf/server.xml中添加:
<Context docBase=""E:\workspace\pic_temp" path="/pic" reloadable="false"/>
public String updateItems(Model model,Integer id,@Validated(value = {ValidGroup1.class}) Items items, BindingResult result,MultipartFile items_pic) throws Exception if(items_pic!=null) { //图片原始名称 String originalFilename = items_pic.getOriginalFilename(); if(originalFilename!=null && originalFilename.length() > 0) { //图片物理存储地址 String pic_path = "E:\\workspace\\pic_temp\\"; //新图片名称 String newFileName = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf(".")); //创建新图片 File newfile = new File(pic_path+newFileName); //图片写入磁盘 items_pic.transferTo(newfile); items.setPic(newFileName); } }
<td>商品图片</td> <td> <c:if test="${items.pic !=null}"> <input type="hidden" name="pic" value="${items.pic}"/> <img src="/pic/${items.pic}" width=100 height=100/> <br/> </c:if> <input type="file" name="items_pic"/> </td>
3.6. json数据交互
3.6.1. 导入jar包
3.6.2. 配置json转换器
<!--注解适配器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> <property name="messageConverters"> <list> <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean> </list> </property> </bean>
如果使用<mvc:annotation-driven /> 则不用定义上边的内容
3.6.3. 页面
function jsonRequest(){ $.ajax({ type:"POST", url:"${pageContext.request.contextPath }/jsonRequest.action", contentType:"application/json;charset=utf-8", data:'{"id":"1","name":"笔记本","price":5000}', success:function(data){ alert(data.id+":"+data.name+":"+data.price); } }); }
function keyValueRequest(){ $.ajax({ type:"POST", url:"${pageContext.request.contextPath }/keyValueRequest.action", //contentType:"application/json;charset=utf-8", 默认为key/value data:'id=1&name=笔记本&price=5000', success:function(data){ alert(data.id+":"+data.name+":"+data.price); } }); }
3.6.4. Controller
json请求,json输出
//@RequestBody 将json格式请求转换为pojo实体类Items //@ResponseBody 将pojo实体类items转换为json格式输出 @RequestMapping("/jsonRequest") public @ResponseBody Items jsonRequest(@RequestBody Items items) { return items; }
key/value请求,json输出
//@ResponseBody 将pojo实体类items转换为json格式输出 @RequestMapping("/keyValueRequest") public @ResponseBody Items keyValueRequest(Items items) { return items; }
3.7. RESTful支持
3.7.1. RESTful架构
结构清晰、符合标准、易于理解、扩展方便
非REST的url:http://...../queryItems.action?id=001&type=T01
REST的url风格:http://..../items/001
特点:url简洁,将参数通过url传到服务端
例:
配置前端控制器:
<!-- springmvc前端控制器,RESTful配置 --> <servlet> <servlet-name>springmvc_rest</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- contextConfigLocation配置springmvc加载的配置文件 如果不配置contextConfigLocation,默认加载/WEB-INF/servlet名称-servlet.xml(springmvc-servlet.xml) --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/springmvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc_rest</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
Controller:
//查询商品信息 //返回json格式 @RequestMapping("/queryItemsById/{id}") public @ResponseBody Items queryItemsById(@PathVariable("id") Integer itemsId) throws Exception { Items items = itemsService.findItemsById(itemsId); return items; }
@RequestMapping(value="/queryItemsById/{id}"):{×××}占位符,请求的URL可以是“/queryItemsById/1”或“/queryItemsById/2”,通过在方法中使用@PathVariable获取{×××}中的×××变量。
@PathVariable用于将请求URL中的模板变量映射到功能处理方法的参数上。
如果RequestMapping中表示为"/ queryItemsById /{id}",id和形参名称一致,@PathVariable不用指定名称。
静态资源解析:
<!-- 静态资源解析 -->
<!-- <mvc:default-servlet-handler/> -->
<mvc:resources location="/js/" mapping="/js/**"/>
访问:
3.8. 拦截器
3.8.1. 定义拦截器,实现HandlerInterceptor接口
比如:统一日志处理拦截器,需要该拦截器preHandle一定要放行,且将它放在拦截器链接中第一个位置。
比如:登陆认证拦截器,放在拦截器链接中第一个位置。权限校验拦截器,放在登陆认证拦截器之后。(因为登陆通过后才校验权限)
3.8.2. 拦截器配置
类似全局的拦截器:
<!-- 配置全局拦截器 需要实现接口HandlerInterceptor --> <mvc:interceptors> <!-- 登陆拦截器 --> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="cn.kai.sm.interceptor.LoginInterceptor"/> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="cn.kai.sm.interceptor.HandlerInterceptor1"/> </mvc:interceptor> </mvc:interceptors>
针对某种mapping配置拦截器:
<!-- 针对某种mapping配置拦截器 --> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"> <property name="interceptors"> <list> <ref bean="loginInterceptor"/> <ref bean="handlerInterceptor2"/> </list> </property> </bean> <bean id="loginInterceptor" class="cn.kai.sm.interceptor.LoginInterceptor"/> <bean id="handlerInterceptor1" class="cn.kai.sm.interceptor.HandlerInterceptor1"/>
3.8.3. Controller
@Controller public class LoginController { // login @RequestMapping("/userLogin") public String userLogin(HttpSession session, String username, String password) { // service登陆逻辑 // ... session.setAttribute("username", username); return "redirect:/items/queryItemsList.action"; } // logout @RequestMapping("/userLogout") public String userLogout(HttpSession session) { // service退出逻辑 // ... session.invalidate(); return "redirect:/items/queryItemsList.action"; } }
3.8.4. LoginInterceptor
public class LoginInterceptor implements HandlerInterceptor { //进入handler之前执行 //用于身份认证、身份授权 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception { String url = request.getRequestURI(); //不需要登陆就能访问的地址不需要拦截 if( url.indexOf("userLogin.action") > 0 ) { return true; } String username = (String) request.getSession().getAttribute("username"); if(username!=null) { return true; } request.getRequestDispatcher("/WEB-INF/jsp/userLogin.jsp").forward(request, response); //false表示拦截,不向下执行 //true表示不拦截 return false; } //进入handler之后,返回ModelAndView之前 //应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图 @Override public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception { } //执行handler完成之后执行 //应用场景:统一异常处理,统一日志处理 @Override public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception { } }
汇总: