SpringMVC拦截器
介绍
拦截器(interceptor)的作用
SpringMVC的拦截器
类似于Servlet开发中的过滤器Filter,用于对处理器 进行预处理
和后处理
将拦截器按一定的顺序连接成一条链,这条链称为拦截器链(Interception Chain)
。在访问被拦截的方法或字段时,拦截器链中的拦截器链就会按其之间定义的顺序被调用。拦截器也是AOP思想的具体实现
拦截器和过滤器之间的区别
区别 | 过滤器(Filter) | 拦截器(Interceptor) |
---|---|---|
使用范围 | 是servlet规范中的一部分,任何java web工程都可以使用 | 是SpringMVC框架自己的,只有使用来了SpringMVC框架的工程才可以使用 |
拦截范围 | 在url-pattern中配置了/*之后,可以对所有要访问的资源进行拦截 | 在<mvc:mapping path=“”/>中配置了/**之后,也可以对所有的资源进行拦截,但是可以通过<mvc:exclude-mapping path=“” />标签排除不需要拦截资源 |
快速入门
自定义拦截器只有三步:
- 创建拦截器类实现HandlerInterception接口
- 配置拦截器
- 测试拦截器的拦截效果
代码实现
1、创建拦截器类实现HandlerInterceptor接口
public class MyhandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle running....");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandler running...");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion running...");
}
}
2、配置拦截器
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="interceptor.MyhandlerInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
3、测试拦截器的拦截效果(编写目标方法)
@Controller
public class TestController {
@RequestMapping("/test")
@ResponseBody
public String save() {
System.out.println("目标方法执行...");
return "index";
}
}
http://localhost:8080/test
多拦截器操作
同上,在编写一个MyHandlerInterceptor1操作,测试执行顺序
拦截器方法说明
方法名 | 说明 |
---|---|
preHandler() | 方法将在请求处理之前进行调用,该方法的返回值是布尔值Boolean类型的,当它返回为false时,表示请求结束,后续的Interceptor和Controller都不会再执行;当返回值为true时就会继续调用下一个Interceptor的preHandle方法 |
postHandler() | 该方法是在当前请求进行处理之后被调用,前提是preHandler方法的返回值为true时才能被调用,且它会在DispatcherServlet进行视图返回渲染之前被调用,所以可以在这个方法中对Controller处理之后的ModelAndView对象进行操作 |
afterCompletion() | 该方法将在整个请求结束之后,也就是在DispatcherServlet渲染了对应的视图之后执行,前提是preHandler方法的返回值为true时才能调用 |
案例
用户登录权限控制
需求:用户没有登录得情况下,不能对后台菜单进行访问操作,点击菜单跳转到登录页面,只有用户登录成功之后,才能进行后台功能得操作
public class PrivilegeInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 逻辑:判断 用户是否登录 本质:判断session中有没有user
HttpSession session = request.getSession();
User user = (User) session.getAttribute("user");
if (user == null) {
// 没有登录
response.sendRedirect(request.getContextPath() + "/login.jsp");
return false;
}
// 放行 访问目标资源
return true;
}
}
拦截器配置
<mvc:interceptors>
<mvc:interceptor>
<!--配置那些资源需要拦截-->
<mvc:mapping path="/**"/>
<!--配置那些资源需要排除-->
<mvc:exclude-mapping path="/user/login"/>
<bean class="com.dc.interceptor.PrivilegeInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
UserController
@RequestMapping("/user")
@Controller
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/login")
public String login(String username, String password, HttpSession session) {
User login = userService.login(username, password);
System.out.println(login);
if (login != null) {
session.setAttribute("user", login);
return "redirect:/index.jsp";
}
return "redirect:/login.jsp";
}
}
Service
public interface UserService {
User login(String username, String password);
}
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public User login(String username, String password) {
try {
return userDao.login(username, password);
} catch (EmptyResultDataAccessException e) {
return null;
}
}
}
Dao层
public interface UserDao {
User login(String username, String password);
}
public class UserDaoImpl implements UserDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
this.jdbcTemplate = jdbcTemplate;
}
@Override
public User login(String username, String password) throws EmptyResultDataAccessException {
User user = jdbcTemplate.queryForObject("select * from sys_user where username = ? and password = ?", new BeanPropertyRowMapper<User>(User.class), username, password);
return user;
}
}