Springboot之拦截器Interceptor
1、Interceptor定义
Interceptor类似于Servlet中的过滤器,但是Interceptor是Spring boot所带的,它主要用于拦截用户请求并做出相应的处理。例如通过拦截器可以进行登录校正。
首先当用户登录成功时,需要生成令牌,并分发令牌。代码如下:
package yuyanan.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import yuyanan.pojo.Emp;
import yuyanan.pojo.Result;
import yuyanan.service.EmpService;
import yuyanan.utils.JwtUtils;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@RestController
public class LoginController {
@Autowired
private EmpService empService;
@PostMapping("/login")
public Result login(@RequestBody Emp emp){
log.info("员工登录:{}", emp);
Emp e = empService.login(emp);
//登录成功,生成令牌,下发令牌
if (e != null){
Map<String, Object> claims = new HashMap<>();
claims.put("id", e.getId());
claims.put("name", e.getName());
claims.put("username", e.getUsername());
String jwt = JwtUtils.generateJwt(claims); //jwt包含了当前登录的员工信息
return Result.success(jwt);
}
//登录失败,返回错误信息
return Result.error("用户名或者密码错误");
}
}
在设置拦截器时需要注意,拦截器LoginCheckInterceptor需要实现HandlerInterceptor接口,并在preHandle方法中编写相应的代码,若该方法返回true,则放行;否则不放行。相应代码如下:
package yuyanan.Interceptor;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import yuyanan.pojo.Result;
import yuyanan.utils.JwtUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Slf4j
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {
@Override //目标资源方法运行前运行,返回true,放行;返回false,拦截
public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
//1、获取请求url
String url = req.getRequestURL().toString();
log.info("请求的url:{}", url);
//2、判断请求url中是否包含login,如果包含,说明是登录操作,放行
if (url.contains("login")){
log.info("登录操作,放行...");
return true;
}
//3、获取请求头中的令牌(token)
String jwt = req.getHeader("token");
//4、判断令牌是否存在,如果不存在,返回错误结果(未登录)
if(!StringUtils.hasLength(jwt)){
log.info("请求头token为空,返回未登录的信息");
Result error = Result.error("NOT_LOGIN");
//手动转换 对象--json ---------》阿里巴巴的fastJson
String jsonString = JSONObject.toJSONString(error);
resp.getWriter().write(jsonString);
return false;
}
//5、解析token,如果解析失败,返回错误结果(未登录)
try {
JwtUtils.parseJWT(jwt);
}catch (Exception e){ //jwt令牌解析失败
e.printStackTrace();
log.info("请求头token为空,返回未登录的信息");
Result error = Result.error("NOT_LOGIN");
//手动转换 对象--json ---------》阿里巴巴的fastJson
String jsonString = JSONObject.toJSONString(error);
resp.getWriter().write(jsonString);
return false;
}
//6、放行
log.info("令牌合法,放行!");
return true;
}
@Override //目标资源方法运行后运行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle....");
}
@Override //视图渲染完毕后运行,最后运行
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion...");
}
}
由于需要将该类放入到容器中进行管理,因此在上面添加@Component注解。紧接着还需要添加一个配置类WebConfig,该配置类实现WebMvcConfigurer接口,并重写添加拦截器addInterceptors方法,在该方法中指出我们要添加的拦截器名字以及作用范围。代码如下:
package yuyanan.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import yuyanan.Interceptor.LoginCheckInterceptor;
@Configuration //代表当前类是一个配置类
public class WebConfig implements WebMvcConfigurer {
@Autowired
private LoginCheckInterceptor loginCheckInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**");
}
}
值得注意的是该类是一个配置类,因此在类上面添加@Configuration注解。
总结:
1、编写自己的拦截器类LoginCheckInterceptor并实现HandlerInterceptor接口,给该类添加注解@Component将其注入到容器中,重写preHandle方法。
2、编写配置类WebConfig并实现WebMvcConfigurer接口,添加@Configuration注解表明该类是一个配置类,在该类中重写addInterceptors方法,并将我们自己编写的拦截器类加入即可。