Javaweb学习笔记(拦截器)
拦截器概述
Spring MVC中的拦截器类似于Servlet中的过滤器,主要用于拦截用户请求并做出相应的处理。
拦截器的定义
通常拦截器类可以通过两种方式来定义,一种是通过实现HandlerInterceptor接口,或者继承HandlerInterceptor接口的实现类;另一种是实现WebRequestInterceptor接口或者WebRequestInterceptor接口的实现类来定义
示例:实现接口HandlerInterceptor
public class CustoomInterceptor implements HandlerInterceptor
@Override
public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throwException{
return false;
}
@Override
public void postHandle(HttpServletRequest request,HttpServletResponse response,ModelAndView modeAndView)throws Exception{
}
@Override
public void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex)throws Exception{
}
}
自定义额拦截器实现了HandlerInterceptor接口,并实现了其中的三各方法
preHandler()方法:该方法会在控制器方法前执行,其返回值表示是否中断后续操作,返回值是true时,表示继续向下执行;当其返回值为false时会中断后续的所有操作。
postHandle():该方法会在控制器方法调用之后,解析视图之前执行,可以通过此方法对请求域中的模型和视图做出进一步的修改
afterCompletion()方法:该方法会在整个请求完成,即视图渲染结束之后执行,刻通过此方法实现一些资源清理、记录日志信息的工作
拦截器的配置
拦截器配置代码如下所示:
<!--配置拦截器-->
<mvc:interceptors>
<!--使用bean直接定义在<mvc:interors>下面Interceptor将拦截所有请求-->
<bean class="com.itheima.interceptor.CustomerInterceptor"/>
<!-拦截器1-->
<mvc:interceptor>
<!--配置拦截器作用的路径-->
<mvc:mapping path="/**"/>
<!--配置不需要拦截器作用的路径-->
<mvc:exclude-mapping path=""/>
<!--定义在<mvc:interceptor>下面的,表示对匹配路径的请求才进行拦截-->
<bean class="com.itheima.interceptor.Interceptor1"/>
</mvc:interceptor>
<!-拦截器2-->
<mvc:interceptor>
<mvc:mapping path="/hello"/>
<bean class="com.itheima.interceptor.Interceptor2"/>
</mvc:interceptor>
</mvc:interceptors>
mvc:interceptors用于配置一组拦截器,其子元素中定义的是全局拦截器,他会拦截所有的请求;而mvc:interceptor元素中定义的是指定路径的拦截器,它会对指定路径下的请求生效。mvc:interceptor元素的子元素<mvc:mapping >用于配置拦截器作用的路径,该路径在其属性path中定义。如上述代码中path的属性值/**表示拦截所有路径,/hello表示拦截所有以/hello结尾的路径。如果在请求路径中包含不需要拦截的内容,还可以通过mvc:exclude-mapping元素进行配置。
需要注意的是,mvc:interceptor中的子元素必须按照上述代码的配置顺序进行编写,即<mvc:mapping >->mvc:exclude-mapping->的顺序,否则文件会报错。
拦截器的执行流程
单个拦截器的执行流程
拦截器的执行是有一些顺序的,首先会先执行拦截器类中的preHandle()方法,如果返回值为true会向下执行处理器的方法,否则不再向下执行,在业务处理器(即控制器Controller类)处理完所有的请求后,会执行postHandle()方法,然后通过DispatcherServlet向客户端返回响应;在DispatcherServlet处理完请求后,才会执行afterCompletetion()方法。
示例:
(1)在Eclipse中创建一个名为lanjie的Web项目,将SpringMVC所需的包导入
(2)在Web.xml中配置SpringMVC的前端过滤器和初始化加载配置文件等信息
(3)在src目录下创建com.itheima.controller包,创建控制器类
package com.itheima.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloController {
@RequestMapping("/hello")
public String Hello(){
System.out.println("hello");
return "success";
}
}
(4)在src目录下创建一个com.itheima.interceptor包,并在包中创建拦截器类
package com.itheima.interceptor;
import javax.servlet.http.*;
import org.springframework.web.servlet.*;
public class CustomerInterceptor implements HandlerInterceptor{
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
// TODO Auto-generated method stub
System.out.println("CustomInterceptor...afterCompletion");
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
// TODO Auto-generated method stub
System.out.println("Customer...postHandle");
}
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
// TODO Auto-generated method stub
System.out.println("Customer...preHandle");
return true;
}
}
(5)创建springmvc配置文件
<?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"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-mvc.xsd">
<context:component-scan base-package="com.itheima.controller"/>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--设置前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--设置后缀-->
<property name="suffix" value=".jsp"/>
</bean>
<!-- 配置拦截器 -->
<mvc:interceptors>
<bean class="com.itheima.interceptor.CustomerInterceptor"/>
</mvc:interceptors>
</beans>
(6)在WEB-INF中创建一个jsp文件夹,文件夹中创建一个success.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>Insert title here</title>
</head>
<body>
ok
</body>
</html>
(7)启动tomcat,将项目发布到tomcat上。访问地址http://localhost:9090/lanjie/hello
多个拦截器的执行流程
当有多个拦截器同时工作时,他们的preHandle()方法会按照配置文件中的拦截器顺序执行,而它们的postHandle()方法和afterCompletion()方法则会按照配置反序执行。
示例:
(1)在com.itheima.interceptor包中创建两个拦截器类Interceptore1和Interceptor2
Interceptore1
package com.itheima.interceptor;
import javax.servlet.http.*;
import org.springframework.web.servlet.*;
public class Interceptor1 implements HandlerInterceptor{
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
// TODO Auto-generated method stub
System.out.println("Interceptor1...afterCompletion");
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
// TODO Auto-generated method stub
System.out.println("Interceptor1...postHandle");
}
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
// TODO Auto-generated method stub
System.out.println("Interceptor1...preHandle");
return true;
}
}
Interceptor2
package com.itheima.interceptor;
import javax.servlet.http.*;
import org.springframework.web.servlet.*;
public class Interceptor2 implements HandlerInterceptor{
@Override
public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
// TODO Auto-generated method stub
System.out.println("Interceptor2...afterCompletion");
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
throws Exception {
// TODO Auto-generated method stub
System.out.println("Interceptor2...postHandle");
}
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
// TODO Auto-generated method stub
System.out.println("Interceptor2...preHandle");
return true;
}
}
(2)配置文件spring-config.xml中的< mvc:interceptors>中的元素
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.itheima.interceptor.Interceptor1"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/hello"/>
<bean class="com.itheima.interceptor.Interceptor2"/>
</mvc:interceptor>
</mvc:interceptors>
(3)启动tomcat,访问地址http://localhost:9090/lanjie/hello
案例:实现用户登录权限验证
(1)在src目录下创建一个com.itheima.po的包,创建一个User类。
package com.itheima.po;
public class User {
private Integer id;
private String username;
private String password;
public Integer getId(){
return id;
}
public void setId(Integer id){
this.id=id;
}
public String getUsername(){
return username;
}
public void setUsername(String username){
this.username=username;
}
public String getPassword(){
return password;
}
public void setPassword(String password){
this.password=password;
}
}
(2)在com.itheima.controller包中创建控制器类UserController,并在类中定义向主页跳转
package com.itheima.controller;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.itheima.po.User;;
@Controller
public class UserController {
@RequestMapping(value="/login",method=RequestMethod.GET)
public String toLogin(){
return "login";
}
@RequestMapping(value="/login",method=RequestMethod.POST)
public String login(User user,Model model,HttpSession session){
String username=user.getUsername();
String password=user.getPassword();
if(username!=null&&username.equals("root")&&password!=null&&password.equals("123456")){
session.setAttribute("USER_SESSION",user);
return "redirect:main";
}
model.addAttribute("msg","用户名或密码错误,请重新登录");
return "login";
}
@RequestMapping(value="/main")
public String toMain(){
return "main";
}
@RequestMapping(value="/logout")
public String logout(HttpSession session){
session.invalidate();
return "redirect:login";
}
}
(3)创建拦截器类LoginInterceptor
package com.itheima.interceptor;
import javax.servlet.http.*;
import org.springframework.web.servlet.*;
import com.itheima.po.*;
public class LoginInterceptor implements HandlerInterceptor{
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {
// TODO Auto-generated method stub
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// TODO Auto-generated method stub
String url=request.getRequestURI();
if(url.indexOf("/login")>=0){
return true;
}
HttpSession session=request.getSession();
User user=(User) session.getAttribute("USER_SESSION");
if(user!=null){
return true;
}
request.setAttribute("msg", "你还没有登录,请先登录!");
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
return false;
}
}
(4)在配置文件中配置自定义拦截器信息
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.itheima.interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
(5)创建两个jsp文件
main.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>
当前用户:${USER_SESSION.username}
<a href="${pageContext.request.contextPath }/logout">退出</a>
</body>
</html>
login.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>Insert title here</title>
</head>
<body>
${msg }
<form action="${pageContext.request.contextPath }/login" method="post">
用户名:<input type="text" name="username"/><br>
密 码:<input type="password" name="password"/><br>
<input type="submit" value="登录"/>
</form>
</body>
</html>
(6)启动tomcat访问地址http://localhost:9090/lanjie/login
点击退出后返回登录页面
输入密码错误后