获取指定类上的@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;
    }
}
时间: 2024-08-07 04:12:19

获取指定类上的@RequestMapping注解的请求信息的相关文章

objectARX 获取指定图层上所有实体ID

2015-12-17 1 //获取指定图层上所有实体ID 2 AcDbObjectIdArray GetAllEntityId(const TCHAR* layername) 3 { 4 AcDbObjectIdArray entIds; 5 bool bFilterlayer = false; 6 AcDbObjectId layerId; 7 //获取指定图层对象ID 8 if (layername != NULL) 9 { 10 AcDbLayerTable *pLayerTbl = NU

Python:爬虫之利用Python获取指定网址上的所有图片—Jaosn niu

# coding=gbk import urllib.request import re import os import urllib def getHtml(url): #指定网址获取函数 page = urllib.request.urlopen(url) html = page.read() return html.decode('UTF-8') def getImg(html): #定义获取图片函数 reg = r'src="(.+?\.jpg)" pic_ext' imgr

python获取指定网页上的有多少个超级链接

# -*- coding: cp936 -*- import urllib2 import re def u(url): #connect to a URL website = urllib2.urlopen(url) #read html code html = website.read() #use re.findall to get all the links links = re.findall('"((http|ftp)s?://.*?)"', html) print u'有

RequestMapping 注解的解析、匹配、注册

RequestMapping 注解的解析.匹配.注册 1)创建 RequestMappingHandlerMapping 实例时会触发 afterPropertiesSet 调用. 2)读取容器中所有带有 Controller 或 RequestMapping 注解的类. 3)读取此类中所有满足过滤器 ReflectionUtils.USER_DECLARED_METHODS 的方法, 读取处理方法上的 RequestMapping 注解信息, 将其解析并封装为 RequestMappingIn

springboot实战之获取工具类bean

这次的实践经验的起因在于,在开发中,我想在工具类中使用配置文件的变量值.通常使用@value注解,这个只能在spring中管理的bean总获取.之前我也很疑惑,为什么之前的开发人员会在SpringUtil类上加入@Component注解,今天又遇到这种情况,其原因完全理解了. @Component public class SpringUtil implements EnvironmentAware { private static Environment env; public static

获取Java类中注解的详细信息

前言:这篇博客主要是为了后续的获取SpringMVC中的全部请求URL做的准备. public class AnnotationHelper { private static final AnnotationHelper helper = new AnnotationHelper(); protected AnnotationHelper() { } public static AnnotationHelper getInstance() { return helper; } /** * 得到类

RequestMapping注解_修饰类

[使用RequestMapping映射请求] 1.Spring MVC使用 @RequestMapping 注解为控制器指定可以处理哪些URL请求. 2.在控制器的类定义及方法定义处都可以标注. @RequestMapping --类定义处:提供初步的请求映射信息.相对于WEB应用的根目录. --方法处:提供进一步的细节映射信息.相对于类定义处的URL.若类定义处未标注@RequestMapping,则方法处标记的URL相对于WEB应用的根目录. 从源码中可以看出: 3.DispatcherSe

获取指定包名下继承或者实现某接口的所有类(扫描文件目录和所有jar)

import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.net.JarURLConnection; import java.net.URL; import java.net.URLDecoder; import java.util.Enumeration; import java.util.Iterator; import java.util.LinkedHashSet; im

Spring:使用Spring AOP时,如何获取目标方法上的注解

当使用spring AOP时,判断目标方法上的注解进行相关操作,如缓存,认证权限等 自定义注解 package com.agent.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.