注解
1.什么是注解(annotation)
最常见的注解就是@Override 覆盖超类的方法。
注解和源码结合在一起,可以经过编译和测试,附带有额外的功能。
自定义注解可以搭配注解处理器生成一些特定的信息和功能。
注解可以使代码变得更加简洁和比编译器的类型检查等。
2.注解的基本知识
注解主要有四种元注解,主要作用就是为了创建新的注解
@Target @Retention @Documented @Inherited
2.1 @Target
@Target(ElementType.XXXX)
主要是表示该注解可以用在什么地方
可选参数有
可选参数 | 说明 |
ElementType.CONSTRUCTOR | 构造函数的声明 |
ElementType.FIELD | 成员变量的声明(包含enum) |
LOCAL_VARIABLE | 局部变量的声明 |
METHOD | 方法的声明 |
PACKAGE | 包声明 |
PARAMETER | 参数声明 |
TYPE | 类、接口(包括注解类型) 或enum声明 |
2.2 @Retention
@Retention主要是表示该注解保存到什么级别
可选参数 | 说明 |
RetentionPolicy.Source | 注释将被编译器丢弃 |
RetentionPolicy.Class | 注解在class中可用,但是还是会被JVM所丢弃 |
RetentionPolicy.RunTime | JVM也会保存相关信息,因此可以通过反射得到相关信息 |
2.3 @Documented @Inherited
这两个注解就比较好理解了,@Documented的注解会包含在JavaDoc中。
而@Inherited表明该注解允许子类继承父类中的注解.
3.自定义参数解析器
自定义参数解析器主要要实现HandlerMethodArgumentResolver接口
public interface HandlerMethodArgumentResolver {
boolean supportsParameter(MethodParameter var1);
@Nullable Object resolveArgument(MethodParameter var1,
@Nullable ModelAndViewContainer var2,
NativeWebRequest var3,
@Nullable WebDataBinderFactory var4) throws Exception;
}
该接口的源码显示,主要有两个方法。
一个是supportsParameter
一个是resolveArgument
3.1 supportsParameter
public boolean supportsParameter(@Nullable MethodParameter parameter) {
return parameter != null && parameter.getParameterAnnotation(CurrTownAdmin.class) != null && parameter.getParameterType() == (TownshipAdmin.class);
}
//这是代码中出现的supportsParameter
//这里是首先检查不为空,标签是否是CurrTownAdmin,类型是否是TownShipAdmin
按照源码的提示
/**
* Whether the given {@linkplain MethodParameter method parameter} is
* supported by this resolver.
* @param parameter the method parameter to check
* @return {@code true} if this resolver supports the supplied parameter;
* {@code false} otherwise */
大意是:给定的自定义注解可以通过此参数解析器进行处理参数
parameter是需要检查的参数
如果是该参数解析器支持的参数则会返回,如果不支持则返回false
3.2 resolveArgument
源码注释如下:
/**
* Resolves a method parameter into an argument value from a given request.
* A {@link ModelAndViewContainer} provides access to the model for the request.
* A {@link WebDataBinderFactory} provides a way to create
* A {@link WebDataBinder} instance when needed for data binding and type conversion purposes.
* @param parameter the method parameter to resolve. This parameter must have previously been passed to {@link #supportsParameter} which must have returned {@code true}.
* @param mavContainer the ModelAndViewContainer for the current request
* @param webRequest the current request
* @param binderFactory a factory for creating {@link WebDataBinder} instances
* @return the resolved argument value, or {@code null} if not resolvable
* @throws Exception in case of errors with the preparation of argument values
*/
大意是:
从给定的请求中将方法参数转为指定的参数值
ModelAndViewContainer 对这个请求提供一个模型
WebDataBinderFactory 去创建WebDataBinder 当需要日期绑定和类型转换的目的
parameter 是经过上面supprotsParameter且必须要返回true
mavContainer 当前请求的视图解析器
webRequest 当前的请求主体
binderFactory 是一个工厂提供创建WebDataBinder实例
return 返回解析处理过后的值或者如果解析失败返回空
代码实例:
@Override
public Object resolveArgument(@Nullable MethodParameter parameter, ModelAndViewContainer mavContainer, @Nullable NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
if (webRequest != null) {
Object request = webRequest.getNativeRequest();
if (request instanceof HttpServletRequest) {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpSession session = httpServletRequest.getSession(false);
Object result;
if (session == null || (result = session.getAttribute(Constant.CURR_TOWN_ADMIN)) == null) {
throw new NoLoginException();
}
return result;
}
}
return null;
}
主要目的就是返回session中的currAdmin对象
写完注解解析器后,需要加入到Configuration类里面
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers)
{
argumentResolvers.add(new CurrMainAdminArgumentResolver());
argumentResolvers.add(new CurrTownAdminArgumentResolver());
}
Sprintboot启动类进行扫描即可
写完后,直接声明注解后使用即可
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface CurrTownAdmin {
}
public Map<String, Object> appraiseCycleList(@CurrTownAdmin MainAdmin currAdmin) {}
综上:通过这个自定义注解+自定义参数处理解析器,可以不用频繁的取出session中的user等信息。直接使用标签即可