在项目开发时,大部分操作时都是基于用户登录状态下的。拦截器是最经常使用的方式,这里我结合了自定义注解。https://github.com/XMUTLZY/login-check-demo
项目结构
Demo主要用Springboot搭建
- vo包:定义了一个用户实体类
- annotation包:存放自定义的注解
- config包:配置类,主要用于初始化拦截器
- controller包:一些操作,比如登录校验、访问主页
- interceptor包:定义拦截器
具体实现
自定义注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by lin on 2020/04/10
*/
@Target(ElementType.METHOD) //标记在方法上
@Retention(RetentionPolicy.RUNTIME) //生命周期(运行时有效)
public @interface LoginRequired {
}
这里主要用到2个元注解,其中@Target和@Retention有多个枚举型可以设置,具体看源码。
拦截器
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import redis.clients.jedis.Jedis;
import sch.jake.logincheckdemo.web.annotation.LoginRequired;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
/**
* Created by lin on 2020/04/10
* @Tip: 登录校验拦截器
*/
public class LoginInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (!(handler instanceof HandlerMethod)) { //判断处理请求的handler类型
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod(); //获取处理请求的方法
if (method.getAnnotation(LoginRequired.class) != null) { //判断该方法上是否有自定义的注解
Jedis jedis = new Jedis("127.0.0.1", 6379);
String userJsonStr = jedis.get("USER_INFO");
if (!StringUtils.hasText(userJsonStr)) { //判断缓存中是否有用户数据
return false;
}
}
return true;
}
}
简单来说就是,拦截器拦截请求,当注解标记在该请求方法上时,查询缓存中是否有用户信息。
配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import sch.jake.logincheckdemo.web.interceptor.LoginInterceptor;
/**
* Created by lin on 2020/04/10
* @Tip: 配置类,用于初始化拦截器
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor());
}
@Bean
public LoginInterceptor loginInterceptor() {
return new LoginInterceptor();
}
}
这里就是初始化拦截器,并注册到配置中。
Controller
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import redis.clients.jedis.Jedis;
import sch.jake.logincheckdemo.vo.User;
import sch.jake.logincheckdemo.web.annotation.LoginRequired;
/**
* Created by lin on 2020/04/10
*/
@Controller
public class TestController {
//登录校验(成功时在缓存中存放用户信息)
@PostMapping("/verify")
@ResponseBody
public String verify(@RequestBody User user) {
if ("Jake.lin".equals(user.getUserName()) && "test123".equals(user.getPassword())) {
Jedis jedis = new Jedis("127.0.0.1", 6379);
String userJsonStr = JSONObject.toJSONString(user);
jedis.set("USER_INFO", userJsonStr);
return "success";
}
return "failure";
}
//进入主页
@GetMapping("/index")
@LoginRequired
public String index() {
return "index.html";
}
}
这里主要定义了两个方法。
(1)当用户调用/verify接口时,如果用户密码输入正确,将用户信息序列化之后存入Redis缓存中。
(2)自定义注解标记在index()方法,表示当访问该方法时,会对登录状态进行校验(因为之前已经定义过拦截器对方法上是否存在自定义注解进行判断)
总结
这样当用户请求的操作需要登录状态时,只需要在对应请求的方法上添加注解即可。这里我使用的是Redis替代了session的功能,意思一样