为了方便我们在日常开发注解的使用,本文将开发所需要的注解统一并进行归类起来,并结合用例进行解析,这样收藏起来以便日后使用。最主要本文将持续更新日常使用的注解,也可以评论中告知其他注解。
1依赖注入
1.1组件注解 @component
@component,而其余 @Controller、@Service、@Repository都组合了@component注解,主要为便于使用者Class组件进行归类。
默认加载IOC容器中的组件,容器启动会调用无参构造器创建对象,再进行初始化赋值等操作
注解 | 解析 | 用法 |
@Component | 组件注解,使用了该注解会基于注释的配置和类路径扫描时,会自动扫描并加载Class到ICO容器中 | 注释在类上 |
@Controller | 应用在MVC层(控制层)DispatcherServlet会自动扫描注解了此注解的类,然后将web请求映射到注解了@RequestMapping的方法上 | 注释在类上 |
@Service | 应用在service层(业务逻辑层 | 注释在类上 |
@Repository | 应用在dao层(数据访问层) | 注释在类上 |
1.2依赖注入注解
@Autowired和@Inject、@Resource,可以与@Qualifier或者@Name配合使用,防止多实例注入时出错,以及值注入@Value。
注解 | 解析 | 用法 |
@Autowired | 通过AutowiredAnnotationBeanPostProcessor类实现的依赖注入,默认是根据类型进行注入的,因此如果有多个类型一样的Bean候选者,则需要限定其中一个候选者,否则将抛出异常。 | 可注释在字段上,在方法上 |
@Inject | 作用与@Autowired一样 | 可注释在字段上,在方法上、构造器上 |
@Resource | 默认按照名称进行装配,名称可以通过name属性进行指定 | 可注释在字段上,在方法上 |
@Qualifier | 限定描述符除了能根据名字进行注入,更能进行更细粒度的控制如何选择候选者,可与@Autowired或者@Inject进行组合使用,进行精确注入 | 可注释字段上,在方法上、参数上以及注解中 |
1.3 作用域和生命过程
@Scope,具有4个作用域可看Scope作用域以及涉及的问题章节,以及生命周期过程处理@PostConstruct、@PreDestroy 。
注解 | 解析 | 用法 |
@Scope | 具有4个作用域singleton,prototype,session,request,默认为singleton单例模式 | 可注释在Class创建时 |
@PostConstruct | 相当于init-method,使用在方法上,当Bean初始化时执行 | 可注释在方法上 |
@PreDestroy | 相当于destory-method,使用在方法上,当Bean销毁时执行 | 可注释在方法上 |
1.4 章节用例(结合1.1、1.2、1.3小节)
@Service //组件注入,注明为service组件 @Scope("prototype")//声明Scope为Prototype public class UseFunctionService { @Autowired //默认按type注入 @Qualifier("functionService") //精确注入 FunctionService functionService; @Resource(name="baseDao")//默认按name注入,可以通过name和type属性进行选择性注入 private BaseDao baseDao; @Inject @Qualifier("userServiceImpl") //精确注入 public IUserService userService; @PostConstruct//执行完构造函数后执行 public postConstruct(){ System.out.println("postConstruct"); } @PreDestroy//在销毁Bean前执行 public perDestroy(){ System.out.println("perDestroy"); } @Autowired public void setUserDao(@Qualifier("userDao") UserDao userDao) { this.userDao = userDao; } public String SayHello(String word){ return functionService.sayHello(word); } }
2. 配置注解
2.1 @Configuration配置注解
@Configuration可替换xml配置文件进行配置。被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。可与@PropertySource一起使用。 @Configuration作为元注解延伸了@SpringBootConfiguration
注解 | 解析 | 用法 |
@Configuration | 配置类注解,可以与@Beae、@PropertySource一起使用,进行配置 | 注释在类、接口、枚举上 |
@SpringBootConfiguration | 组合注解,@Configuration配置、@EnableAutoConfiguration启用自动配置、@ComponentScan默认扫描@SpringBootApplication所在类的同级目录以及它的子目录 | 可注解在类上 |
@AutoConfigureAfter | 在指定的自动配置类之后再配置 | 可注解在类上 |
2.2扫描注解
@ComponentScan注解,被@Configuration注解标注的类上面,涉及了@filter过滤器注解
注解 | 解析 | 用法 |
@ComponentScan | 定义扫描的路径,默认就会加载标识了@Controller,@Service,@Repository,@Component注解的类到spring容器中,excludeFilters 指定扫描的时候需要排除的组件,includeFilters 指定扫描的时候只包含的组件 | 可注解在类Class |
@ComponentScans | 包含着@ComponentScan数组 | 可注解在类Class |
@filter | 声明要用作包含过滤器或排除过滤器的类型过滤器 | 可注解在@ComponentScan中 |
2.3 资源、值等注入注解
可以将配置文件、配置文件中的属性、以及系统属性等注入所需的字段中,或者bean中
注解 | 解析 | 用法 |
@Value | 值注入,可以注入普通字符,系统属性,表达式运算结果,其他Bean的属性,文件内容,网址请求内容,配置文件属性值等等 | 可注释在字段上,方法上、参数上 |
@Bean | 声明当前方法的返回值为一个Bean,而且返回的Bean对应的类中可以定义init()方法和destroy()方法,然后在@Bean(initMethod=”init”,destroyMethod=”destroy”)定义,在构造之后执行init,在销毁之前执行destroy | 注解在方法上,注解上 |
@PropertySource | 指定配置文件位置,与@configuration类一起使用 | 注解在类Class、接口上 |
@ImportResource | 加载xml配置文件 | 注解在类Class、接口上 |
@ConfigurationProperties | 将properties属性与一个Bean及其属性相关联 | 可注解在类上、接口上 |
@Import | 用来导入配置类的 | 可注解在类上、接口上 |
2.4 条件注解 @Conditional
@Conditional根据满足某一特定条件创建特定的Bean,基于@Conditional元注解可延伸很多条件注解。
注解 | 解析 | 用法 |
@ConditionalOnBean | Spring容器中是否存在对应的实例,可以通过实例的类型、类名、注解、昵称去容器中查找(可以配置从当前容器中查找或者父容器中查找或者两者一起查找)这些属性都是数组,通过”与”的关系进行查找 | 可注解方法上 |
@ConditionalOnClass | 类加载器中是否存在对应的类,逻辑跟@ConditionalOnBean类似 | 可注解在方法上、类Class、接口上 |
@ConditionalOnExpression | 判断SpEL 表达式是否成立 | 可注解在方法上、类Class、接口上 |
@ConditionalOnJava | 指定Java版本是否符合要求 | 可注解在方法上、类Class、接口上 |
@ConditionalOnMissingBean | Spring容器中是否缺少对应的实例,逻辑跟@ConditionalOnBean类似 | 可注解在方法上、类Class、接口上 |
@ConditionalOnMissingClass | Spring容器中是否缺少对应的实例,逻辑跟@ConditionalOnBean类似 | 可注解在方法上、类Class、接口上 |
@ConditionalOnNotWebApplication | 应用程序是否是非Web程序,没有提供属性,只是一个标识 | 可注解在方法上、类Class、接口上 |
@ConditionalOnProperty | 应用环境中的屬性是否存在,逻辑跟@ConditionalOnBean类似 | 可注解在方法上、类Class、接口上上 |
@ConditionalOnResource | 是否存在指定的资源文件。只有一个属性resources,是个String数组。会从类加载器中去查询对应的资源文件是否存在可注解在方法上、类Class、接口上 | |
@Profile | 指定某个bean属于哪一个profile:spring.profiles.active和spring.profiles.default(默认) | 可注解在方法上,类class、接口上 |
2.5 章节用例(2.1、2.2、2.3、2.4小节)
@Configuration //@SpringBootConfiguration @ComponentScan(value="com.cn",ComponentDefaultFilters=true, includeFilters={ @Filter(type=FilterType.ANNOTATION,classes={Controller.class}), @Filter(type=FilterType.CUSTOM,classes={MyTypeFilter.class}) }) @ImportResource("classpath:condition.xml")//导入xml配置 @Import(ConditionConfig.class)//导入ConditionConfig Class,并会实例化到容器中以及ConditionConfig中的配置也一起注入 public class Config { @Value("I Love You!") //注入普通字符 private String normal; @Value("#{systemProperties['os.name']}") //注入操作系统属性 private String osName; @Value("#{ T(java.lang.Math).random() * 100.0 }") //注入表达式运算结果 private double randomNumber; @Value("#{demoService.another}") //注入其他Bean的属性 private String fromAnother; @Value("classpath:org/light4j/sping4/usually/el/test.txt") //注入文件内容 private Resource testFile; @Value("http://www.baidu.com") //注入网址内容 private Resource testUrl; @Value("${book.name}") //注入属性文件 private String bookName; @Bean//加载bean @Conditional(WindowsCondition.class) // 通过@Conditional注解,符合Windows条件则true @ConditionalOnResource(resources="classpath:windows.ini")//在类路径下是否存在windows.ini文件,存在为true,最后进行注解与操作,为true实例化Bean public ListService windowsListService(){ return new WindowsListService(); } @Bean @ConditionalOnClass(LinuxCondition.class) // 通过@ConditionalOnClass注解,符合Linux条件则true @ConditionalOnProperty(name = "synchronize", havingValue = "true"))//如果synchronize在配置文件中并且值为true public ListService linuxListService(){ return new LinuxListService(); } //加载配置文件中前缀为spring.datasource的属性 @ConfigurationProperties(prefix = "spring.datasource") public DataSource jwcDataSource() { return DataSourceBuilder.create().build(); } @Bean @ConditionalOnMissingClass({LinuxCondition.class,WindowsCondition.class})//当容器中缺失这两个Class时为true @Profile("dev")//在dev环境下为true 最后结果为注解和之与,true实例化该Bean public ListService macListService(){ return new MacListService(); } }
3. 验证注解
验证注解在javax.validation包下:
注解 | 解析 | 用法 |
@Valid | 启动校验,Errors参数要紧跟在带有@Valid注解的参数后面,@Valid注解所标注的就是要检验的参数 | 可注释在字段、方法、构造器、参数上 |
@AssertFalse | 所注解的元素必须是Boolean类型,并且值为false | 可注释在字段、方法、构造器、参数上 |
@AssertTrue | 所注解的元素必须是Boolean类型,并且值为true | 可注释在字段、方法、构造器、参数上 |
@DecimalMax | 所注解的元素必须是数字,并且它的值要小于或等于给定的BigDecimalString值 | 可注释在字段、方法、构造器、参数上 |
@DecimalMin | 所注解的元素必须是数字,并且它的值要大于或等于给定的BigDecimalString值 | 可注释在字段、方法、构造器、参数上 |
@Digits | 所注解的元素必须是数字,并且它的值必须有指定的位数 | 可注释在字段、方法、构造器、参数上 |
@Future | 所注解的元素的值必须是一个将来的日期 | 可注释在字段、方法、构造器、参数上 |
@Max | 所注解的元素必须是数字,并且它的值要小于或等于给定的值 | 可注释在字段、方法、构造器、参数上 |
@Min | 所注解的元素必须是数字,并且它的值要大于或等于给定的值 | 可注释在字段、方法、构造器、参数上 |
@NotNull | 所注解元素的值必须不能为null | 可注释在字段、方法、构造器、参数上 |
@Null | 所注解元素的值必须为null | 可注释在字段、方法、构造器、参数上 |
@Past | 所注解的元素的值必须是一个已过去的日期 | 可注释在字段、方法、构造器、参数上 |
@Pattern | 所注解的元素的值必须匹配给定的正则表达式 | 可注释在字段、方法、构造器、参数上 |
@Size | 所注解的元素的值必须是String、集合或数组,并且它的长度要符合给定的范围 | 可注释在字段、方法、构造器、参数上 |
4.AOP
4.1 AspectJ的注解式切面编程:
AspectJ的注解式在org.aspectj包下
注解 | 解析 | 用法 |
@Aspect | 声明该类是一个切面 | 可注解在类Class、接口上 |
@After | 通知方法会在目标方法返回或抛出异常后调用 | 可注解在方法上 |
@Before | 通知方法会在目标方法调用之前执行 | 可注解在方法上 |
@Around | 通知方法会将目标方法封装起来 | 可注解在方法上 |
@AfterReturning | 通知方法会在目标方法返回后调用 | 可注解在方法上 |
@AfterThrowing | 通知方法会在目标方法抛出异常后调用 | 可注解在方法上 |
@Pointcut | 能够在一个@AspectJ切面内定义可重用的切点,(通过@Pointcut注解声明频繁使用的切点表达式) | 可注解在方法上 |
@annotation | 限定匹配带有指定注解的连接点 | 可注解在建言(advice)上,如@After等 |
@EnableAspectJAutoProxy | 开启Spring对AspectJ的支持,在配置类上 | 可注解在类Class、接口上 |
4.2 AspectJ指示器
execution指示器是我们在编写切点定义时最主要使用的指示器:
注解 | 解析 | 用法 |
AspectJ指示器 | 描 述 | |
arg() | 限制连接点匹配参数为指定类型的执行方法 | 可注释在AspectJ的注解式、如@After等 |
@args() | 限制连接点匹配参数由指定注解标注的执行方法可注释在AspectJ的注解式,如@After等 | |
execution() | 用于匹配是连接点的执行方法 | 可注释在AspectJ的注解式,如@After等 |
this() | 限制连接点匹配AOP代理的bean引用为指定类型的类 | 可注释在AspectJ的注解式,如@After等 |
Target | 限制连接点匹配目标对象为指定类型的类可注释在AspectJ的注解式,如@After等 | |
@target() | 限制连接点匹配特定的执行对象,这些对象对应的类要具有指定类型的注解 | 可注释在AspectJ的注解式,如@After等 |
within() | 限制连接点匹配指定的类型 | 可注释在AspectJ的注解式,如@After等 |
@within() | 限制连接点匹配指定注解所标注的类型(当使用Spring AOP时,方法定义在由指定的注解所标注的类里) | 可注释在AspectJ的注解式,如@After等 |
4.3 用例:编写切面
@Aspect //声明该类是一个切面 @Component public class LogAspect { private final String POINT_CUT ="execution(* org.sping4.ccww.aop.DemoMethodService.*(..))"; @Pointcut("@annotation(org.ccww.sping4.base.aop.Action)") //声明切面 public void annotationPointCut(){}; @After("annotationPointCut()") //声明一个建言,并使用@Pointcut定义的切点 public void after(JoinPoint joinPoint) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); Action action = method.getAnnotation(Action.class); System.out.println("注解式拦截 " + action.name()); //⑤ } @Before("execution(* org.sping4.ccww.aop.DemoMethodService.*(..))")//声明一个建言,此建言直接使用拦截规则作为参数 public void before(JoinPoint joinPoint){ MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); System.out.println("方法规则式拦截,"+method.getName()); } /** * 后置返回 * 如果第一个参数为JoinPoint,则第二个参数为返回值的信息 * 如果第一个参数不为JoinPoint,则第一个参数为returning中对应的参数 * returning:限定了只有目标方法返回值与通知方法参数类型匹配时才能执行后置返回通知,否则不执行, * 参数为Object类型将匹配任何目标返回值 */ @AfterReturning(value = POINT_CUT,returning = "result") public void doAfterReturningAdvice1(JoinPoint joinPoint,Object result){ System.out.println("第一个后置返回通知的返回值:"+result); } }
5. Spring MVC
注解 | 解析 | 用法 |
@EnableWebMvc | 会开启一些默认配置,如一些ViewResolver或者MessageConverter等 | 可注解在类Class、接口上 |
@RequestMapping | 用来映射Web请求(访问路径和参数),处理类和方法的(即配置URL和方法之间的映射),注解在方法上的@RequestMapping路径会继承注解在类上的路径 | 可注解在类Class、接口上、方法上 |
@ResponseBody | 支持将返回值放在response体内 | 可注解在返回值前或者方法上 |
@RequestBody | 允许requ | est的参数在request体内 |
@PathVariable | 用来接收路径参数,如/ccww/003,可接收003作为参数 | 可注解在参数前 |
@RestController | 组合注解,组合了@Controller和@ResponseBody,这就意味着当你只开发一个和页面交互数据的控制的时候,需要使用此注解。若没有此注解,要想实现上述功能,则需要自己在代码中加@Controller和@ResponseBody两个注解 | 可注解在类Class、接口上 |
@ModelAttribute | 绑定请求参数到命令对象、暴露@RequestMapping 方法返回值为模型数据、暴露表单引用对象为模型数据 | 可注解在方法、参数上 |
用例:
@Controller //声明此类是一个控制器 @RequestMapping("/ccww") //映射此类的访问路径是/ccww //@RestController // 使用@RestController,声明是控制器,并且返回数据时不需要@ResponseBody //@RequestMapping("/ccww") public class DemoAnnoController { //此方法未标注路径,因此使用类级别的路径/anno;produces可定制返回的response的媒体类型和字符集,或返回值是json对象,则设置porduces="application/json;charset=UTF-8" @RequestMapping(produces = "text/plain;charset=UTF-8") public @ResponseBody String index(HttpServletRequest request) { //可接受HttpServletRequest作为参数,当然也可以接受HttpServletResponse作为参数。此处的@ResponseBody用在返回值前 return "url:" + request.getRequestURL() + " can access"; } @RequestMapping(value = "/demoPathVar/{str}", produces = "text/plain;charset=UTF-8")// public @ResponseBody String demoPathVar(@PathVariable String str, //接受路径参数,并在方法参数前结合@PathVariable使用,访问路径为/ccww/demoPathVar/xxx HttpServletRequest request) { return "url:" + request.getRequestURL() + " can access,str: " + str; } //常规的request参数获取,访问路径为/ccww/requestParam?id=1 @RequestMapping(value = "/requestParam", produces = "text/plain;charset=UTF-8") public @ResponseBody String passRequestParam(Long id, HttpServletRequest request) { return "url:" + request.getRequestURL() + " can access,id: " + id; } @RequestMapping(value = "/obj", produces = "application/json;charset=UTF-8") @ResponseBody // 可注解在方法上 public String passObj(DemoObj obj, HttpServletRequest request) { return "url:" + request.getRequestURL() + " can access, obj id: " + obj.getId()+" obj name:" + obj.getName(); } //映射不同的路径到相同的方法,访问路径为/anno/name1或/anno/name2 @RequestMapping(value = { "/name1", "/name2" }, produces = "text/plain;charset=UTF-8") public @ResponseBody String remove(HttpServletRequest request) { return "url:" + request.getRequestURL() + " can access"; } @RequestMapping(value = "/helloWorld") //以“user”为名称添加到模型对象中供视图页面展示使用 public String helloWorld(@ModelAttribute User user) { return "helloWorld"; } }
6.Spring security
Spring security用户访问认证和授权,两个关键注解:
注解 | 解析 | 用法 |
@EnableWebSecurityConfig | 该注解和@Configuration注解一起使用,注解 WebSecurityConfigurer类型的类,或者利用@EnableWebSecurity注解继承WebSecurityConfigurerAdapter的类,这样就构成了Spring Security的配置 | 可注解在Class上 |
@EnableGlobaleMethodSecurity | Spring security默认是禁用注解的,要想开启注解,需要继承WebSecurityConfigurerAdapter的类上加@EnableGlobalMethodSecurity注解,来判断用户对某个控制层的方法是否具有访问权限 | 可注释在Class上 |
用@EnableGlobaleMethodSecurity的参数想要开启注解:
- @EnableGlobalMethodSecurity(securedEnabled=true):开启@Secured注解过滤权限
- @EnableGolablMethodSecurity(jsr250Enabled=true):开启@RolesAllowed注解过滤权限
- @EnableGlobalMethodSecurity(prePostEnable=true):使用Spring_EL表达式控制更细粒度的访问控制
具体开启注解解析如下:
注解 | 解析 | 用法 |
@Secured | 认证是否有权限访问 | 可注解方法上 |
@RolesAllowed | 该方法只要具有其参数中任意一种权限就可以访问(可以省略前缀ROLE_) | 可注解在方法上 |
@DenyAll | 拒绝所有访问 | 可注解在方法上 |
@PermitAll | 允许所有访问 | 可注解在方法上 |
@PreAuthorize | 在方法执行之前执行,而且这里可以调用方法的参数,也可以得到参数值。 @PreAuthorize注解会在方法执行前进行权限验证,支持Spring EL表达式,它是基于方法注解的权限解决方案。只有当@EnableGlobalMethodSecurity(prePostEnabled=true)的时候,@PreAuthorize才可以使用,@EnableGlobalMethodSecurity注解在SPRING安全中心进行设置 | 可注解在方法上 |
@PostAuthorize | 在方法执行之后执行,而且这里可以调用方法的返回值,如果EL为false,那么该方法也已经执行完了,可能会回滚 | 可注解在方法上 |
@PreFilter | 在方法执行之前执行,而且这里可以调用方法的参数,然后对参数值进行过滤或处理,EL变量filterObject表示参数,如果有多个参数,使用filterTarget注解参数 | 可注解在方法上 |
@PostFilter | 在方法执行之后执行,而且这里可以通过表达式来过滤方法的结果 | 可注解在方法上 |
用例:
两个关键注解@EnableWebSecurityConfig、@EnableGlobaleMethodSecurity:
@Configuration
@EnableWebSecurity//开启webSecurityConfig
@EnableGlobalMethodSecurity(prePostEnabled = true.securedEnabled = true)//可开启多个注解
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
.....
}
其他注解:
@Secured("IS_AUTHENTICATED_ANONYMOUSLY")//@Secured注解,匿名访问 public Account readAccount(Long id){ ... } @Secured("ROLE_TELLER")//@Secured注解具有TELLER访问 public Account readAccount(Long id){ ... } @PreAuthorize("#userId==authentication.principal.userId or hasAuthority('ADMIN')") //利用Spring Security的@P标注参数,或者Spring Data的@Param标注参数来接收@PreAuthorize的返回值 public void changPassword(@P("userId")long userId){ ... } @PreAuthorize("hasAuthority('ADMIN')")//PreAuthorize是否具有admin角色 public void changePassword(long userId){ ... }
#######################################
例子2:如何使用
①. 注解如何使用?
/**
* 删除用户
*/
@PreAuthorize("@ss.hasPermi('system:user:remove')")
@Log(title = "用户管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{userIds}")
public Result remove(@PathVariable Long[] userIds) {
if (ArrayUtils.contains(userIds, getUserId())) {
return error("当前用户不能删除");
}
return toAjax(userService.deleteUserByIds(userIds));
}
②. 自定义权限实现
@PreAuthorize(“@ss.hasPermi(‘system:user:remove’)”)的意思是什么?
- A. ss 是一个注册在 Spring容器中的BEAN,对应的类是cn.hadoopx.framework.web.service.PermissionService;
- B. hasPermi 是PermissionService类中定义的方法;
- C.当Spring EL 表达式返回TRUE,则权限校验通过;
- D. PermissionService.java的定义如下:
/**
* 自定义权限实现,ss取自SpringSecurity首字母
* @author ROCKY
*/
@Service("ss")
public class PermissionService {
/**
* 所有权限标识
*/
private static final String ALL_PERMISSION = "*:*:*";
/**
* 管理员角色权限标识
*/
private static final String SUPER_ADMIN = "admin";
private static final String ROLE_DELIMETER = ",";
private static final String PERMISSION_DELIMETER = ",";
/**
* 验证用户是否具备某权限
* @param permission 权限字符串
* @return 用户是否具备某权限
*/
public boolean hasPermi(String permission) {
if (StringUtils.isEmpty(permission)) {
return false;
}
LoginUser loginUser = SecurityUtils.getLoginUser();
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) {
return false;
}
return hasPermissions(loginUser.getPermissions(), permission);
}
/**
* 验证用户是否不具备某权限,与 hasPermi逻辑相反
* @param permission 权限字符串
* @return 用户是否不具备某权限
*/
public boolean lacksPermi(String permission) {
return hasPermi(permission) != true;
}
/**
* 验证用户是否具有以下任意一个权限
* @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表
* @return 用户是否具有以下任意一个权限
*/
public boolean hasAnyPermi(String permissions) {
if (StringUtils.isEmpty(permissions)) {
return false;
}
LoginUser loginUser = SecurityUtils.getLoginUser();
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) {
return false;
}
Set<String> authorities = loginUser.getPermissions();
for (String permission : permissions.split(PERMISSION_DELIMETER)) {
if (permission != null && hasPermissions(authorities, permission)) {
return true;
}
}
return false;
}
/**
* 判断用户是否拥有某个角色
* @param role 角色字符串
* @return 用户是否具备某角色
*/
public boolean hasRole(String role) {
if (StringUtils.isEmpty(role)) {
return false;
}
LoginUser loginUser = SecurityUtils.getLoginUser();
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) {
return false;
}
for (SysRole sysRole : loginUser.getUser().getRoles()) {
String roleKey = sysRole.getRoleKey();
if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role))) {
return true;
}
}
return false;
}
/**
* 验证用户是否不具备某角色,与 isRole逻辑相反。
* @param role 角色名称
* @return 用户是否不具备某角色
*/
public boolean lacksRole(String role) {
return hasRole(role) != true;
}
/**
* 验证用户是否具有以下任意一个角色
* @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表
* @return 用户是否具有以下任意一个角色
*/
public boolean hasAnyRoles(String roles) {
if (StringUtils.isEmpty(roles)) {
return false;
}
LoginUser loginUser = SecurityUtils.getLoginUser();
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) {
return false;
}
for (String role : roles.split(ROLE_DELIMETER)) {
if (hasRole(role)) {
return true;
}
}
return false;
}
/**
* 判断是否包含权限
* @param permissions 权限列表
* @param permission 权限字符串
* @return 用户是否具备某权限
*/
private boolean hasPermissions(Set<String> permissions, String permission) {
return permissions.contains(ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission));
}
}
7. Spring Boot
注解 | 解析 | 用法 |
@SpringBootApplication | Spring Boot核心注解,组合注解(@Configuration、@EnableAutoConfiguration、@ComponentScan),主要是为了开启自动配置 | 注解在Class,接口 |
@EnableAutoConfiguration | 让Spring Boot根据类路径中的jar包依赖为当前项目进行自动配置 | 可注释在Class |
参考:
推荐收藏系列:Spring boot 2.x注解Annotation大全(持续更新....)-阿里云开发者社区