1.拦截器的定义

SpringMVC中的拦截器,类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并做相应的处理.例如,通过拦截器可以进行权限验证,记录请求信息的日志,判断用户是否登录等

通常拦截器类可以通过两种方式来定义,一种是通过实现HandlerInterceptor接口,或继承HandlerInterceptor接口的实现类HandlerInterceptorAdapter另一种是通过实现WebRequestInterceptor接口,或继承WebRequestInterceptor接口的实现类来定义

demo:实现HandlerInterceptor接口

public class CustomInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throws Exception{
 return false;
}
@Override
public void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView)throws Exception{
}
@Override
public void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex)throws Exception{
}
}
  •  preHandle():该方法会在控制器方法前执行,其返回值表示是否中断后续操作,当返回值为true时,表示继续向下执行;当返回值为false时,会中断后续的所有操作(包括调用下一个拦截器和控制器类中的方法执行等)
  • postHandle():该方法会在控制器方法调用之后,解析视图之前执行,可以通过此方法对请求域中的模型和视图作出进一步的修改
  • afterCompletion()方法:该方法会在整个请求完成,即视图渲染结束之后执行,可以通过此方法实现一些资源清理,记录日志信息等工作.

 

2.拦截器的配置

<!--配置拦截器-->
<mvc:interceptors>
<!--使用bean直接定义在<mvc:interceptors>下面的Interceptor将拦截所有请求-->
<bean class="com.itcast.interceptor.CustomInterceptor"/>
<!--拦截器1-->
<mvc:interceptor>
<!--配置拦截器作用的路径-->
<mvc:mapping path="/**"/>
<!--配置不需要拦截器作用的路径-->
<mvc:exclude-mapping path=""/>
<!--定义在<mvc:interceptor>下面的,表示对匹配路径的请求进行拦截-->
<bean class="com.itcast.interceptor.Interceptor1"/>
</mvc:interceptor>
<!--拦截器2-->
<mvc:interceptor>
<mvc:mapping path="/hello"/>
<bean class="com.itcast.interceptor.Interceptor2"/>
</mvc:interceptor>
   ...
</mvc:interceptors>

 

 

3.单个拦截器的执行流程

接口拦截器springboot 提高性能 springmvc中拦截器实现接口是_ide

demo:

(1)创建chapter15的web项目,导入相关jar包

(2)在web.xml中,配置SpringMVC的前端过滤器和初始化加载配置文件等信息

(3)HelloController

@Controller
public class HelloController{
/*
页面跳转
*/
@RequestMapping("/hello")
public String Hello(){}
System.out.println("Hello!");
return "success";
}

 

(4)创建拦截器类CustomInterceptor

/*
实现了HandlerInterceptor接口的自定义拦截器类
*/
public class CustomInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throws Exception{
System.out.println("CustomInterceptor...preHandle");
//对拦截的请求进行放行处理
 return true;
}
@Override
public void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView)throws Exception{
System.out.println("CustomInterceptor...postHandle");

}
@Override
public void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex)throws Exception{
System.out.println("CustomInterceptor...afterCompletion");

}
}

(5)SpringMVC.xml

<!--定义组件扫描器,指定需要扫描的包-->
  <context:component-scan base-package="com.itcast.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直接定义在<mvc:interceptors>下面的拦截器将拦截所有请求-->
<bean class="com.itcast.interceptor.CustomInterceptor"/>
</mvc:interceptors>
</beans>

 

4.多个拦截器的执行流程

 

接口拦截器springboot 提高性能 springmvc中拦截器实现接口是_拦截器_02

 

 

(1)定义两个拦截器类

Interceptor1

/*
以实现接口的方式定义拦截器
*/
public class Interceptor1 implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throws Exception{
System.out.println("Intercepter1...preHandle");
//对拦截的请求进行放行处理
 return true;
}
@Override
public void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView)throws Exception{
System.out.println("Intercepter1...postHandle");

}
@Override
public void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex)throws Exception{
System.out.println("Intercepter1...afterCompletion");

}
}

Interceptor2

/*
以实现接口的方式定义拦截器
*/
public class Interceptor2 implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throws Exception{
System.out.println("Intercepter2...preHandle");
//对拦截的请求进行放行处理
 return true;
}
@Override
public void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView)throws Exception{
System.out.println("Intercepter2...postHandle");

}
@Override
public void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex)throws Exception{
System.out.println("Intercepter2...afterCompletion");
}
}

(3)springmvc-config.xml中,定义两个拦截器

<!--配置拦截器1-->
<mvc:interceptor>
<!--配置拦截器作用的路径-->
<mvc:mapping path="/**">
<!--使用bean直接定义在<mvc:interceptors>下面的拦截器将拦截所有请求-->
<bean class="com.itcast.interceptor.Interceptor1"/>
</mvc:interceptor>
<!--拦截器2-->
<mvc:interceptor>
<mvc:mapping path="/hello">
<bean class="com.itcast.interceptor.Interceptor2"/>
</mvc:interceptor>

 

5.应用案例:实现用户登录权限验证

接口拦截器springboot 提高性能 springmvc中拦截器实现接口是_拦截器_03

 

只有登录后的用户才能访问系统中的主页面,如果没有登录系统而直接访问主页面,则拦截器会将请求拦截,并转发到登录页面,同时在登录页面中给出提示信息.如果用户名或密码错误,也会在登录页面给出相应的提示信息,当已登录的用户在系统主页中单击"退出"按钮时,系统同样会回到登录页面

(1)User类

(2)UserController

@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("xiaoxue")&&password!=null&&password.equals("123456")){
//将用户对象添加到session
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
session.invalidate();
//重定向到登录页面的跳转方法
return"redirect:login";
  }
}

 

(3)创建登录拦截器类LoginInterceptor

/*
登录拦截器
*/
public class LoginInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throws Exception{
//获取请求的URL
String url=request.getRequestURI();
//url:除了login.jsp是可以公开访问的,其他的URL都进行拦截控制
if(url.indexOf("/login")>=0){
return true;
}
//获取session
HttpSession sessio=request.getSession();
User user=(User)session.getAttribute("USER_SESSION");
//判断session中是否有数据,如果有,则返回true,继续向下执行
if(user!=null){
return true;
}
//不符合条件的给出提示信息,并转发到登录页面
request.setAttribute("msg","您还没有登录,请先登录!");
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
return false;
}
@Override
public void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView)throws Exception{
}
@Override
public void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex)throws Exception{
   }
}

 

(4)在配置文件<mvc:interceptors>元素中,配置自定义的拦截器信息

<mvc:interceptor>
   <mvc:mapping path="/**"/>
   <bean class="com.itcast.interceptor.LoginInterceptor"/>
</mvc:interceptor>

 

(5)在WEB-INF目录下的jsp文件夹中,创建一个系统主页面main.jsp.在该页面中,使用EL表达式获取用户信息,并且通过一个超链接来实现"退出"功能

<title>系统主页</title>
<body>
    当前用户:${USER_SESSION.username}
    <a href="${pageContext.request.contextpath}/logout">退出</a>
</body>

(6)login.jsp

<title>用户登录</title>
<body>
${msg}
  <form action="${pageContext.request.contextpath}/login" method="POST">
    用户名:<input type="text" name="username" id="username"><br/>
    密    码:
  <input type="password" name="password" id="password"><br/>
 <input type="submit" value="登录" />
</form>
</body>