总体步骤
1.自定义一个实现HandlerInterceptor 接口的类比如SignUpHandlerInterceptor(我这边以注册登录拦截器为例)。
package com.example.project.config;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class SignUpHandlerInterceptor implements HandlerInterceptor {
/**
* 预处理回调方法,实现处理器的预处理(如检查登陆),第三个参数为响应的处理器,自定义Controller
* 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//若注册成功可以获取session
Object signUpUser = request.getSession().getAttribute("signUpUser");
if(signUpUser==null){
request.setAttribute("msg","没有权限,请先注册账号");
request.getRequestDispatcher("/signup").forward(request,response);
return false;
}else{
return true;
}
}
/**
* 后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
*/
// @Override
// public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
// }
//
// /**
// * 整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中
// */
// @Override
// public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
// }
}
2.我这边是对注册的拦截器,所以我需要设置session
package com.example.project.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.thymeleaf.util.StringUtils;
import javax.servlet.http.HttpSession;
@Controller
public class SignUpController {
@RequestMapping({"/user/signup"})
public String signUp(@RequestParam("signup_name") String signup_name,
@RequestParam("signup_email")String signup_email,
@RequestParam("signup_password")String signup_password,
Model model,
HttpSession session){//通过model返回数据,通过RequestParam接收数据
//业务
//测试
System.out.println("###=>"+signup_name);
System.out.println("###=>"+signup_email);
System.out.println("###=>"+signup_password);
//姓名邮箱不为空并且密码为123456
if(!StringUtils.isEmpty(signup_name)&&!StringUtils.isEmpty(signup_email)&&"123456".equals(signup_password)){
//注册成功就设置session
//x.setAttribute(name,value)把x的name的值设置为value
session.setAttribute("signUpUser",signup_email);
return "index";
}else{
//反馈失败信息
model.addAttribute("msg","您的输入有误,请重试");
return "signup";
}
// return "signup";
}
}
3.重写addInterceptor方法,添加自定义的拦截器并设置需要拦截的页面和不需要拦截的页面。
package com.example.project.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MyMvcConfiguration implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("signup");
registry.addViewController("/signup.html").setViewName("signup");
registry.addViewController("/signup").setViewName("signup");
}
//自定义国际化组件
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SignUpHandlerInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/signup","/","/user/signup","/login","/login.html");
}
}
HandlerInterceptor 接口的三个方法
/**
* 预处理回调实现处理器的预处理(如检查登陆),第三个参数为响应的处理器,自定义Controller
* 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
* 这个方法将在请求处理之前进行调用。 「注意」:如果该方法的返回值为false ,将视为当前请求结束,不仅自身的拦截器会失效,还会导致其他的拦截器也不再执行。
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return HandlerInterceptor.super.preHandle(request, response, handler);
}
/**
* 后处理回调实现处理器的后处理(但在渲染视图之前),modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
* 只有在 preHandle 方法返回值为true 时才会执行。会在Controller 中的方法调用之后,DispatcherServlet 返回渲染视图之前被调用。
* postHandle 方法被调用的顺序跟 preHandle 是相反的,先声明的拦截器 preHandle 方法先执行,而postHandle方法反而会后执行。
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
/**
只有在 preHandle 方法返回值为true 时才会执行。在整个请求结束之后, DispatcherServlet 渲染了对应的视图之后执行。
* 整个请求处理完毕回调,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间.
* 还可以进行一些资源清理或释放资源,类似于try-catch-finally中的finally,但仅调用处理器执行链中
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
一般的处理顺序为:preHandler -> Controller -> postHandler -> model渲染-> afterCompletion
拦截器拦截页面设置
在自定义的Configuration配置文件中设置拦截的页面
addPathPatterns设置进入拦截器的页面
excludePathPatterns设置除外的不需拦截的页面(比如注册和登录)
当需要拦截的内容多的时候可以用:
registry.addInterceptor(new XXXXHandlerInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/signup","/","/user/signup","/login");
/**表示所有路径
excludePathPatterns把除外的可以随意访问的路径放入
完整的MyMvcConfiguration代码:
@Configuration
public class MyMvcConfiguration implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("signup");
registry.addViewController("/signup.html").setViewName("signup");
registry.addViewController("/signup").setViewName("signup");
}
//自定义国际化组件
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SignUpHandlerInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/signup","/","/user/signup","/login");
}
}