Spring——自定义注解
1.参数注解
注解
/**
- 字段参数注解
* - @author A.keung
- 2019/8/30 0030
@Constraint 通过使用validatedBy指定与注解关联的验证器
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ParamsCheckConstraintValidator.class)
public @interface ParamsCheck {
//参数
String[] paramValues();//提示
String message() default “params error”;Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
- 字段参数注解
验证器
/**
- 字段参数注解验证器
* - @author A.keung
2019/8/30 0030
*/
public class ParamsCheckConstraintValidator implements ConstraintValidator{
//注解参数
private ListparamValues; @Override
public void initialize(ParamsCheck paramsCheck) {//初始化时获取注解上的值
paramValues = Arrays.asList(paramsCheck.paramValues());
}
@Override
public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {return paramValues.contains(o);
}
}
- 字段参数注解验证器
测试
@RequestMapping(value = “testParamsCheck”,method = RequestMethod.POST)
public String testParamsCheck(@Validated @RequestBody User user) {
log.info(JSON.toJSONString(user));
return "OK";
}
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@TableName(“t_user”)
@NoArgsConstructor
//@AllArgsConstructor
public class User extends BaseEntity{/**
* 密码
*/
@TableField("password")
private String password;
/**
* 手机
*/
@TableField("phone_number")
private String phoneNumber;
/**
* 邮箱
*/
@TableField("email")
private String email;
/**
* 昵称
*/
@TableField("nickname")
private String nickname;
/**
* 权限
*/
@ParamsCheck(paramValues = {"ADMIN","USER"})
@TableField("role")
private String role;
/**
* qqOpenId
*/
@TableField("qq_open_id")
private String qqOpenId;
/**
* 头像地址
*/
@TableField("figure_url")
private String figureUrl;
/**
* 是否启用
*/
@TableField("enable")
private Boolean enable;
private User(Builder builder) {
setId(builder.id);
setCreatedDatetime(builder.createdDatetime);
setModifiedDatetime(builder.modifiedDatetime);
setPassword(builder.password);
setPhoneNumber(builder.phoneNumber);
setEmail(builder.email);
setNickname(builder.nickname);
setRole(builder.role);
setQqOpenId(builder.qqOpenId);
setFigureUrl(builder.figureUrl);
setEnable(builder.enable);
}
public static final class Builder {
private Long id;
private Date createdDatetime;
private Date modifiedDatetime;
private String password;
private String phoneNumber;
private String email;
private String nickname;
private String role;
private String qqOpenId;
private String figureUrl;
private Boolean enable;
public Builder() {
}
public Builder id(Long val) {
id = val;
return this;
}
public Builder createdDatetime(Date val) {
createdDatetime = val;
return this;
}
public Builder modifiedDatetime(Date val) {
modifiedDatetime = val;
return this;
}
public Builder password(String val) {
password = val;
return this;
}
public Builder phoneNumber(String val) {
phoneNumber = val;
return this;
}
public Builder email(String val) {
email = val;
return this;
}
public Builder nickname(String val) {
nickname = val;
return this;
}
public Builder role(String val) {
role = val;
return this;
}
public Builder qqOpenId(String val) {
qqOpenId = val;
return this;
}
public Builder figureUrl(String val) {
figureUrl = val;
return this;
}
public Builder enable(Boolean val) {
enable = val;
return this;
}
public User build() {
return new User(this);
}
}
}
" class="reference-link">
2.缓存注解
注解
/**
- 部门缓存注解
* - @author A.keung
- 2019/8/30 0030
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DeptCache {
//#user.name或jack
String keyExpr();
}
- 部门缓存注解
切面
/**
- 部门缓存切面
* - @author A.keung
2019/8/30 0030
*/
@Component
@Aspect
@Slf4j
public class DeptCacheAspect {/**
- 对含有注解的方法进行处理
* - @param joinPoint
@return 返回值
*/
@Around(“@annotation(com.ak.common.DeptCache)”)
public Object process(ProceedingJoinPoint joinPoint) throws NoSuchMethodException {
Object result = null;
// 获取切入的方法对象
// 代理对象的,没有包含注解
Method m = ((MethodSignature) joinPoint.getSignature()).getMethod();
// 目标对象反射获取的method对象才包含注解
Method methodWithAnnotations = joinPoint.getTarget().getClass().getDeclaredMethod(joinPoint.getSignature().getName(), m.getParameterTypes());
// 根据目标方法对象获取注解对象
DeptCache deptCache = methodWithAnnotations.getDeclaredAnnotation(DeptCache.class);
// 解析key
String keyExpr = deptCache.keyExpr();
Object[] argValues = joinPoint.getArgs();
String key = parseKey(methodWithAnnotations, argValues, keyExpr);
//根据key查询缓存
String cache = findCache(key);
if (StringUtils.isNotBlank(cache)) {return cache;
}
//执行目标方法
try {result = joinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return result;
}/**
- 解析key(只支持String)
* - @param method
- @param argValues 方法参数值
- @param keyExpr 注解值或表达式(含#)
- @return key
@throws IllegalAccessException
*/
private String parseKey(Method method, Object[] argValues, String keyExpr) {
if (keyExpr.startsWith(“#”)) {String[] exprParamNames = keyExpr.substring(keyExpr.indexOf('#') + 1).split("\\.");
// 获取方法参数名列表
LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
String[] paramNames = discoverer.getParameterNames(method);
Object argValue = null;
for (int i = 0; i < paramNames.length; i++) {
if (paramNames[i].equals(exprParamNames[0])) {
argValue = argValues[i];
break;
}
}
try {
for (int i = 1; i < exprParamNames.length; i++) {
argValue = dealArg(argValue, exprParamNames[i]);
}
if (argValue instanceof String) {
return (String) argValue;
}
} catch (IllegalAccessException e) {
log.info("keyExpr:{}" + keyExpr);
throw new RuntimeException("无法解析表达式:" + e.getMessage());
}
throw new RuntimeException("无法解析表达式");
} else {
return keyExpr;
}
}private Object dealArg(Object object, String fieldName) throws IllegalAccessException {
if (object == null) {return null;
}
Class clazz = object.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {//属性可见
field.setAccessible(true);
if (fieldName.equals(field.getName())) {
return field.get(object);
}
}
return null;
}
- 对含有注解的方法进行处理
- 部门缓存切面
private String findCache(String key) {
double k = Math.random();
log.info("k======"+k);
if (k < 0.5) {
return key + "_lt_0.5";
}
return null;
}
测试
@RequestMapping(value = “testDeptCache”,method = RequestMethod.GET)
@DeptCache(keyExpr = "#user.nickname")
public String testDeptCache(User user) {
return "OK";
}
" class="reference-link">
3.权限注解
注解
/**
- 权限注解
* - @author A.keung
- 2019/8/30 0030
*/
@Target({ ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PermissionCheck {
String[] values() default {};
}
- 权限注解
拦截器
/**
- 权限注解拦截器
* - @author A.keung
2019/8/30 0030
*/
public class PermissionCheckInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {if (!handler.getClass().isAssignableFrom(HandlerMethod.class)) {
return true;
}
PermissionCheck permission = findPermissionCheck((HandlerMethod) handler);
//无权限注解
if (permission == null) {
return true;
}
//获取注解中的值
String[] values = permission.values();
//获取用户权限
Map<String, String> userPermission = findUserPermission();
for (String value : values) {
if (userPermission.containsKey(value)) {
return true;
}
}
throw new Exception("No Permission");
}
/**
- 模拟获取权限集
* @return 权限集
*/
private MapfindUserPermission() {
MappermissionMap = new HashMap<>();
permissionMap.put(“SELECT”, “”);
permissionMap.put(“UPDATE”, “”);
permissionMap.put(“DELETE”, “”);
return permissionMap;
}/**
- 获取注解信息
* - @param handlerMethod 方法对象
- @return PermissionCheck注解
*/
private PermissionCheck findPermissionCheck(HandlerMethod handlerMethod) {
//方法上注解
PermissionCheck permission = handlerMethod.getMethodAnnotation(PermissionCheck.class);
if (permission == null) {
}//类上注解
permission = handlerMethod.getBeanType().getAnnotation(PermissionCheck.class);
return permission;
}
}
- 权限注解拦截器
配置
/**
- Mvc配置类
- 在SpringBoot2.0之后的版本中WebMvcConfigurerAdapter过时了
- 采用以下方式:
- 1.继承WebMvcConfigurationSupport类
- 静态资源的访问的问题,在静态资源的访问的过程中,
- SpringBoot中的自动的配置会失效,不需要返回逻辑视图,可以选择继承此类
- 继承WebMvcConfigurationSupport,若多个类继承该类,只会有一个类中的重写的方法执行
- 2.实现WebMvcConfigurer接口
- @author A.keung
2019/8/30 0030
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Override
public void addInterceptors(InterceptorRegistry interceptorRegistry) {interceptorRegistry.addInterceptor(new PermissionCheckInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/index/**","/api/login");
}
@Override
public void configurePathMatch(PathMatchConfigurer pathMatchConfigurer) {}
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer contentNegotiationConfigurer) {}
@Override
public void configureAsyncSupport(AsyncSupportConfigurer asyncSupportConfigurer) {}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer defaultServletHandlerConfigurer) {}
@Override
public void addFormatters(FormatterRegistry formatterRegistry) {}
@Override
public void addResourceHandlers(ResourceHandlerRegistry resourceHandlerRegistry) {}
@Override
public void addCorsMappings(CorsRegistry corsRegistry) {}
@Override
public void addViewControllers(ViewControllerRegistry viewControllerRegistry) {}
@Override
public void configureViewResolvers(ViewResolverRegistry viewResolverRegistry) {}
@Override
public void addArgumentResolvers(Listlist) { }
@Override
public void addReturnValueHandlers(Listlist) { }
@Override
public void configureMessageConverters(List> list) { }
@Override
public void extendMessageConverters(List> list) { }
@Override
public void configureHandlerExceptionResolvers(Listlist) { }
@Override
public void extendHandlerExceptionResolvers(Listlist) { }
@Override
public Validator getValidator() {return null;
}
@Override
public MessageCodesResolver getMessageCodesResolver() {return null;
}
}
测试
@PermissionCheck(values = “SELECT”)
@RequestMapping(value = "testPermissionCheck",method = RequestMethod.GET)
public String testPermissionCheck() {
return "OK";
}
还没有评论,来说两句吧...