java 自定義注解
在項目開發的過程中我們能遇到的自定義注解一般分為兩類:
- 通過自定義注解自動擷取參數值。比如:@LoginUser
-
通過自定義注解做驗證。比如 驗簽,token驗證
上面兩類最大的差別就是一個需要傳回值一個不需要傳回值。
接下來我将對如上兩類自定義的處理方法進行實際的實作,自定義的基礎理論可以在網上查找一下,我這裡就不做詳細的介紹。
第一類 @Loguser
實作分為三步:
- 定義一個注解@LoginUser
- 建立一個LoginUser注解的解析器
- 建立一個配置類(在WebMvcConfigurer )
定義一個注解
注意: Target
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginUser {
}
建立一個LoginUser注解的解析器
@Component
public class LoginUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Autowired
private LoginService loginService;
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().isAssignableFrom(User.class) && parameter.hasParameterAnnotation(LoginUser.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer container,NativeWebRequest request, WebDataBinderFactory factory) throws Exception {
Long cUserId=(Long) request.getAttribute(Constants.CURRENT_USER_ID,RequestAttributes.SCOPE_REQUEST);
if (cUserId>0) {
User user = loginService.getUserById(cUserId);
if(user == null) {
throw new RuntimeException(i18nService.getMessage("user.not.exist"));
}
//重點是這裡傳回對象
return user;
}
}
}
建立一個配置類
@Configuration
public class LoginUserConfigurer implements WebMvcConfigurer {
//必須用注入方式,不能用new,否則此對象内部屬性無法被注入
@Autowired
private LoginUserHandlerMethodArgumentResolver loginUserHandlerMethodArgumentResolver;
/**
* 配置自定義參數解析器
*/
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(loginUserHandlerMethodArgumentResolver);
}
}
直接可以在代碼裡面使用
public ResponseResult saveServiceInfo(@LoginUser User loginUser) {
// 下面直接擷取資料
loginUser.getUsername();
}
第二類 驗證
- 先定義注解
- 定義一個切面
- 直接使用
定義注解
注意: Target
import java.lang.annotation.*;
@Target({ElementType.METHOD,ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ValidatedSignature {
String value() default "";
}
定義切面
Aspect
@Component
@SuppressWarnings({"unused"})
public class ValidatedSignatureAspect {
public static final Logger logger = LoggerFactory.getLogger(ValidatedSignature.class);
public static final String TOKEN_KEY = "token";
/**
* checkUrl,keyUrl,tokenScope是通過Spring的@Value注解來擷取配置檔案中的配置項
*
* @Value等同于Spring原先的配置模式中的value <bean id="" class="">
* <property name="" value="">
* </bean>
*/
@Pointcut("@annotation(com.louis.kitty.admin.annotation.ValidatedSignature)")
public void annotationPointcut() {
logger.info("annotationPointcut()");
}
@Before("annotationPointcut()")
public void beforePointcut(JoinPoint joinPoint) {
// 此處進入到方法前 可以實作一些業務邏輯
logger.info("beforePointcutJoinPoint joinPoint)");
}
@Around("annotationPointcut()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
logger.info("doAround(ProceedingJoinPoint joinPoint)");
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
String[] params = methodSignature.getParameterNames();// 擷取參數名稱
Class[] paramsType = methodSignature.getParameterTypes();
Object[] args = joinPoint.getArgs();// 擷取參數值
JSONObject jsonObj=new JSONObject();
for (int index=0;index<params.length;index++) {
jsonObj.put(params[index],args[index]);
}
logger.info(jsonObj.toJSONString());
int size1=params.length;
int size2=paramsType.length;
int size3=args.length;
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
String token = request.getHeader("token");
// if (null == params || params.length == 0) {
// String mes = "Using Token annotation, the token parameter is not passed, and the parameter is not valid.";
// logger.info(mes);
// throw new Exception(mes);
// }
// boolean hasToken = false;
// int index = 0;
// for (int i = 0; i < params.length; i++) {
// if (TOKEN_KEY.equals(params[i])) {
// hasToken = true;
// index = i;
// break;
// }
// }
// if (!hasToken) {
// String mes = "The token parameter is not included in the requested parameter, the parameter is not valid.";
// logger.info(mes);
// throw new Exception(mes);
// }
return jsonObj;
// return joinPoint.proceed();
}
/**
* 在切入點return内容之後切入内容(可以用來對處理傳回值做一些加工處理)
*
* @param joinPoint
*/
@AfterReturning("annotationPointcut()")
public void doAfterReturning(JoinPoint joinPoint) {
logger.info("doAfterReturning(JoinPoint joinPoint)");
}
}
代碼直接使用
@ValidatedSignature
public ResponseResult saveServiceInfo() {
}