一、拦截器工作流程
HandlerInterceptor包含三个方法,分别是
- preHandle【业务执行前拦截】
- postHandle【业务执行后拦截】
- afterCompletion【页面渲染后拦截】
拦截顺序如下:
二、实现方法
1.自定义一个用于返回的bean
package com.cxstar.bean;
import lombok.Data;
@Data
public class ControllerRes {
private Integer code;
private String msg;
public ControllerRes(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
}
只写了常用的 preHandle 拦截器
2.创建拦截器
interceptor/CommonInterceptor.java
package com.cxstar.interceptor;
import com.alibaba.fastjson.JSONObject;
import com.cxstar.bean.ControllerRes;
import com.cxstar.bean.User;
import com.cxstar.utils.JwtUtil;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 拦截需要授权的接口
*/
public class CommonInterceptor implements HandlerInterceptor {
// 目标方法执行前调用
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 加入一些共用请求头部信息
request.setAttribute("common-msg", "好耶");
// 过滤掉一些请求
String ua = request.getHeader("User-Agent");
String referer = request.getHeader("Referer");
if(ua!=null && referer!=null) return true; // 返回 TRUE 进入业务层执行方法后返回
else {
// 返回参数加入返回体
addResBody(response, new ControllerRes(-1, "非法请求"));
return false; // 返回 FALSE 不执行业务直接携带返回体返回
}
}
// 目标方法执行后调用
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
// 页面渲染前调用
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
/**
* 将返回对象序列化后加入返回体
* @param response
* @param res
* @throws IOException
*/
private void addResBody(HttpServletResponse response, ControllerRes res) throws IOException {
response.setStatus(HttpServletResponse.SC_FORBIDDEN); // 设置状态码
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
PrintWriter out = response.getWriter();
out.write(JSONObject.toJSONString(res));
out.flush();
out.close();
}
}
3.在Spring定制配置中增加此拦截器
config/CommonWebConfig.java
package com.cxstar.config;
import com.cxstar.interceptor.CommonInterceptor;
import com.cxstar.interceptor.PermisssionInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CommonWebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new CommonInterceptor())
.addPathPatterns("/**") // 拦截全部路径
.excludePathPatterns("/login", "/register"); // 放行部分路径
}
}
4.测试
随便写个controller测试一下
package com.cxstar.controller;
import com.cxstar.bean.ControllerRes;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Slf4j
@Controller
@ResponseBody
public class CommonController {
@GetMapping("/register")
public ControllerRes register() {
return new ControllerRes(1, "注册成功");
}
@GetMapping("/login")
public ControllerRes login() {
return new ControllerRes(1, "登录成功");
}
@GetMapping("/book")
public ControllerRes getBook() {
return new ControllerRes(1, "《历史上的今天》");
}
}
启动项目
-
请求 /register 和 /login 是可以的,拦截器配置的放行
-
请求 /book 被拦截,因为请求头中的 Referer 为空