- 一、注解的基本元素
- 修饰符
- 元注解
- 二、实战
- 1、新建注解类
- 2、注解类的解析
- 3、配置拦截器并放开swagger
- 4、编写接口验证
访问修饰符必须为public,不写默认为pubic;
关键字:@interface;
注解名称:自定义注解的名称,就是注解名称
注解类型元素:注解中内容,根据需要标志参数
@Target、@Retention、@Inherited、@documented 这四个注解就是元注解,元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的元注解类型,它们被用来提供对其它 注解类型作标志操作(可以理解为最小的注解,基础注解)
@Target:用于描述注解的使用范围,该注解可以使用在什么地方
| Target类型 | 描述 |
|---|---|
| ElementType.TYPE | 应用于类、接口(包括注解类型)、枚举 |
| ElementType.FIELD | 应用于属性(包括枚举中的常量) |
| ElementType.METHOD | 应用于方法 |
| ElementType.PARAMETER | 应用于方法的形参 |
| ElementType.CONSTRUCTOR | 应用于构造函数 |
| ElementType.LOCAL_VARIABLE | 应用于局部变量 |
| ElementType.ANNOTATION_TYPE | 应用于注解类型 |
| ElementType.PACKAGE | 应用于包 |
备注:例如@Target(ElementType.METHOD),标志的注解使用在方法上,但是我们在这个注解标志在类上,就会报错
@Retention:表明该注解的生命周期
| 生命周期类型 | 描述 |
|---|---|
| RetentionPolicy.SOURCE | 编译时被丢弃,不包含在类文件中 |
| RetentionPolicy.CLASS | JVM加载时被丢弃,包含在类文件中,默认值 |
| RetentionPolicy.RUNTIME | 由JVM 加载,包含在类文件中,在运行时可以被获取到 |
@Inherited:是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。
@documented:表明该注解标记的元素可以被Javadoc 或类似的工具文档化
二、实战自定义注解校验用户是否有admin/manager角色
1、新建注解类@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@documented
public @interface RoleAuthorize {
String[] value() default {};
}
2、注解类的解析
@Component
@Slf4j
public class RoleInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
RoleAuthorize permission = handler.getClass().getAnnotation(RoleAuthorize.class);
if(handler.getClass().isAssignableFrom(HandlerMethod.class)){
RoleAuthorize methodAnnotation =
((HandlerMethod) handler).getMethodAnnotation(RoleAuthorize.class);
if (methodAnnotation != null) {
permission = methodAnnotation;
}
}
// 如果没有添加权限注解则直接跳过允许访问
if (permission == null){
return true;
}
// 获取注解中的值
String[] validateRoles = permission.value();
// 校验是否含有对应的角色,编写自己的校验规则
for (String role : validateRoles) {
if ("admin".equals(role) || "manager".equals(role)){
return true;
}
}
throw new AccessDeniedException("没有权限访问当前接口");
}
}
3、配置拦截器并放开swagger
我采用的是swagger测试访问的
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Autowired
private RoleInterceptor roleInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
String[] swaggerExcludes=new String[]{"/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**"};
registry.addInterceptor(roleInterceptor)
.excludePathPatterns(swaggerExcludes)
.addPathPatterns("/**");
super.addInterceptors(registry);
}
}
拦截器的第二种实现
注意:继承WebMvcConfigurerAdapter虽然可以实现,但是在springboot2中已经过时,可以采用以下这种方式:继承:WebMvcConfigurationSupport
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
@Autowired
private RoleInterceptor roleInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(roleInterceptor)
.addPathPatterns("/**")
// .excludePathPatterns("/user/login")
.excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**");
}
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/meta-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/meta-INF/resources/webjars/");
}
}
4、编写接口验证
@RestController
@Slf4j
public class StudentController {
@Autowired
private StudentService studentService;
@GetMapping("students")
@RoleAuthorize(value = {"admin"})
public CommonResult listStudents(@RequestParam("userName") String userName) throws InterruptedException {
return CommonResult.build(200, "ok", studentService.getStudent(userName));
}
@GetMapping("list")
@RoleAuthorize(value = {"test"})
public CommonResult lists() throws InterruptedException {
return CommonResult.build(200, "ok", studentService.getStudent(null));
}
}
5、启动类
@SpringBootApplication
@EnableSwagger2 // 注入swagger
public class PlatformTestApp {
public static void main(String[] args) {
SpringApplication.run(PlatformTestApp.class,args);
}
// SpringBoot Swagger去掉basic-error-controller
@Bean
public Docket demoApi() {
return new Docket(documentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.regex("(?!/error.*).*"))
.build();
}
}



