在SpringBoot中,我们可以使用自定义注解来实现很多功能,比如权限控制,一般只需要四步就可以实现自定义注解。今天,我们就来简单总结一下SpringBoot实现自定义注解的方法。

SpringBoot 使用拦截器实现自定义注解

业务场景:现在我需要对部分用户进行拦截,通过注解的方式,假如有这么一个注解@WithOutLogin,只要他作用在方法上,那么请求都不需要带token,反之,如果请求没有带token,那么请求方法将会失败。

一. 自定义注解

定义一个@interface类。

  1. package com.exam.common.security;
  2.  
  3. import java.lang.annotation.*;
  4.  
  5. @Target(ElementType.METHOD)
  6. @Retention(RetentionPolicy.RUNTIME)
  7. @Documented
  8. public @interface WithOutLogin {
  9. }

@Target:用于描述注解的使用范围。
ElementType.TYPE:类、接口(包括注解类型) 或enum声明。ElementType.METHOD:方法。
@Retention:注解的生命周期,用于表示该注解会在什么时期保留。
RetentionPolicy.RUNTIME:运行时保留,这样就可以通过反射获得了。
@Documented:表示该注解会被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。

二. 编写拦截器类

注解定义好了,接下来使用Springboot拦截器,创建类继承HandlerInterceptor,并实现preHandle、postHandle、afterCompletion方法。然后在preHandle方法中编写业务逻辑,实现注解的业务功能。

  1. package com.exam.common.security;
  2.  
  3. import lombok.extern.slf4j.Slf4j;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.stereotype.Component;
  6. import org.springframework.web.method.HandlerMethod;
  7. import org.springframework.web.servlet.HandlerInterceptor;
  8. import org.springframework.web.servlet.ModelAndView;
  9.  
  10. import javax.servlet.http.HttpServletRequest;
  11. import javax.servlet.http.HttpServletResponse;
  12.  
  13. @Component
  14. @Slf4j
  15. public class PermissionInterceptor implements HandlerInterceptor {
  16.  
  17. //在请求已经返回之后执行
  18. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) throws Exception {
  19. }
  20.  
  21. //执行目标方法之后执行
  22. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object hadnler, ModelAndView ex) throws Exception {
  23. }
  24.  
  25. //在执行目标方法之前执行
  26. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object hadnler) throws Exception {
  27. //判断是否方法级别的
  28. if (hadnler instanceof HandlerMethod) {
  29. HandlerMethod handlerMethod = (HandlerMethod) hadnler;
  30. WithOutLogin withOutLogin = handlerMethod.getMethodAnnotation(WithOutLogin.class);
  31. //有注解,则不验证token
  32. if (withOutLogin != null) {
  33. return true;
  34. }
  35. }
  36.  
  37. String token = request.getHeader("X-Auth-Token");
  38. if (StringUtils.isBlank(token)) {
  39. log.error("未登录 userId is :{}, token is null.", token);
  40. return false;
  41. }
  42. return true;
  43. }
  44. }

三. 拦截器类注册

创建一个普通类,让该类继承WebMvcConfigurerAdapter,并且使用@Configuration注解标注在类名上,使其成为一个配置类。然后重写addInterceptors方法,当服务器启动时,会自动调用此方法。

  1. package com.exam.common.security;
  2.  
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  5. import org.springframework.context.annotation.Configuration;
  6. import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
  7. import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
  8.  
  9. @Configuration
  10. public class PermissionConfigure extends WebMvcConfigurerAdapter {
  11. @Autowired
  12. private PermissionInterceptor permissionInterceptor;
  13.  
  14. @Override
  15. public void addInterceptors(InterceptorRegistry registry) {
  16. registry.addInterceptor(permissionInterceptor).addPathPatterns("/user/**");
  17. super.addInterceptors(registry);
  18. }
  19. }

四. 编写controller类

在Controller中的业务方法上选择是否标注@WithOutLogin注解,如果有,那么无需登录就可以执行该方法。如果没有此注解,就需要登录后才可以执行。

  1. package com.exam.api.rest;
  2.  
  3. import com.exam.common.security.WithOutLogin;
  4. import lombok.extern.slf4j.Slf4j;
  5. import org.springframework.web.bind.annotation.PutMapping;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import org.springframework.web.bind.annotation.RestController;
  8. import javax.servlet.http.HttpServletRequest;
  9.  
  10. @RestController
  11. @RequestMapping("/user")
  12. @Slf4j
  13. public class UserController extends RestBaseController {
  14.  
  15. @WithOutLogin
  16. @PutMapping(value = "/findPassword")
  17. public String smsLogin(HttpServletRequest request){
  18. return "找回密码不需要登录";
  19. }
  20.  
  21. @PostMapping(value = "/modifyMobile")
  22. public String modifyMobile(ModifyMobileRequest entity, HttpServletRequest request){
  23. return "修改手机号需要登录";
  24. }
  25. }

至此,我们启动服务器,访问接口,就能看到效果了,这里不再做示范。

本文已通过「原本」原创作品认证,转载请注明文章出处及链接。

Java最后更新:2022-11-6
夏日阳光
  • 本文由 夏日阳光 发表于 2019年10月10日
  • 本文为夏日阳光原创文章,转载请务必保留本文链接:https://www.pieruo.com/111.html
匿名

发表评论

匿名网友
:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:
确定

拖动滑块以完成验证
加载中...