说明:所有代码调式的环境:开发环境idea,jdk7,tomcat8.5.27,数据库MySQL5.1,spring3.2
SpringMVC
1、什么是SpringMVC?
- springmvc是spring框架的一个模块,springmvc和spring无需通过中间整合层进行整合。
- springmvc是一个基于mvc的web框架。
- mvc
- mvc在b/s系统 下的应用:
- springMVC框架
框架执行流程
- 1、用户发送请求至前端控制器DispatcherServlet
- 2、DispatcherServlet收到请求调用HandlerMapping处理器映射器。
- 3、处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
- 4、DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
- 5、执行处理器(Controller,也叫后端控制器)。
- 6、Controller执行完成返回ModelAndView
- 7、HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
- 8、DispatcherServlet将ModelAndView传给ViewReslover视图解析器
- 9、ViewReslover解析后返回具体View
- 10、DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)。
- 11、DispatcherServlet响应用户
- mvc在b/s系统 下的应用:
2、SpringMVC框架原理(掌握)
- 前端控制器DispatcherServlet(不需要程序员开发)
- 作用接收请求,响应结果,相当于转发器,中央处理器。有了DispatcherServlet减少了其它组件之间的耦合度。
- 处理器映射器HandlerMapping(不需要程序员开发)
- 作用:根据请求的url查找Handler
- 处理器适配器HandlerAdapter
- 作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler
- 处理器Handler (需要程序员开发)
- 注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler
- 视图解析器View resolver(不需要程序员开发)
- 作用:进行视图解析,根据逻辑视图名解析成真正的视图(view)
- 视图View (需要程序员开发)
- View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf…)
3、SpringMVC入门程序
- 需求
- 以案例作为驱动。springmvc和mybaits使用一个案例(商品订单管理)
- 功能需求:商品列表查询
- 环境准备
- 数据库还是使用mybatis的数据。(mybatis的由浅入深教程开篇有下载地址)
- java环境: jdk(9),ide(idea)
- jar包: spring所有jar(一定包括spring-webmvc.RELEASE.jar)这个jar包,版本的话个人认为当前版本的上一个大版本的最后一个小版本更合适,因为这样实时性和稳定性都不会太差
- 入门程序的目的: 对前端控制器,处理器映射器,处理器适配器,视图解析器的加深学习
接下来开始写程序:
- 创建java web项目,引入相应的jar包打开数据库
- 在web.xml中配置前端控制器
- classpath下的springmvc.xml中配置处理器适配器
- 开发Handler
- 视图编写
- Handler
- 配置处理器映射器
- 配置视图解析器
部署调试:
- 正常调试:
- 异常调试:
处理器映射器根据url找不到Handler,报下边的错误。说明url错误。
接下来我们修改jsp视图的地址
处理器映射器根据url找到了Handler,转发的jsp页面找到,报下边的错误,说明jsp页面地址错误了。注意WEB-INF被修改为WEB-IF
非注解的处理器映射器和处理器适配器
- 非注解处理器映射器:
- org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
- 另一个映射器:
- org.springframework.web.servlet.handler.SimpleUrlHandlerMapping
修改springmvc.xml文件如下:
- 非注解处理器映射器:
<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 ">
<!-- 配置Handler -->
<bean id="itemsController1" name="/queryItems.action" class="cn.itcast.ssm.controller.ItemsController1" />
<!--配置另一个handler-->
<bean id="itemsController2" class="cn.itcast.ssm.controller.ItemsController2" />
<!-- 处理器映射器 将bean的name作为url进行查找 ,需要在配置Handler时指定beanname(就是url)
所有的映射器都实现 HandlerMapping接口。
-->
<bean
class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
<!-- 处理器适配器 所有处理器适配器都实现 HandlerAdapter接口 -->
<bean
class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
<!--简单url映射 -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<!-- 对itemsController1进行url映射,url是/queryItems1.action -->
<prop key="/queryItems1.action">itemsController1</prop>
<prop key="/queryItems2.action">itemsController1</prop>
</props>
</property>
</bean>
<!-- 视图解析器
解析jsp解析,默认使用jstl标签,classpath下的得有jstl的包
-->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
</bean>
</beans>
测试:
由此可见:多个映射器可以并存,前端控制器判断url能让哪些映射器映射,就让正确的映射器处理
- 非注解处理器适配器
- org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter
要求编写的Handler实现 Controller接口。 - org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter
要求编写的Handler实现 HttpRequestHandler接口。
在controller包下新增ItemsController2.java
- org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter
package cn.itcast.ssm.controller;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.servlet.ModelAndView;
import cn.itcast.ssm.po.Items;
public class ItemsController2 implements HttpRequestHandler {
@Override
public void handleRequest(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
//调用service查找 数据库,查询商品列表,这里使用静态数据模拟
List<Items> itemsList = new ArrayList<Items>();
//向list中填充静态数据
Items items_1 = new Items();
items_1.setName("联想笔记本");
items_1.setPrice(6000f);
items_1.setDetail("ThinkPad T430 联想笔记本电脑!");
Items items_2 = new Items();
items_2.setName("苹果手机");
items_2.setPrice(5000f);
items_2.setDetail("iphone6苹果手机!");
itemsList.add(items_1);
itemsList.add(items_2);
//设置模型数据
request.setAttribute("itemsList", itemsList);
//设置转发的视图
request.getRequestDispatcher("/WEB-INF/jsp/items/itemsList.jsp").forward(request, response);
//使用此方法可以通过修改response,设置响应的数据格式,比如响应json数据
/*
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json串");*/
}
}
- DispatcherSerlvet.properties
前端控制器从上边的文件中加载处理映射器、适配器、视图解析器等组件,如果不在springmvc.xml中配置,使用默认加载的。 注解的处理器映射器和处理器适配器
在spring3.1之前使用
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping注解映射器。在spring3.1之后使用
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping注解映射器。在spring3.1之前使用
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter注解适配器。在spring3.1之后使用
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> -->
开发注解Handler
package cn.itcast.ssm.controller;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import cn.itcast.ssm.po.Items;
//使用Controller标识 它是一个控制器
@Controller
public class ItemsController3 {
//注解开发Handler
//商品查询列表
//@RequestMapping实现 对queryItems方法和url进行映射,一个方法对应一个url
//一般建议将url和方法写成一样
@RequestMapping("/queryItems")
public ModelAndView queryItems()throws Exception{
//调用service查找 数据库,查询商品列表,这里使用静态数据模拟
List<Items> itemsList = new ArrayList<Items>();
//向list中填充静态数据
Items items_1 = new Items();
items_1.setName("联想笔记本3");
items_1.setPrice(6000f);
items_1.setDetail("ThinkPad T430 联想笔记本电脑!3");
Items items_2 = new Items();
items_2.setName("苹果手机3");
items_2.setPrice(5000f);
items_2.setDetail("iphone6苹果手机!3");
itemsList.add(items_1);
itemsList.add(items_2);
//返回ModelAndView
ModelAndView modelAndView = new ModelAndView();
//相当 于request的setAttribut,在jsp页面中通过itemsList取数据
modelAndView.addObject("itemsList", itemsList);
//指定视图
//下边的路径,如果在视图解析器中配置jsp路径的前缀和jsp路径的后缀,修改为
//modelAndView.setViewName("/WEB-INF/jsp/items/itemsList.jsp");
//上边的路径配置可以不在程序中指定jsp路径的前缀和jsp路径的后缀
modelAndView.setViewName("items/itemsList");
return modelAndView;
}
//定义其它的方法
//商品添加
//商品修改
}
- 在spring容器中加载Handler
<!-- 对于注解的Handler可以单个配置
实际开发中建议使用组件扫描
-->
<!-- <bean class="cn.itcast.ssm.controller.ItemsController3" /> -->
<!-- 可以扫描controller、service、...
这里让扫描controller,指定controller的包
-->
<context:component-scan base-package="cn.itcast.ssm.controller"></context:component-scan>
部署测试
入门总结:前端控制器配置:
- 第一种:*.action,访问以.action结尾 由DispatcherServlet进行解析
- 第二种:/,所以访问的地址都由DispatcherServlet进行解析,对于静态文件的解析需要配置不让DispatcherServlet进行解析
使用此种方式可以实现 RESTful风格的url
处理器映射器:
- 非注解处理器映射器(了解)
- 注解的处理器映射器(掌握)
- 对标记@Controller类中标识有@RequestMapping的方法进行映射
- 在@RequestMapping里边定义映射的url。使用注解的映射器不用在xml中配置url和Handler的映射关系。
- 处理器适配器:
- 非注解处理器适配器(了解)
- 注解的处理器适配器(掌握)
- 注解处理器适配器和注解的处理器映射器是配对使用。理解为不能使用非注解映射器进行映射。
入门程序源代码下载 密码: msiy
4、SpringMVC和Mybatis整合(掌握)
- 需求:使用springmvc和mybatis完成商品列表查询。
- ssm系统架构
- 整合思路
- 第一步:整合dao层
- mybatis和spring整合,通过spring管理mapper接口。
- 使用mapper的扫描器自动扫描mapper接口在spring中进行注册。
- 第二步:整合service层
- 通过spring管理 service接口。
- 使用配置方式将service接口配置在spring配置文件中。
- 实现事务控制。
- 第三步:整合springmvc
- 由于springmvc是spring的模块,不需要整合。
- 第一步:整合dao层
开发环境
- 基本和入门程序的差不多,只是jar包的不同
- 所需要的jar包:
- springmvc3.2的jar包
- spring3.2的jar包
- 数据库驱动包:mysql5.1
- mybatis的jar包
- mybatis和spring整合包
- log4j包
- dbcp数据库连接池包
- jstl包
之后我会上传源码。
- 开发
- 项目目录
- 整合dao
- 配置sqlMapConfig.xml
- 配置applicationContext-dao.xml
- 数据源,SqlSessionFactory,mapper扫描器
- 逆向工程生成po类及mapper(单表增删改查)
- ItemsMapperCustom.xml和ItemsMapperCustom.java
- 整合service
- 定义service接口
- 在spring容器配置service(applicationContext-service.xml)
- 事务控制(applicationContext-transaction.xml)
- 整合springmvc
- 创建springmvc.xml文件,配置处理器映射器、适配器、视图解析器。
- 配置前端控制器
- 编写controller
- 编写jsp
- 加载spring容器(web.xml中)
- 项目目录
5、SpringMVC注解开发
- 常用的注解学习
- @controller
- 这个注解必须要加,作用标识类是一个Handler处理器。
- @RequestMapping
- URL映射定义controller方法对应的URL,进行处理器映射使用。
- 窄化请求映射
- 限制http请求方法出于安全性考虑,对http的链接进行方法限制。如果限制请求为post方法,进行get请求,报错:
- @RequestParam
- 通过@RequestParam对简单类型的参数进行绑定。
- 如果不使用@RequestParam,要求request传入参数名称和controller方法的形参名称一致,方可绑定成功。
- 如果使用@RequestParam,不用限制request传入参数名称和controller方法的形参名称一致。
- 通过required属性指定参数是否必须要传入,如果设置为true,没有传入参数,报下边错误:
- @controller
controller方法的返回值
- 返回ModelAndView
- 需要方法结束时,定义ModelAndView,将model和view分别进行设置。
- 返回string
- 如果controller方法返回string:
- 表示返回逻辑视图名。真正视图(jsp路径)=前缀+逻辑视图名+后缀
- 表示redirect重定向
- 商品修改提交后,重定向到商品查询列表。
- redirect重定向特点:浏览器地址栏中的url会变化。修改提交的request数据无法传到重定向的地址。因为重定向后重新进行request(request无法共享)
- 表示forward页面转发
- 通过forward进行页面转发,浏览器地址栏url不变,request可以共享。
- 通过forward进行页面转发,浏览器地址栏url不变,request可以共享。
- 表示返回逻辑视图名。真正视图(jsp路径)=前缀+逻辑视图名+后缀
- 如果controller方法返回string:
返回void
在controller方法形参上可以定义request和response,使用request或response指定响应结果:
使用request转向页面,如下:
- request.getRequestDispatcher(“页面路径”).forward(request, response);
也可以通过response页面重定向:
- response.sendRedirect(“url”)
也可以通过response指定响应结果,例如响应json数据如下:
- response.setCharacterEncoding(“utf-8”);
response.setContentType(“application/json;charset=utf-8”);
response.getWriter().write(“json串”);
- response.setCharacterEncoding(“utf-8”);
- 返回ModelAndView
参数绑定(简单类型,pojo)
- spring参数绑定过程
- 从客户端请求key/value数据,经过参数绑定,将key/value数据绑定到controller方法的形参上。
- springmvc中,接收页面提交的数据是通过方法形参来接收。而不是在controller类定义成员变更接收!!!!
- 默认支持的类型
直接在controller方法形参上定义下边类型的对象,就可以使用这些对象。在参数绑定过程中,如果遇到下边类型直接进行绑定。
- HttpServletRequest
通过request对象获取请求信息 - HttpServletResponse
通过response处理响应信息 - HttpSession
通过session对象得到session中存放的对象 - Model/ModelMap
model是一个接口,modelMap是一个接口实现 。
作用:将model数据填充到request域。
- HttpServletRequest
- pojo绑定
- 页面中input的name和controller的pojo形参中的属性名称一致,将页面中数据绑定到pojo
- 页面定义:
- controller的pojo形参的定义:
- spring参数绑定过程
自定义参数绑定实现日期类型绑定(掌握)
对于controller形参中pojo对象,如果属性中有日期类型,需要自定义参数绑定。将请求日期数据串传成 日期类型,要转换的日期类型和pojo中日期属性的类型保持一致
所以自定义参数绑定将日期串转成java.util.Date类型。
需要向处理器适配器中注入自定义的参数绑定组件。自定义日期类型绑定:
配置:
6、SpringMVC和Struts2的区别
- pringmvc基于方法开发的,struts2基于类开发的。
- springmvc将url和controller方法映射。映射成功后springmvc生成一个Handler对象,对象中只包括了一个method。方法执行结束,形参数据销毁。springmvc的controller开发类似service开发。
- springmvc可以进行单例开发,并且建议使用单例开发,struts2通过类的成员变量接收参数,无法使用单例,只能使用多例。
- 经过实际测试,struts2速度慢,在于使用struts标签,如果使用struts建议使用jstl。
7、SpringMVC参数绑定(集合类型)
- 批量删除
- 关键:将页面选择(多选)的商品id,传到controller方法的形参,方法形参使用数组接收页面请求的多个商品id。
- 关键:将页面选择(多选)的商品id,传到controller方法的形参,方法形参使用数组接收页面请求的多个商品id。
- list绑定
- controller方法定义:
1、进入批量商品修改页面(页面样式参考商品列表实现)
2、批量修改商品提交:使用List接收页面提交的批量数据,通过包装pojo接收,在包装pojo中定义list<>属性
- controller方法定义:
- map绑定
- 也通过在包装pojo中定义map类型属性。
- 在包装类中定义Map对象,并添加get/set方法,action使用包装对象接收。
包装类中定义Map对象如下:
Public class QueryVo {
private Map<String, Object> itemInfo = new HashMap<String, Object>();
//get/set方法..
}
页面定义如下:
<tr>
<td>学生信息:</td>
<td>
姓名:<inputtype="text"name="itemInfo['name']"/>
年龄:<inputtype="text"name="itemInfo['price']"/>
.. .. ..
</td>
</tr>
Contrller方法定义如下:
public String useraddsubmit(Model model,QueryVo queryVo)throws Exception{
System.out.println(queryVo.getStudentinfo());
}
8、SpringMVC数据回显
- 什么数据回显
提交后,如果出现错误,将刚才提交的数据回显到刚才的提交页面 - pojo数据回显方法
- 1、springmvc默认对pojo数据进行回显。
- pojo数据传入controller方法后,springmvc自动将pojo数据放到request域,key等于pojo类型(首字母小写)
- 使用@ModelAttribute指定pojo回显到页面在request中的key
- 2、@ModelAttribute还可以将方法的返回值传到页面
- 在商品查询列表页面,通过商品类型查询商品信息。
- 在controller中定义商品类型查询方法,最终将商品类型传到页面。
- 3、使用最简单方法使用model,可以不用@ModelAttribute
- 1、springmvc默认对pojo数据进行回显。
- 5.3简单类型数据回显
- 使用最简单方法使用model。
- model.addAttribute(“id”, id);
9、SpringMVC异常处理
- 异常处理思路
- 系统中异常包括两类:预期异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。
- 系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理,如下图:
springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统一异常处理。
- 自定义异常
- 对不同的异常类型定义异常类,继承Exception。需要时抛出此类异常
- 对不同的异常类型定义异常类,继承Exception。需要时抛出此类异常
- 全局异常开发处理
- 思路:
系统遇到异常,在程序中手动抛出,dao抛给service、service给controller、controller抛给前端控制器,前端控制器调用全局异常处理器。 - 全局异常处理器处理思路:
- 解析出异常类型
- 如果该 异常类型是系统 自定义的异常,直接取出异常信息,在错误页面展示
- 如果该 异常类型不是系统 自定义的异常,构造一个自定义的异常类型(信息为“未知错误”)
- springmvc提供一个HandlerExceptionResolver接口
- 思路:
@Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) {
//handler就是处理器适配器要执行Handler对象(只有method)
// 解析出异常类型
// 如果该 异常类型是系统 自定义的异常,直接取出异常信息,在错误页面展示
// String message = null;
// if(ex instanceof CustomException){
// message = ((CustomException)ex).getMessage();
// }else{
如果该 异常类型不是系统 自定义的异常,构造一个自定义的异常类型(信息为“未知错误”)
// message="未知错误";
// }
//上边代码变为
CustomException customException = null;
if(ex instanceof CustomException){
customException = (CustomException)ex;
}else{
customException = new CustomException("未知错误");
}
//错误信息
String message = customException.getMessage();
ModelAndView modelAndView = new ModelAndView();
//将错误信息传到页面
modelAndView.addObject("message", message);
//指向错误页面
modelAndView.setViewName("error");
return modelAndView;
}
错误页面
在springmvc.xml配置全局异常处理器
异常测试(抛出)
在controller、service、dao中任意一处需要手动抛出异常。
如果是程序中手动抛出的异常,在错误页面中显示自定义的异常信息,如果不是手动抛出异常说明是一个运行时异常,在错误页面只显示“未知错误”。- 在商品修改的controller方法中抛出异常
在service接口中抛出异常:
如果与业务功能相关的异常,建议在service中抛出异常。
与业务功能没有关系的异常,建议在controller中抛出。上边的功能,建议在service中抛出异常。
- 在商品修改的controller方法中抛出异常
9、SpringMVC上传图片
10、SpringMVC json数据交互
- 为什么要进行json数据交互
- json数据格式在接口调用中、html页面中较常用,json格式比较简单,解析还比较方便。
比如:webservice接口,传输json数据.
- json数据格式在接口调用中、html页面中较常用,json格式比较简单,解析还比较方便。
- springmvc进行json交互
1、请求json、输出json,要求请求的是json串,所以在前端页面中需要将请求的内容转成json,不太方便。
2、请求key/value、输出json。此方法比较常用。 - 环境准备
- 加载json转的jar包
- springmvc中使用jackson的包进行json转换(@requestBody和@responseBody使用下边的包进行json转),如下:
- springmvc中使用jackson的包进行json转换(@requestBody和@responseBody使用下边的包进行json转),如下:
- 加载json转的jar包
- 配置json转换器
- 在注解适配器中加入messageConverters
<!--注解适配器 -->
<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 /> 则不用定义上边的内容。-->
11、SpringMVC RESTful支持
什么是RESTful
- RESTful架构,就是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用
RESTful(即Representational State Transfer的缩写)其实是一个开发理念,是对http的很好的诠释。
- 1、对url进行规范,写RESTful格式的url
- 非REST的url:http://…../queryItems.action?id=001&type=T01
- REST的url风格:http://…./items/001
- 特点:url简洁,将参数通过url传到服务端
2、http的方法规范
- 不管是删除、添加、更新。。使用url是一致的,如果进行删除,需要设置http的方法为delete,同理添加。。。
- 后台controller方法:判断http方法,如果是delete执行删除,如果是post执行添加。
3、对http的contentType规范
- 请求时指定contentType,要json数据,设置成json格式的type。。
- 1、对url进行规范,写RESTful格式的url
12、SpringMVC拦截器
定义配置
拦截定义
- 定义拦截器,实现HandlerInterceptor接口。接口中提供三个方法。
public class HandlerInterceptor1 implements HandlerInterceptor { //进入 Handler方法之前执行 //用于身份认证、身份授权 //比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //return false表示拦截,不向下执行 //return true表示放行 return false; } //进入Handler方法之后,返回modelAndView之前执行 //应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图 @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } //执行Handler完成执行此方法 //应用场景:统一异常处理,统一日志处理 @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }
- 定义拦截器,实现HandlerInterceptor接口。接口中提供三个方法。
拦截配置
针对HandlerMapping配置:
springmvc拦截器针对HandlerMapping进行拦截设置,如果在某个HandlerMapping中配置拦截,经过该 HandlerMapping映射成功的handler最终使用该 拦截器。
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"> <property name="interceptors"> <list> <ref bean="handlerInterceptor1"/> <ref bean="handlerInterceptor2"/> </list> </property> </bean> <bean id="handlerInterceptor1" class="springmvc.intercapter.HandlerInterceptor1"/> <bean id="handlerInterceptor2" class="springmvc.intercapter.HandlerInterceptor2"/>
一般不推荐使用。
类似全局的拦截器
springmvc配置类似全局的拦截器,springmvc框架将配置的类似全局的拦截器注入到每个HandlerMapping中。
多拦截器测试
编写两个拦截器
两个拦截器都放行
HandlerInterceptor1…preHandle
HandlerInterceptor2…preHandle
HandlerInterceptor2…postHandle
HandlerInterceptor1…postHandle
HandlerInterceptor2…afterCompletion
HandlerInterceptor1…afterCompletion总结:
preHandle方法按顺序执行,
postHandle和afterCompletion按拦截器配置的逆向顺序执行。拦截器1放行,拦截器2不放行
HandlerInterceptor1…preHandle
HandlerInterceptor2…preHandle
HandlerInterceptor1…afterCompletion总结:
拦截器1放行,拦截器2 preHandle才会执行。拦截器2 preHandle不放行,拦截器2 postHandle和afterCompletion不会执行。
只要有一个拦截器不放行,postHandle不会执行。
拦截器1不放行,拦截器2不放行
HandlerInterceptor1…preHandle拦截器1 preHandle不放行,postHandle和afterCompletion不会执行。
拦截器1 preHandle不放行,拦截器2不执行。
小结
根据测试结果,对拦截器应用。
比如:统一日志处理拦截器,需要该 拦截器preHandle一定要放行,且将它放在拦截器链接中第一个位置。
比如:登陆认证拦截器,放在拦截器链接中第一个位置。权限校验拦截器,放在登陆认证拦截器之后。(因为登陆通过后才校验权限)
13、springmvc校验
- 校验理解
- 项目中,通常使用较多是前端的校验,比如页面中js校验。对于安全要求较高点建议在服务端进行校验。
- 服务端校验:
- 控制层conroller:校验页面请求的参数的合法性。在服务端控制层conroller校验,不区分客户端类型(浏览器、手机客户端、远程调用)
- 业务层service(使用较多):主要校验关键业务参数,仅限于service接口中使用的参数。
- 持久层dao:一般是不校验的。
- springmvc校验需求
- springmvc使用hibernate的校验框架validation(和hibernate没有任何关系)。
- 校验思路:
- 页面提交请求的参数,请求到controller方法中,使用validation进行校验。如果校验出错,将错误信息展示到页面。
- 具体需求:
- 商品修改,添加校验(校验商品名称长度,生产日期的非空校验),如果校验出错,在商品修改页面显示错误信息。
- 环境:
- 配置校验器
- 校验器注入到处理器适配器中
- 在pojo中添加校验规则
- 在ItemsCustom.java中添加校验规则:
- 在ItemsCustom.java中添加校验规则:
- CustomValidationMessages.properties文件
捕获校验错误信息
在需要校验的pojo前边添加@Validated,在需要校验的pojo后边添加BindingResult bindingResult接收校验出错信息注意:@Validated和BindingResult bindingResult是配对出现,并且形参顺序是固定的(一前一后)。
- 在页面显示校验错误信息
项目源码 密码: cyv3