往期文章
SSM系列笔记整理,往期笔记如下:
Spring01 —— Spring概念及快速入门
Spring02 —— Spring配置文件详解和依赖注入
Spring03 —— SpringAPI和在Spring中配置数据源
Spring04 —— Spring的注解开发
Spring05 —— Spring集成Junit
Spring06 —— Spring集成web环境
SpringMVC01 —— SpringMVC简介&快速入门
SpringMVC02 —— SpringMVC的各组件详解
SpringMVC03 —— Spring的请求和响应
Spring07 —— Spring Jdbctemplate的使用
SpringMVC拦截器
1、什么是拦截器
在系统中,经常需要在处理用户请求之前和之后执行一些行为,例如检测用户的权限,或者将请求的信息记录到日志中,即平时所说的“权限检测”及“日志记录”。当然不仅仅这些,所以需要一种机制,拦截用户的请求,在请求的前后添加处理逻辑。
Spring MVC 的拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。
将拦截器按一定的顺序联结成一条链,这条链称为拦截器链(InterceptorChain)。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。拦截器也是AOP思想的具体实现。
2、SpringMVC拦截器和过滤器的区别
3、SpringMVC拦截器快速入门
自定义拦截器很简单,只有如下三步:
①创建拦截器类实现HandlerInterceptor接口
②配置拦截器
③测试拦截器的拦截效果
1、环境搭建
创建一个module,完善Spring集成web环境
SpringMVC需要配置的首先是注解驱动、视图解析器、静态资源访问权限开放、组件扫描
web.xml主要配置前端控制器 全局乱码过滤器
web层编写一个controller TestController
package com.zhou.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
/**
* @author it春和
* @create 2022-04-11 20:15
*/
@Controller
public class TestController {
@RequestMapping("/show")
public ModelAndView show() {
System.out.println("目标资源执行!");
ModelAndView modelAndView = new ModelAndView();
// 设置模型
modelAndView.addObject("username", "张无忌");
// 设置视图
modelAndView.setViewName("index");
return modelAndView;
}
}
部署测试:
1、编写自定义的拦截器:
我们去实现handlerinterceptor接口,由于做了默认的实现并不会报错,所以我们需要手动去重写三个方法。
public class MyInterceptor1 implements HandlerInterceptor {
// 在目标方法执行之前执行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle执行...");
return false;
}
// 在目标方法执行之后、视图返回之前执行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle执行...");
}
// 整个流程执行完毕后执行
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion执行...");
}
}
2、在spring-mvc中配置拦截器
<!-- 配置拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 指定对哪些资源进行拦截操作 -->
<mvc:mapping path="/**"/>
<bean class="com.zhou.interceptor.MyInterceptor1"/>
</mvc:interceptor>
</mvc:interceptors>
3、测试
原因在于PreHandle方法返回的false表示不放行,整个流程处于被拦截状态。
将返回值改为true
当拦截器的preHandle方法返回true则会执行目标资源,如果返回false则不执行目标资源
多个拦截器情况下,配置在前的先执行,配置在后的后执行
拦截器中的方法执行顺序是:preHandler-------目标资源----postHandle---- afterCompletion
4、拦截器小细节
拦截器我们常用的就只有两个方法
1、preHandle,在该方法中我们可以做一些逻辑的判断
// 在目标方法执行之前执行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle执行...");
String name = request.getParameter("name");
if ("zhangsan".equals(name)){
// 放行
return true;
}
// 参数名不匹配则跳转到错误页面
request.getRequestDispatcher("/error.jsp").forward(request,response);
return false;
}
访问目标资源的时候需要携带参数,根据参数进行判断
2、postHandle方法是在目标方法执行之后执行,在渲染视图之前执行,所以我们可以在这里修改视图。
// 在目标方法执行之后、视图返回之前执行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle执行...");
modelAndView.addObject("username","张三");
}
5、拦截器案例
在Spring综合练习的基础上加上用户登录相关的拦截器,用户没有登录的情况下,不能对后台菜单进行访问操作,点击菜单跳转到登录页面,只有用户登录成功后才能进行后台功能的操作
判断用户登录的本质就是判断session中有没有user
,如果没有则跳转到登录页面,如果有则放行
编写拦截器
public class LoginInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 1、获取session
HttpSession session = request.getSession();
// 2、从session中获取user
User user = (User) session.getAttribute("user");
// 3、判断
if (user == null){
// session中没有user跳转到登录页面
response.sendRedirect(request.getContextPath() + "/login.jsp");
return false;
}
// 有用户登录信息 放行
return true;
}
}
配置拦截器
找到spring-mvc.xml文件进行配置
<!-- 配置拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.itch.test.inteceptor.LoginInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
部署测试
完善登录相关的代码
dao
/**
* 根据用户名密码查询用户
* @param username
* @param password
* @return
*/
public User findUserByNameAndPasswd(String username,String password);
public User findUserByNameAndPasswd(String username, String password) {
User user = null;
try {
String sql = "select * from sys_user where username = ? and password = ?";
user = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), username, password);
} catch (DataAccessException e) {
e.printStackTrace();
}
return user;
}
service
public User login(String username,String password);
public User login(String username, String password) {
return userDao.findUserByNameAndPasswd(username,password);
}
controller
@RequestMapping("/login")
public String login(String username, String password, HttpSession session){
User user = userService.login(username, password);
if (user != null){
// 表示能够查询出用户 将查询出来的用户存入session中
session.setAttribute("user",user);
return "redirect:/index.jsp";
}
return "redirect:/login.jsp";
}
前端代码
修改请求路径
测试
这里点击登录我们会发现并不会发生跳转,这是因为springmvc的拦截器拦截了所有请求,所以我们需要在SpringMVC的配置文件spring-mvc文件中配置不要对登录请求进行拦截操作
<!-- 配置拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 配置对哪些资源执行拦截操作 -->
<mvc:mapping path="/**"/>
<!-- 配置对哪些资源不进行拦截操作 -->
<mvc:exclude-mapping path="/user/login"/>
<bean class="com.itch.test.inteceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
重新部署测试:
自定义拦截器的步骤:
①创建拦截器类实现HandlerInterceptor接口②配置拦截器
③测试拦截器的拦截效果