获取指定类上的@RequestMapping注解的请求信息
Posted longfei2012
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了获取指定类上的@RequestMapping注解的请求信息相关的知识,希望对你有一定的参考价值。
通过上一篇博客,我们能够轻松的得到制定类上的制定注解。现在,我们尝试获取指定类上的@RequestMapping注解,并获取该控制层的全部请求信息。在这里,提供一个实体类,用于存放请求的部分信息。
public class RequestUrlInfo implements Comparable<RequestUrlInfo>{ private String name; //mapping的名称 private String value; //mapping的请求路径 private RequestMethod requestMethod; //响应请求的方法 public RequestUrlInfo() { } public RequestUrlInfo(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } public RequestMethod getRequestMethod() { return requestMethod; } public void setRequestMethod(RequestMethod requestMethod) { this.requestMethod = requestMethod; } @Override public String toString() { return "RequestUrlInfo [name=" + name + ", value=" + value + ", requestMethod=" + requestMethod + "]" + "\n"; } /** * 根据请求路径对请求信息进行区分。 */ @Override public int compareTo(RequestUrlInfo o) { return this.value.compareTo(o.getValue()); } }
在这里,为了后续的排序操作,实现Comparable接口,并根据请求路径进行排序依据。
接下来,就是获取指定类的RequestMapping注解信息。通过以下代码,能够轻松的获取类级别以及方法级别的注解。
Annotation classAnnotation = AnnotationHelper.getInstance().getClassAnnotation(scannerClass, RequestMapping.class); List<Annotation> methodAnnotations = AnnotationHelper.getInstance().getMethodAnnotation(scannerClass, RequestMapping.class);
现在,注解已经得到,需要通过得到的注解,获取该注解相关的信息。要获取RequestMapping注解的信息,就需要了解该注解的相关信息。
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Mapping public @interface RequestMapping { /** * Assign a name to this mapping. * <p><b>Supported at the type level as well as at the method level!</b> * When used on both levels, a combined name is derived by concatenation * with "#" as separator. * @see org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder * @see org.springframework.web.servlet.handler.HandlerMethodMappingNamingStrategy */ String name() default ""; /** * The primary mapping expressed by this annotation. * <p>In a Servlet environment this is an alias for {@link #path}. * For example {@code @RequestMapping("/foo")} is equivalent to * {@code @RequestMapping(path="/foo")}. * <p>In a Portlet environment this is the mapped portlet modes * (i.e. "EDIT", "VIEW", "HELP" or any custom modes). * <p><b>Supported at the type level as well as at the method level!</b> * When used at the type level, all method-level mappings inherit * this primary mapping, narrowing it for a specific handler method. */ @AliasFor("path") String[] value() default {}; /** * In a Servlet environment only: the path mapping URIs (e.g. "/myPath.do"). * Ant-style path patterns are also supported (e.g. "/myPath/*.do"). * At the method level, relative paths (e.g. "edit.do") are supported within * the primary mapping expressed at the type level. Path mapping URIs may * contain placeholders (e.g. "/${connect}") * <p><b>Supported at the type level as well as at the method level!</b> * When used at the type level, all method-level mappings inherit * this primary mapping, narrowing it for a specific handler method. * @see org.springframework.web.bind.annotation.ValueConstants#DEFAULT_NONE * @since 4.2 */ @AliasFor("value") String[] path() default {}; /** * The HTTP request methods to map to, narrowing the primary mapping: * GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE. * <p><b>Supported at the type level as well as at the method level!</b> * When used at the type level, all method-level mappings inherit * this HTTP method restriction (i.e. the type-level restriction * gets checked before the handler method is even resolved). * <p>Supported for Servlet environments as well as Portlet 2.0 environments. */ RequestMethod[] method() default {}; /** * The parameters of the mapped request, narrowing the primary mapping. * <p>Same format for any environment: a sequence of "myParam=myValue" style * expressions, with a request only mapped if each such parameter is found * to have the given value. Expressions can be negated by using the "!=" operator, * as in "myParam!=myValue". "myParam" style expressions are also supported, * with such parameters having to be present in the request (allowed to have * any value). Finally, "!myParam" style expressions indicate that the * specified parameter is <i>not</i> supposed to be present in the request. * <p><b>Supported at the type level as well as at the method level!</b> * When used at the type level, all method-level mappings inherit * this parameter restriction (i.e. the type-level restriction * gets checked before the handler method is even resolved). * <p>In a Servlet environment, parameter mappings are considered as restrictions * that are enforced at the type level. The primary path mapping (i.e. the * specified URI value) still has to uniquely identify the target handler, with * parameter mappings simply expressing preconditions for invoking the handler. * <p>In a Portlet environment, parameters are taken into account as mapping * differentiators, i.e. the primary portlet mode mapping plus the parameter * conditions uniquely identify the target handler. Different handlers may be * mapped onto the same portlet mode, as long as their parameter mappings differ. */ String[] params() default {}; /** * The headers of the mapped request, narrowing the primary mapping. * <p>Same format for any environment: a sequence of "My-Header=myValue" style * expressions, with a request only mapped if each such header is found * to have the given value. Expressions can be negated by using the "!=" operator, * as in "My-Header!=myValue". "My-Header" style expressions are also supported, * with such headers having to be present in the request (allowed to have * any value). Finally, "!My-Header" style expressions indicate that the * specified header is <i>not</i> supposed to be present in the request. * <p>Also supports media type wildcards (*), for headers such as Accept * and Content-Type. For instance, * <pre class="code"> * @RequestMapping(value = "/something", headers = "content-type=text/*") * </pre> * will match requests with a Content-Type of "text/html", "text/plain", etc. * <p><b>Supported at the type level as well as at the method level!</b> * When used at the type level, all method-level mappings inherit * this header restriction (i.e. the type-level restriction * gets checked before the handler method is even resolved). * <p>Maps against HttpServletRequest headers in a Servlet environment, * and against PortletRequest properties in a Portlet 2.0 environment. * @see org.springframework.http.MediaType */ String[] headers() default {}; /** * The consumable media types of the mapped request, narrowing the primary mapping. * <p>The format is a single media type or a sequence of media types, * with a request only mapped if the {@code Content-Type} matches one of these media types. * Examples: * <pre class="code"> * consumes = "text/plain" * consumes = {"text/plain", "application/*"} * </pre> * Expressions can be negated by using the "!" operator, as in "!text/plain", which matches * all requests with a {@code Content-Type} other than "text/plain". * <p><b>Supported at the type level as well as at the method level!</b> * When used at the type level, all method-level mappings override * this consumes restriction. * @see org.springframework.http.MediaType * @see javax.servlet.http.HttpServletRequest#getContentType() */ String[] consumes() default {}; /** * The producible media types of the mapped request, narrowing the primary mapping. * <p>The format is a single media type or a sequence of media types, * with a request only mapped if the {@code Accept} matches one of these media types. * Examples: * <pre class="code"> * produces = "text/plain" * produces = {"text/plain", "application/*"} * produces = "application/json; charset=UTF-8" * </pre> * <p>It affects the actual content type written, for example to produce a JSON response * with UTF-8 encoding, {@code "application/json; charset=UTF-8"} should be used. * <p>Expressions can be negated by using the "!" operator, as in "!text/plain", which matches * all requests with a {@code Accept} other than "text/plain". * <p><b>Supported at the type level as well as at the method level!</b> * When used at the type level, all method-level mappings override * this produces restriction. * @see org.springframework.http.MediaType */ String[] produces() default {}; }
现在,我们知道RequestMapping注解的name、value以及method的返回值,分别是String、String[]、RequestMethod[]。接下来,就是获取将注解的内容填充进实体类中。
private List<RequestUrlInfo> getRequestUrlInfos(Annotation annotation) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { List<RequestUrlInfo> infos = new ArrayList<RequestUrlInfo>(); if(annotation == null) { return infos; } String name = (String) AnnotationHelper.getInstance().getAnnotationInfo(annotation, "name"); List<String> requestUrls = Arrays.asList((String[]) AnnotationHelper.getInstance().getAnnotationInfo(annotation, "value")); List<RequestMethod> requestMethods = Arrays.asList((RequestMethod[]) AnnotationHelper.getInstance().getAnnotationInfo(annotation, "method")); if(requestMethods.isEmpty()) { for(String url : requestUrls) { RequestUrlInfo info = new RequestUrlInfo(name); info.setValue(url); info.setRequestMethod(null); infos.add(info); } } else { for(String url : requestUrls) { for(RequestMethod method : requestMethods) { RequestUrlInfo info = new RequestUrlInfo(name); info.setValue(url); info.setRequestMethod(method); infos.add(info); } } }
剩下的就是,将类级别的注解与方法级别的注解,组装成一个整体的实体类。
private List<RequestUrlInfo> getRequestUrlInfos(Annotation classAnnotation , Annotation methodAnnotation) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { List<RequestUrlInfo> infos = new ArrayList<RequestUrlInfo>(); if(classAnnotation != null) { String[] paths = (String[]) AnnotationHelper.getInstance().getAnnotationInfo(classAnnotation, "value"); for(String path : paths) { infos.addAll(getRequestUrlInfos(path, methodAnnotation)); } } else { infos.addAll(getRequestUrlInfos(methodAnnotation)); } return infos; }
下面,就是这个类的完整代码:
public class RequestUrlHelper { private static final RequestUrlHelper helper = new RequestUrlHelper(); protected RequestUrlHelper() { } public static RequestUrlHelper getInstance() { return helper; } /** * 将RequestMapping注解信息,组装成RequestUrlInfo类中。此类方法共有三种重载方式,分别为Annotation、提供basePath、提供classAnnotation注解三种方式。 * @param annotation * @return * @throws NoSuchMethodException * @throws SecurityException * @throws IllegalAccessException * @throws IllegalArgumentException * @throws InvocationTargetException */ private List<RequestUrlInfo> getRequestUrlInfos(Annotation annotation) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { List<RequestUrlInfo> infos = new ArrayList<RequestUrlInfo>(); if(annotation == null) { return infos; } String name = (String) AnnotationHelper.getInstance().getAnnotationInfo(annotation, "name"); List<String> requestUrls = Arrays.asList((String[]) AnnotationHelper.getInstance().getAnnotationInfo(annotation, "value")); List<RequestMethod> requestMethods = Arrays.asList((RequestMethod[]) AnnotationHelper.getInstance().getAnnotationInfo(annotation, "method")); if(requestMethods.isEmpty()) { for(String url : requestUrls) { RequestUrlInfo info = new RequestUrlInfo(name); info.setValue(url); info.setRequestMethod(null); infos.add(info); } } else { for(String url : requestUrls) { for(RequestMethod method : requestMethods) { RequestUrlInfo info = new RequestUrlInfo(name); info.setValue(url); info.setRequestMethod(method); infos.add(info); } } } return infos; } /** * 上一个方法的重载方法,主要是将类上面的注解中的路径添加到全部的请求信息中。 * @param basePath * @param annotation * @return * @throws NoSuchMethodException * @throws SecurityException * @throws IllegalAccessException * @throws IllegalArgumentException * @throws InvocationTargetException */ private List<RequestUrlInfo> getRequestUrlInfos(String basePath , Annotation annotation) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { List<RequestUrlInfo> infos = getRequestUrlInfos(annotation); if(!StringUtils.hasText(basePath)) { return infos; } for(RequestUrlInfo info : infos) { info.setValue(basePath.concat("/" + info.getValue())); } return infos; } /** * 上一个方法的重载方法,这次,没有提供basePath,而是提供一个Annotation,并从这个注解上面获取得到类上面注解的请求路径。 * @param classAnnotation * @param methodAnnotation * @return * @throws NoSuchMethodException * @throws SecurityException * @throws IllegalAccessException * @throws IllegalArgumentException * @throws InvocationTargetException */ private List<RequestUrlInfo> getRequestUrlInfos(Annotation classAnnotation , Annotation methodAnnotation) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { List<RequestUrlInfo> infos = new ArrayList<RequestUrlInfo>(); if(classAnnotation != null) { String[] paths = (String[]) AnnotationHelper.getInstance().getAnnotationInfo(classAnnotation, "value"); for(String path : paths) { infos.addAll(getRequestUrlInfos(path, methodAnnotation)); } } else { infos.addAll(getRequestUrlInfos(methodAnnotation)); } return infos; } /** * 获取全部的请求,将其包装成RequestUrlInfo实体类,并将其通过请求路径排序后,进行返回。 * @param scannerClass * @return * @throws NoSuchMethodException * @throws SecurityException * @throws IllegalAccessException * @throws IllegalArgumentException * @throws InvocationTargetException */ public List<RequestUrlInfo> getAllRequestUrlInfos(Class<?> scannerClass) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { Annotation classAnnotation = AnnotationHelper.getInstance().getClassAnnotation(scannerClass, RequestMapping.class); List<Annotation> methodAnnotations = AnnotationHelper.getInstance().getMethodAnnotation(scannerClass, RequestMapping.class); List<RequestUrlInfo> infos = new ArrayList<RequestUrlInfo>(); for(Annotation methodAnnotation : methodAnnotations) { infos.addAll(getRequestUrlInfos(classAnnotation, methodAnnotation)); } Collections.reverse(infos); return infos; } }
以上是关于获取指定类上的@RequestMapping注解的请求信息的主要内容,如果未能解决你的问题,请参考以下文章