拦截器

SpringBoot中,自定义注解配合拦截器实现权限校验

创建注解

自定义注解上的注解,下面的网址为注解的解释

@Target:https://blog.csdn.net/qq_18671415/article/details/111866229

@Retention:https://blog.csdn.net/qq_18671415/article/details/111866546

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* 权限校验注解
*/
@Target(ElementType.METHOD)//指定注解加在方法上
@Retention(RetentionPolicy.RUNTIME)//指定注解的生命周期:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;
public @interface CheckAnnotation {
/**
* 是否要求用户登录
*/
boolean needLogin() default true;
}

注解校验拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import com.xiaofei.annotation.CheckAnnotation;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* 注解校验拦截器
*/
@Component
public class CheckInterceptor implements HandlerInterceptor {

/**
* Controller方法处理之前
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

HandlerMethod method = (HandlerMethod) handler;

//获取自定义注解且获取注解中的参数信息
boolean needLogin = true;
CheckAnnotation checkAnnotation = method.getMethodAnnotation(CheckAnnotation.class);
if (checkAnnotation != null) {
needLogin = checkAnnotation.needLogin();
}

//对注解中的参数进行判断,如果满足条件则进行放行,否则拦截
if (needLogin) {
throw new RuntimeException("访问资源需要登录");
}

return true;
}

/**
* Controller方法处理完之后
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("Controller方法处理完之后");
}

/**
* 调用前提:preHandle返回true
* 调用时间:DispatcherServlet进行视图的渲染之后
* 多用于清理资源
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}


添加拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import com.xiaofei.task.CheckInterceptor;
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 WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new CheckInterceptor())
.addPathPatterns("/**"); //所有请求都被拦截包括静态资源
//.excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**"); //放行的请求
}
}

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import com.xiaofei.task.annotation.CheckAnnotation;
import com.xiaofei.task.entity.UserEntity;
import com.xiaofei.task.service.UserService;
import com.xiaofei.task.utils.PageUtils;
import com.xiaofei.task.utils.ResponseUtils;
import com.xiaofei.task.valid.AddGroup;
import com.xiaofei.task.valid.UpdateGroup;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;

/**
* 用户信息
*/
@Api(tags = "用户信息")
@RestController
@RequestMapping("user")
public class UserController {

/**
* 返回信息:
* {
* "code": 200,
* "msg": "请求已经成功处理",
* "data": []
* }
*/
@CheckAnnotation(needLogin = false)//自定义注解
@ApiOperation(value = "根据条件查询", httpMethod = "GET", response = ResponseUtils.class, produces = "application/json")
@GetMapping("list/search")
public ResponseUtils<List<UserEntity>> listBySearch(UserEntity userEntity) {
List<UserEntity> items = userService.listBySearch(userEntity);
return new ResponseUtils<List<UserEntity>>().success(items);
}

/**
* 返回信息:
* {
* "code": 500,
* "msg": "访问资源需要登录",
* "data": null
* }
*/
@CheckAnnotation(needLogin = true)//自定义注解
@ApiOperation(value = "根据传递的参数进行分页查询", httpMethod = "GET", response = ResponseUtils.class, produces = "application/json")
@GetMapping("list/page")
public ResponseUtils<PageUtils<UserEntity>> listByPage(UserEntity userEntity) {
PageUtils<UserEntity> page = userService.selectListByPage(userEntity);
return new ResponseUtils<PageUtils<UserEntity>>().success(page);
}
}

Aspect + 自定义注解

可以直接使用Aspect对接口直接做切面日志,但是如果只是某些方法需要加上日志切面,就可以直接使用Aspect + 自定义注解,将切面精确到指定的方法

引入依赖

1
2
3
4
5
<!-- 引入aop,不然系统中无法使用Aspect 做切面 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

自定义注解

1
2
3
4
5
6
7
8
9
10
11
12
13
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* 日志打印注解
*/
@Target(ElementType.METHOD)//指定注解加在方法上
@Retention(RetentionPolicy.RUNTIME)//指定注解的生命周期:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;
public @interface LogAnnotation {

}

编写切面代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
* 日志打印切面
*/
@Aspect
@Component
@Slf4j
public class LogAspect {

@Pointcut("@annotation(com.xiaofei.task.annotation.LogAnnotation)")
public void pointCut() {
}

/**
* 环绕通知
*/
@Around("pointCut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String requestUrl = request.getRequestURL().toString();
Object result;
try {
log.info("请求路径:{} <=======", requestUrl);
result = joinPoint.proceed();
log.info("=====>请求结果:{} <======", JSON.toJSONString(result));
return result;
} catch (Exception e) {
log.error("=====>请求异常,异常信息:{} <========", e.getMessage());
throw e;
}
}
}

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import com.xiaofei.annotation.LogAnnotation;
import com.xiaofei.entity.UserEntity;
import com.xiaofei.utils.ResponseUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;

@Api(tags = "用户信息")
@RestController
@RequestMapping("user")
public class UserController {

/**
* 查询全部
*
* @return 全部数据
*/
@LogAnnotation
@ApiOperation(value = "查询全部", httpMethod = "GET", response = ResponseUtils.class, produces = "application/json")
@GetMapping("list")
public ResponseUtils<List<UserEntity>> selectList() {
List<UserEntity> items = userService.selectList();
return new ResponseUtils<List<UserEntity>>().success(items);
}
}

image-20230310093850575