17.4.10.7 非常处理

17.4.10.7.1.非常处理思路

系统中非常包括两类:预期非常和运行时非常RuntimeException,预期非常通过捕获非常从而获取非常信息,

jspjqueryjson项目SpringMVC进修笔记文本版四完结篇 Bootstrap

运行时非常RuntimeException紧张通过规范代码开拓、测试通过手段较少运行时非常发生。

系统的dao、service、controller涌现通过throws Exception向上抛出,末了由前端掌握器交由非常处理器进行非常处理。

总体思路:springmvc供应全局的非常处理器(一个别系只有一个非常处理器)进行统一非常处理。

17.4.10.7.2.自定义非常类

对不同的非常类型定义非常类,继续Exception。

package org.hxweb.web.ssm.exception;

/

@see 自定义非常:针对预期非常类,须要在系统中抛出此类非常提示信息

@author Administrator

/

public class CustomException extends Exception{

//非常提示信息

public String messge;

public CustomException(String message){

super(message);

this.messge = message;

}

public String getMessge() {

return messge;

}

public void setMessge(String messge) {

this.messge = messge;

}

}

17.4.10.7.3.全局非常处理器

思路:

系统碰着非常,在程序中手动抛出,dao抛给service,service抛给controller,controller抛给前段掌握器,前端掌握器调用全局非常处理器。

全局非常处理器处理思路:

解析出非常类型

如果该非常类型是系统自定义的非常,直接取出非常信息,在缺点页面显示。

如果该非常类型不是系统自定义的非常,布局一个自定义的非常类型(信息为“未知缺点”)。

springmvc供应一个HandlerExceptionResolver接口:

package org.hxweb.web.ssm.exception;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;

import org.springframework.web.servlet.HandlerExceptionResolver;

import org.springframework.web.servlet.ModelAndView;

/

@see 全局非常处理器

@author Administrator

/

public class CustomExceptionResolver implements HandlerExceptionResolver{

/

@see 全局非常处理

Handler:便是处理器适配器要实行的Handler工具(只有一个method方法)

ex:便是系统抛出的非常

/

@Override

public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,

Exception ex) {

//Handler:便是处理器适配器要实行的Handler工具(只有一个method方法)

//ex:便是系统抛出的非常

//解析出非常类型

//非常信息

/ String message=null;

//如果该非常类型是系统自定义的非常,直接取出非常信息,在缺点页面显示。

if(ex instanceof CustomException){

message = ((CustomException)ex).getMessge();

} else {

//如果该非常类型不是系统自定义的非常,布局一个自定义的非常类型(信息为“未知缺点”)。

message = "未知缺点";

}

/

CustomException customException = null;

//如果该非常类型是系统自定义的非常,直接取出非常信息,在缺点页面显示。

if(ex instanceof CustomException){

customException = (CustomException)ex;

} else {

//如果该非常类型不是系统自定义的非常,布局一个自定义的非常类型(信息为“未知缺点”)。

customException = new CustomException("未知缺点");

}

//非常提示信息

String message = customException.getMessge();

ModelAndView modelAndView = new ModelAndView();

//将非常提示信息传到页面

modelAndView.addObject("message", message);

//指向缺点页面

modelAndView.setViewName("error");

return modelAndView;

}

}

17.4.10.7.4.非常提示页面(error.jsp):

<%@ page language="java" contentType="text/html; charset=UTF-8"

pageEncoding="UTF-8"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>非常提示</title>

</head>

<body>

<font color="red">

${message }

</font>

</body>

</html>

17.4.10.7.5.在springmvc.xml中配置全局非常处理器

<!-- 全局非常处理器

只要实现了HandlerExceptionResolver接口,只要配置bean 就会起浸染

-->

<bean class="org.hxweb.web.ssm.exception.CustomExceptionResolver"></bean>

17.4.10.7.6.测试非常

在controller、service、dao中任意一处手动抛出非常。

如果非常是程序中手动抛出的,则在非常信息提示页面抛出自定义的非常信息,

如果非常不是手动抛出,则解释是运行时非常,在非常信息提示页面只显示"未知缺点.".

在商品修正的 controller 方法中手动抛出非常:

// 商品信息修正页面显示(展示)。

// @RequestMapping("/editItems")

// 限定 http 要求的方法 为post和get

@RequestMapping(value = "/editItems", method = { RequestMethod.POST, RequestMethod.GET })

// @RequestParam里边指定request传入参数名称和形参进行绑定。

// 通过required属性指定参数是否必须要传入

// 通过defaultValue可以设置默认值,如果id参数没有传入,将默认值和形参绑定。

public String editItems(Model model, @RequestParam(value = "id", required = true) Integer items_id)

throws Exception {

/

调用service来查找根据商品id从 数据库查询对应商品的信息

/

ItemsCustom itemsCustom = itemsService.findItemsById(items_id);

//判断商品是否为空,根据id没有查询到商品,抛出非常,提示用户商品信息不存在。

if (itemsCustom == null) {

throw new CustomException("修正的商品信息不存在!
");

}

// 为返回ModelAndView填充数据和指定视图

// ModelAndView modelAndView = new ModelAndView();

// 相称于request.setAtttibute,在jsp页面可以通过items获取商品修正信息展示

// modelAndView.addObject("itemsCustom", itemsCustom);

// 指定返回视图

// modelAndView.setViewName("/WEB-INF/jsp/items/editItems.jsp");

// modelAndView.setViewName("items/editItems");

// 通过形参中model将model数据传到页面

// 相称于modelAndView.addObject方法

model.addAttribute("itemsCustom", itemsCustom);

return "items/editItems";

}

在service中手动抛出非常:

@Override

public ItemsCustom findItemsById(Integer id) throws Exception {

//利用ItemsMapper查询数据库

Items items = ItemsMapper.selectByPrimaryKey(id);

//判断商品是否为空,根据id没有查询到商品,抛出非常,提示用户商品信息不存在。

if (items == null) {

throw new CustomException("修正的商品信息不存在!
");

}

如果与业务功能干系的非常,建议在 service 中手动抛出非常。

如果与业务功能无关的非常,建议在 controller 中手动抛出非常。

商品修正功能的非常抛出,建议在 service 中手动抛出非常。

判断商品是否为空,根据id没有查询到商品,抛出非常,提示用户商品信息不存在。

17.4.10.7.7. 上传图片

17.4.10.7.7.1 需求

在修正商品页面,添加上传商品图片功能。

17.4.10.7.7.2 springmvc中对多部件类型的解析

1.在页面form提交enctype="multipart/form-data"的数据时,须要springmvc对multipart类型的数据进行解析。

2.在springmvc.xml中配置multipart类型解析器

<!-- 文件上传 -->

<bean id="multipartResolver"

class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

<!-- 设置上传文件的最大尺寸为5MB -->

<property name="maxUploadSize">

<value>5242880</value>

</property>

</bean>

3.加入上传图片的jar包,这里通过maven依赖加入

<!-- 上传组件包 -->

<dependency>

<groupId>commons-fileupload</groupId>

<artifactId>commons-fileupload</artifactId>

<version>1.3.1</version>

</dependency>

<dependency>

<groupId>commons-io</groupId>

<artifactId>commons-io</artifactId>

<version>2.4</version>

</dependency>

<dependency>

<groupId>commons-codec</groupId>

<artifactId>commons-codec</artifactId>

<version>1.9</version>

</dependency>

<dependency>

<groupId>org.codehaus.jackson</groupId>

<artifactId>jackson-core-asl</artifactId>

<version>1.9.13</version>

</dependency>

<dependency>

<groupId>org.apache.bval</groupId>

<artifactId>bval-jsr</artifactId>

<version>1.1.1</version>

</dependency>

17.4.10.7.7.3 创建图片虚拟目录 存储图片

1.图片配置

2.修正tomcat conf/service.xml文件 添加如下内容

<Context docBase="F:\workspaces\Neon\ssmhxweb\src\main\webapp\upload\temp" path="/pic" reloadable="true"/></Host>

把稳:在图片虚拟目录中,一定要将图片目录分级创建(提高I/O性能),一样平常采取按日期(年、月、日)进行分级创建。

17.4.10.7.7.4 上传代码:

1.修正 controller 商品修正方法代码:

// 商品信息修正提交。

//在须要校验的pojo前边添加 @Validated表明,在须要校验的pojo后边添加 BindingResult bindingResult吸收校验出错提示信息

//把稳: @Validated表明和BindingResult bindingResult是配对涌现的,并且形参顺序是固定的(一前一后)。

//value={ValidGroupEdit.class} 指定利用ValidGroupEdit分组的校验

//@ModelAttribute(value="itemsCustom") 指定pojo回显到request域中的key

@RequestMapping("/editItemsSubmit")

public String editItemsSubmit(Model model,HttpServletRequest request, Integer id,

@Validated(value={ValidGroupEdit.class}) ItemsCustom itemsCustom,

BindingResult bindingResult,

MultipartFile items_pic //吸收商品图片

) throws Exception {

//获取校验缺点提示信息

if(bindingResult.hasErrors()){

//输出错误提示信息

List<ObjectError> allErrors = bindingResult.getAllErrors();

for(ObjectError objectError:allErrors){

System.out.println(objectError.getDefaultMessage());

}

//缺点提示信息传到页面

model.addAttribute("allErrors",allErrors);

//可以直策应用Model将回显的pojo直接回显到页面,key值与页面中的变量名称同等

model.addAttribute("itemsCustom", itemsCustom);

//大略数据类型直策应用model

//model.addAttribute("id", id);

//校验不通过跳转到当前页面(重新到商品修正页面)

return "items/editItems";

}

//上传图片

if (items_pic != null && items_pic.getOriginalFilename() != null && items_pic.getOriginalFilename().length()>0) {

//存储图片的物理路径

String picPath ="F:\\workspaces\\Neon\\ssmhxweb\\src\\main\\webapp\\upload\\temp\\";

//获取图片的原始文件名

String picOriginalFilename = items_pic.getOriginalFilename();

//新的图片名称: UUID随机串+原始图片的扩展名

String picNewFilename = UUID.randomUUID()+picOriginalFilename.substring(picOriginalFilename.lastIndexOf("."));

//图片新文件=存储图片的物理路径+新的图片名称

File picNewFile = new File(picPath+picNewFilename);

//将内存中的图片数据写入到磁盘

items_pic.transferTo(picNewFile);

//将新的商品图片名称写到itemsCustom中

itemsCustom.setPic(picNewFilename);

}

/

调用service来根据商品id更新数据库对应商品的信息

/

itemsService.updateItems(id, itemsCustom);

// 重定向到商品查询列表

// return "redirect:queryItems.action";

// 转发到商品查询列表

return "forward:queryItems.action";

}

2.图片展示设上传页面代码:

<form id="itemForm" action="${pageContext.request.contextPath }/items/editItemsSubmit.action" method="post" enctype="multipart/form-data">

<input type="hidden" name="id" value="${itemsCustom.id }"/>

<input type="hidden" name="pic" value="${itemsCustom.pic }"/>

修正商品信息:

<table width="100%" border=1>

<tr>

<td>商品名称</td>

<td><input type="text" name="name" value="${itemsCustom.name }"/></td>

</tr>

<tr>

<td>商品价格</td>

<td><input type="text" name="price" value="${itemsCustom.price }"/></td>

</tr>

<tr>

<td>商品生产日期</td>

<td><input type="text" name="createtime" value="<fmt:formatDate value="${itemsCustom.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/>"/></td>

</tr>

<tr>

<td>商品图片</td>

<td>

<c:if test="${itemsCustom.pic != null}">

<img src="/pic/${itemsCustom.pic}" width=100 height=100/>

<br/>

</c:if>

<input type="file" name="items_pic" />

</td>

</tr>

<tr>

<td>商品简介</td>

<td>

<textarea rows="3" cols="30" name="detail">${itemsCustom.detail }</textarea>

</td>

</tr>

<tr>

<td colspan="2" align="center"><input type="submit" value="提交"/>

</td>

</tr>

</table>

</form>

17.4.10.7.8 json数据交互

8.1 为什么叫进行json数据交互

json数据格式在接口调用中、html页面中教常用,json格式比较大略,解析比较方便。

比如:webservice接口,传输json数据。

8.2 springmvc进行json交互

1.流程:客户端要求的是json串(contentType=application/json),springmvc须要通过 @RequestBody 表明 将json串转成java工具,须要通过 @Response 表明 将java工具转成json串输

出。

客户端要求的是key/value串(contentType=application/x-www-form-urlen:默认的,不用指定),springmvc不须要通过 @RequestBody 表明 将json串转成java工具,须要通过

@Response 表明 将java工具转成json串输出。

终极都输出json数据,为了在前端页面方便对要求结果进行解析。

2.要求json,输出json,哀求要求是json串,以是在前端页面须要将要求的内容转成json,不太方便。

3.要求key/value,输出json。
次方法比较常用。

8.3 环境准备

8.3.1 springmvc 默认用 MappingJacksonHttpMessageConvertor 对 json数据进行转换, 通过 @RequestBody 表明 @Response 表明来进行json转换 ,

须要导入 jackson有关的jar包,通过maven依赖导入:

<!-- json jar 包 -->

<dependency>

<groupId>org.codehaus.jackson</groupId>

<artifactId>jackson-core-asl</artifactId>

<version>1.9.13</version>

</dependency>

<dependency>

<groupId>org.codehaus.jackson</groupId>

<artifactId>jackson-mapper-asl</artifactId>

<version>1.9.13</version>

</dependency>

8.3.2 配置json转换器

利用了<mvc:annotation-driven />,就不用单独配置json转换器。

8.4 json测试

8.4.1 输入的是json串,输出的是json串。

jsp页面:

利用jquery的ajax提交json串,对输出的json结果进行解析。

<script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-1.4.4.min.js"></script>

<script type="text/javascript">

//要求json,输出是json

function requestJson(){

$.ajax({

type:'post',

url:'${pageContext.request.contextPath }/requestJson.action',

contentType:'application/json;charset=utf-8',

//数据格式是json串,商品信息

data:'{"name":"手机","price":999}',

success:function(data){//返回json结果

alert(data);

}

});

}

controller 方法:

/

@see 要求json(商品信息),输出json(商品信息)

@return

/

@RequestMapping("/requestJson")

//@RequestBody将商品信息要求json串转成itemsCustom工具

//@ResponseBody将itemsCustom转成json输出

public @ResponseBody ItemsCustom requestJson(@RequestBody ItemsCustom itemsCustom){

//@ResponseBody将itemsCustom转成json输出

return itemsCustom;

}

8.4.2 输入的是key/value 输出的是json串。

jsp页面:

利用jquery的ajax提交key/value串,对输出的json结果进行解析。

//要求key/value,输出是json

function responseJson(){

$.ajax({

type:'post',

url:'${pageContext.request.contextPath }/responseJson.action',

//要求是key/value这里不须要指定contentType,由于默认就 是key/value类型

//contentType:'application/json;charset=utf-8',

//数据格式是json串,商品信息

data:'name=手机&price=999',

success:function(data){//返回json结果

alert(data.name);

}

});

}

controller 方法:

/

@see 要求key/value,输出json

@return

/

@RequestMapping("/responseJson")

//@ResponseBody将itemsCustom转成json输出

public @ResponseBody ItemsCustom responseJson(ItemsCustom itemsCustom){

//@ResponseBody将itemsCustom转成json输出

return itemsCustom;

}

17.4.10.7.9 RESTful 支持

9.1 什么是RESTful

RESTful架构,便是目前最盛行的一种互联网软件架构。
它构造清晰、符合标准、易于理解、扩展方便,以是正得到越来越多网站的采取。

RESTful(Representational State Transfer的缩写。
我对这个词组的翻译是"表现层状态转化")实在是一个开拓理念,是对http的很好的诠释。

9.1.1 对url进行规范,写RESTful格式url

查询商品url:

非RESTful格式的url: http://.../queryItems.action?id=001&type=A001

RESTful格式url: http://../items/001

特点:url非常简洁,将参数通过url传到做事端。

9.1.2 http方法规范

不管是删除、添加、更新...利用的url是同等的,如果进行删除,须要设置http的方法为delete,添加、更新也同理。

后台 controller 方法 判断http方法,如果是delete实行删除,如果是post实行添加。

9.1.3 对http的 contentType 规范

要求时指定contentType,要json数据,设置成json格式的contentType=application/json

9.2 RESTful 案列

9.2.1 需求

查询商品信息,返回json数据。

9.2.2 controller 方法

定义方法,进行映射url时利用RESTful格式的url,将查询商品的id传到controller方法

输出json利用 @ResponseBody 表明将java工具输出json。

//RESTful格式的查询商品信息,输出json

///ItemsFind/{id}中大括号中的{id}表示将这个位置的参数传到@PathVariable指定的对应名称的参数中

@RequestMapping("/ItemsFind/{id}")

public @ResponseBody ItemsCustom ItemsFind(@PathVariable("id") Integer id) throws Exception{

ItemsCustom itemsCustom = itemsService.findItemsById(id);

return itemsCustom;

}

9.2.3 RESTful 格式的前端掌握器配置

<!--RESTful风格 配置前端掌握器 -->

<servlet>

<servlet-name>springmvc-rest</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<!-- contextConfigLocation 1.配置springmvc须要加载的配置文件(配置处理器映射器、处理器适配器、处理器、视图解析器等)

2.如果不配置contextConfigLocation,就会默认加载/WEB-INF/servlet名称-servlet.xml (这里是springmvc-servlet.xml) -->

<init-param>

<param-name>contextConfigLocation</param-name>

<param-value>classpath:config/spring/springmvc.xml</param-value>

</init-param>

</servlet>

<servlet-mapping>

<servlet-name>springmvc-rest</servlet-name>

<!-- 多种配置办法: 第一种:.action,.do 访问以.action、.do为结尾的由DispatcherServlet来解析。

第二种:/ 所有访问地址都由DispatcherServlet来解析,对应静态文件须要配置不由DispatcherServlet进行解析。

利用此种办法可以实现RESTFul风格的url

第三种:/ 这种配置办法存在问题(不要用这种办法):终极转发到一个jsp页面时,

仍旧会由由DispatcherServlet解析jsp页面,不能根据jsp页面找到对应的Handler,会报错。
也不符合我们设计思想。

-->

<url-pattern>/</url-pattern>

</servlet-mapping>

9.3 对静态资源的解析

在springmvc中配置静态资源配置

<!-- default-servlet-handler 将在 SpringMVC 高下文中定义一个 DefaultServletHttpRequestHandler,

它会对进入 DispatcherServlet 的要求进行筛查, 如果创造是没有经由映射的要求, 就将该要求交由 WEB 运用做事器默认的 Servlet

处理. 如果不是静态资源的要求,才由 DispatcherServlet 连续处理 一样平常 WEB 运用做事器默认的 Servlet 的名称都是 default.

若所利用的 WEB 做事器的默认 Servlet 名称不是 default,则须要通过 default-servlet-name 属性显式指定 -->

<mvc:default-servlet-handler />

状态转化(State Transfer)

访问一个网站,就代表了客户端和做事器的一个互动过程。
在这个过程中,势必涉及到数据和状态的变革。

互联网通信协议HTTP协议,是一个无状态协议。
这意味着,所有的状态都保存在做事器端。
因此,如果客户端想要操作做事器,必须通过某种手段,让做事器端发生"状态转化"(State

Transfer)。
而这种转化是建立在表现层之上的,以是便是"表现层状态转化"。

客户端用到的手段,只能是HTTP协议。
详细来说,便是HTTP协议里面,四个表示操作办法的动词:GET、POST、PUT、DELETE。
它们分别对应四种基本操作:GET用来获取资源,POST用来新建资

源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源。

综述

综合上面的阐明,我们总结一下什么是RESTful架构:

(1)每一个URI代表一种资源;

(2)客户端和做事器之间,通报这种资源的某种表现层;

(3)客户端通过四个HTTP动词,对做事器端资源进行操作,实现"表现层状态转化"。

误区

RESTful架构有一些范例的设计误区。

最常见的一种设计缺点,便是URI包含动词。
由于"资源"表示一种实体,以是该当是名词,URI不应该有动词,动词该当放在HTTP协议中。

举例来说,某个URI是/posts/show/1,个中show是动词,这个URI就设计错了,精确的写法该当是/posts/1,然后用GET方法表示show。

如果某些动作是HTTP动词表示不了的,你就该当把动作做成一种资源。
比如网上汇款,从账户1向账户2汇款500元,缺点的URI是:

POST /accounts/1/transfer/500/to/2

精确的写法是把动词transfer改成名词transaction,资源不能是动词,但是可以是一种做事:

POST /transaction HTTP/1.1

Host: 127.0.0.1

from=1&to=2&amount=500.00

另一个设计误区,便是在URI中加入版本号:

http://www.example.com/app/1.0/foo

http://www.example.com/app/1.1/foo

http://www.example.com/app/2.0/foo

由于不同的版本,可以理解成同一种资源的不同表现形式,以是该当采取同一个URI。
版本号可以在HTTP要求头信息的Accept字段中进行区分(拜会Versioning REST Services):

Accept: vnd.example-com.foo+json; version=1.0

Accept: vnd.example-com.foo+json; version=1.1

Accept: vnd.example-com.foo+json; version=2.0

17.4.10.7.10 拦截器

10.1 拦截器定义

package org.hxweb.web.ssm.interceptor;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;

import org.springframework.web.servlet.ModelAndView;

/

@see 测试拦截器1

@author Administrator

/

public class HandlerInterceptor1 implements HandlerInterceptor{

/

(non-Javadoc)

@see 进入Handler之前实行

运用处景:身份验证,身份授权(比如:用户登录、权限验证等)

比如身份认证,如果身份认证不通过表示当前用户没有登录,须要此方法拦截不再向下实行,否则放行。

/

@Override

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)

throws Exception {

// return false表示拦截,不再向下实行

// return true表示放行。

return false;

}

/

(non-Javadoc)

@see 进入Handler之后,返回ModelAndView之前实行

运用处景从modelAndView出发:将公用的模型数据(比如菜单导航等)传到视图,也可以在这里指定统一视图

/

@Override

public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,

ModelAndView modelAndView) throws Exception {

// TODO Auto-generated method stub

}

/

(non-Javadoc)

@see 实行Handler完成之后实行

运用处景:统一非常处理、统一日志处理

/

@Override

public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)

throws Exception {

// TODO Auto-generated method stub

}

}

10.2 拦截器配置

10.2.1 针对HandlerMapping的拦截设置(不常用,不推举)

springmvc拦截器是针对HandlerMapping进行拦截设置:如果在某个 HandlerMapping 中配置拦截,经由该 HandlerMapping 映射成功的 Handler 终极利用 该 拦截器。

10.2.2 类似全局拦截器配置(常用,推举)

springmvc配置类似全局拦截器,springmvc框架将配置的类似全局拦截器注入到每个 HandlerMapping 中。

<!--拦截器 -->

<mvc:interceptors>

<!--多个拦截器,顺序实行 -->

<!-- 上岸认证拦截器 -->

<mvc:interceptor>

<mvc:mapping path="/" />

<bean class="org.hxweb.ssm.interceptor.LoginInterceptor"></bean>

</mvc:interceptor>

<mvc:interceptor>

<!-- / 表示所有url包括子url路径 -->

<mvc:mapping path="/" />

<bean class="org.hxweb.ssm.interceptor.HandlerInterceptor1"></bean>

</mvc:interceptor>

<mvc:interceptor>

<mvc:mapping path="/" />

<bean class="org.hxweb.ssm.interceptor.HandlerInterceptor2"></bean>

</mvc:interceptor>

</mvc:interceptors>

10.3 拦截器的测试

10.3.1 测试需求

测试多个拦截器各自方法实行机遇。

10.3.2 定义三个对应的拦截器

10.3.2.1 HandlerInterceptor1:

package org.hxweb.web.ssm.interceptor;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;

import org.springframework.web.servlet.ModelAndView;

/

@see 测试拦截器1

@author Administrator

/

public class HandlerInterceptor1 implements HandlerInterceptor{

/

(non-Javadoc)

@see 进入Handler之前实行

运用处景:身份验证,身份授权(比如:用户登录、权限验证等)

比如身份认证,如果身份认证不通过表示当前用户没有登录,须要此方法拦截不再向下实行,否则放行。

/

@Override

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)

throws Exception {

System.out.println("HandlerInterceptor1...preHandle");

// return false表示拦截,不再向下实行

// return true表示放行。

return false;

}

/

(non-Javadoc)

@see 进入Handler之后,返回ModelAndView之前实行

运用处景从modelAndView出发:将公用的模型数据(比如菜单导航等)传到视图,也可以在这里指定统一视图

/

@Override

public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,

ModelAndView modelAndView) throws Exception {

// TODO Auto-generated method stub

System.out.println("HandlerInterceptor1...postHandle");

}

/

(non-Javadoc)

@see 实行Handler完成之后实行

运用处景:统一非常处理、统一日志处理

/

@Override

public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)

throws Exception {

// TODO Auto-generated method stub

System.out.println("HandlerInterceptor1...afterCompletion");

}

}

10.3.2.2 HandlerInterceptor2:

package org.hxweb.web.ssm.interceptor;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;

import org.springframework.web.servlet.ModelAndView;

/

@see 测试拦截器2

@author Administrator

/

public class HandlerInterceptor2 implements HandlerInterceptor{

/

(non-Javadoc)

@see 进入Handler之前实行

运用处景:身份验证,身份授权(比如:用户登录、权限验证等)

比如身份认证,如果身份认证不通过表示当前用户没有登录,须要此方法拦截不再向下实行,否则放行。

/

@Override

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)

throws Exception {

System.out.println("HandlerInterceptor2...preHandle");

// return false表示拦截,不再向下实行

// return true表示放行。

return false;

}

/

(non-Javadoc)

@see 进入Handler之后,返回ModelAndView之前实行

运用处景从modelAndView出发:将公用的模型数据(比如菜单导航等)传到视图,也可以在这里指定统一视图

/

@Override

public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,

ModelAndView modelAndView) throws Exception {

// TODO Auto-generated method stub

System.out.println("HandlerInterceptor2...postHandle");

}

/

(non-Javadoc)

@see 实行Handler完成之后实行

运用处景:统一非常处理、统一日志处理

/

@Override

public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)

throws Exception {

// TODO Auto-generated method stub

System.out.println("HandlerInterceptor2...afterCompletion");

}

}

10.3.2.3 LoginInterceptor:

package org.hxweb.web.ssm.interceptor;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;

import org.springframework.web.servlet.HandlerInterceptor;

import org.springframework.web.servlet.ModelAndView;

/

@see 用户登录拦截器测试

@author Administrator

/

public class LoginInterceptor implements HandlerInterceptor{

/

(non-Javadoc)

@see 进入Handler之前实行

运用处景:身份验证,身份授权(比如:用户登录、权限验证等)

比如身份认证,如果身份认证不通过表示当前用户没有登录,须要此方法拦截不再向下实行,否则放行。

/

@Override

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)

throws Exception {

//获取要求的url

String url = request.getRequestURI();

//判断url是否是公开 地址(实际利用时将公开 地址配置配置文件中)

//这里公开地址是上岸提交的地址

if(url.indexOf("login.action")>=0){

//如果进行上岸提交,放行

return true;

}

//判断session

HttpSession session = request.getSession();

//从session中取出用户身份信息

String username = (String) session.getAttribute("username");

if(username != null){

//身份存在,放行

return true;

}

//实行这里表示用户身份须要认证,跳转上岸页面

request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);

// return false表示拦截,不再向下实行

// return true表示放行。

return false;

}

/

(non-Javadoc)

@see 进入Handler之后,返回ModelAndView之前实行

运用处景从modelAndView出发:将公用的模型数据(比如菜单导航等)传到视图,也可以在这里指定统一视图

/

@Override

public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,

ModelAndView modelAndView) throws Exception {

// TODO Auto-generated method stub

System.out.println("LoginInterceptor...postHandle");

}

/

(non-Javadoc)

@see 实行Handler完成之后实行

运用处景:统一非常处理、统一日志处理

/

@Override

public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)

throws Exception {

// TODO Auto-generated method stub

System.out.println("LoginInterceptor...afterCompletion");

}

}

10.3.3 测试结果:

10.3.3.1 拦截器1和拦截器2都放行

HandlerInterceptor1...preHandle

HandlerInterceptor2...preHandle

HandlerInterceptor2...postHandle

HandlerInterceptor1...postHandle

HandlerInterceptor2...afterCompletion

HandlerInterceptor1...afterCompletion

总结:

preHandle方法按照拦截器配置顺序实行。

postHandle和afterCompletion按照拦截器配置顺序的逆向顺序实行。

10.3.3.2 拦截器1放行和拦截器2不放行

HandlerInterceptor1...preHandle

HandlerInterceptor2...preHandle

HandlerInterceptor1...afterCompletion

总结:

拦截器1的preHandle方法放行,拦截器2的preHandle方法才能实行。

拦截器2的preHandle方法不放行,拦截器2的postHandle和afterCompletion方法都不实行。

只要有一个拦截器的preHandle方法不放行,拦截器的postHandle方法都不实行。

把稳:统一日志处理拦截器,日志拦截器必须配置在第一的位置,且日志拦截器的preHandle方法必须放行。

10.3.3.3 拦截器1不放行、拦截器2也不放行

HandlerInterceptor1...preHandle

总结:

拦截器1的preHandle方法不放行,拦截器1的postHandle和afterCompletion方法都不实行。

拦截器1的preHandle方法不放行,拦截器2也不会实行。

10.3.4 小结

根据测试结果,对拦截器运用。

比如:统一日志处理拦截器,须要 该 拦截器的preHandle方法必须放行,且必须将它放在拦截器链接第一个的位置。

比如:登录认证拦截器,它必须放在拦截器链接中统一日志处理拦截器后的第一个的位置。

比如:权限校验拦截器,它必须放在拦截器链接中登录认证拦截器后的第一个的位置(登录认证通过后才会进行权限校验)。

10.3.5 拦截器运用(实现登录认证):

10.3.5.1 需求

1.用户要求url

2.拦截器进行拦截校验

如果要求的url是公开地址(不要用登录即可访问的url),就放行。

如果用户session不存在,跳转到登录页面。

如果用户session存在,连续操作。

10.3.5.2 登录 controller 方法

10.3.5.3 登录认证拦截器实现