拦截器HandlerInterceptor在普通项目中用得挺多的。比如控制登录拦截,没有登录用户session的都统一跳转到登录页面。拦截请求,统一增加日志,统计http请求操作时间等。
整合
在原来的jsp基础上实现
创建两个jsp页面
index.jsp 主页,需要登录进来才可以看
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
你已成功访问到主页面!
</body>
</html>
一个登录页面login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form method="get" action="/user/handle" >
用户名:<input type="text" name="name"/><br/>
密码:<input type="text" name="pwd"/>
<input type="submit" value="登录"/>
</form>
</body>
</html>
这里注意一下这里的action是二级的。
页面跳转controller这两个页面`@Controller
public class LoginController {
@Autowired
private UserDao userDao;
@RequestMapping("/login")
public String login() {
return "login";
}
@RequestMapping("/index")
public String index() {
return "index";
}
}
处理点击登录按钮的链接跳转
@Controller
@RequestMapping("/user")
public class HandleController {
@Autowired
private UserDao userDao;
@RequestMapping("/handle")
public String handle(User user, HttpSession session) {
Specification<User> specification = new Specification<User>() {
@Nullable
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
criteriaQuery.where(criteriaBuilder.equal(root.get("name"), user.getName()));
return null;
}
};
boolean flag = true;
String json = "";
User user1 = (User) userDao.findOne(specification).get();
System.out.println(user1.toString());
if (user1 == null) {
json = "用户不存在,登录失败!";
} else if (!user.getPwd().trim().equals(user1.getPwd().trim())) {
flag = false;
json = "密码不正确!请重新登录!";
}
if (flag) {
session.setAttribute("session_user", user1);
json = "登录成功";
return "index";
} else {
return "login";
}
}
}
以上就是没有拦截器的情况,任何情况都可以直接访问到index页面。无论是否登录过。
拦截器
增加一个类SessionInterceptor实现接口HandlerInterceptor
里面判断页面是否有session,没有就弹回登录页面。
public class SessionInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("进入拦截器");
if (request.getRequestURI().equals("/login")) {
return true;
}
//验证session是否存在
Object user = request.getSession().getAttribute("session_user");
if (user == null) {
response.sendRedirect("/login");
return false;
}
return true;
}
}
同时增加一个配置SessionConfiguration,相当于传统项目的mvc拦截配置。这里注意拦截的页面和不拦截的页面要区分开,登录页面和登录操作都是不能被拦截的。
@Configuration
public class SessionConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
InterceptorRegistration interceptor = registry.addInterceptor(new SessionInterceptor());
/**
* 添加拦截的路径
* /为根路径
* /*为一级路径
* /** 为所有路径包括多级
*/
interceptor.addPathPatterns("/**");
//排除不拦截的,包括自己登录的页面不用拦截
interceptor.excludePathPatterns("/login");
interceptor.excludePathPatterns("/user/handle");
}
}
最后记得在总的application上面加上注解@EnableAutoConfiguration
使自定义配置生效。
访问login页面可以正常访问,访问index页面没有登录就跳转到login页面。
其中拦截器的具体方法有三个,根据情况增加即可
@Override
public boolean preHandler(HttpServletRequest request, HttpServletResponse response, Object obj)throws Exception{
/*该方法将在请求处理之前进行调用,只有该方法返回true,才会继续执行后续的Interceptor和Controller,当返回值为true 时就会继续调用下一个Interceptor的preHandle 方法,如果已经是最后一个Interceptor的时候就会是调用当前请求的Controller方法;*/
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,Object obj,Exception e)throws Exception {
/*该方法将在请求处理之后,DispatcherServlet进行视图返回渲染之前进行调用,可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作。*/
}
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,Object arg2,ModelAndView arg3) throws Exception {
/*该方法也是需要当前对应的Interceptor的preHandle方法的返回值为true时才会执行,该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。用于进行资源清理。*/
}
正常顺序preHandler返回true情况下是先preHandler、postHandle、afterCompletion
返回false就直接跳过postHandle.