How to implement @RequestMapping custom properties

后端 未结 2 1200
天命终不由人
天命终不由人 2020-12-01 01:25

As an example, take subdomain mapping.

This article: Managing multiple Domain and Sub Domain on Google App Engine for Same Applicat

相关标签:
2条回答
  • 2020-12-01 02:01

    That's correct, but that would be too complicated. You'd better check the Host header, whether it contains a given subdomain.

    But you should not really need this more than once or twice, so you can also do it manually in the method body. If you really need it in many places, it would be an odd requirement.

    0 讨论(0)
  • 2020-12-01 02:05

    I've created solution based on referenced spring-mvc-31-demo

    This solution can be used to map only single RequestCondition as of now. I've created two Issues to notify, this should be changed:
    https://github.com/rstoyanchev/spring-mvc-31-demo/issues/5
    https://jira.springsource.org/browse/SPR-9350

    This solution uses custom @RequestCondition feature of Spring 3.1.1.RELEASE platform

    USAGE

    Example 1:

    @Controller
    @SubdomainMapping(value = "subdomain", tld = ".mydomain.com")
    class MyController1 {
        // Code here will be executed only on address match:
        // subdomain.mydomain.com
    }
    

    Example 2:

    @Controller
    class MyController2 {
    
        @RequestMapping("/index.html")
        @SubdomainMapping("www")
        public function index_www(Map<Object, String> map){
            // on www.domain.com
            // where ".domain.com" is defined in SubdomainMapping.java
        }
    
        @RequestMapping("/index.html")
        @SubdomainMapping("custom")
        public function index_custom(Map<Object, String> map){
            // on custom.domain.com
            // where ".domain.com" is defined in SubdomainMapping.java
        }
    }
    

    We need three files

    • SubdomainMapping.java
    • SubdomainRequestCondition.java
    • SubdomainRequestMappingHandlerMapping.java

    SubdomainMapping.java

    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target({ElementType.METHOD, ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface SubdomainMapping {
    
        /**
        * This param defines single or multiple subdomain
        * Where the Method/Type is valid to be called
        */
        String[] value() default {};
        /**
        * This param defines site domain and tld
        * It's important to put the leading dot
        * Not an array, so cannot be used for mapping multiple domains/tld
        */
        String tld() default ".custom.tld";
    }
    

    SubdomainRequestCondition.java

    import java.net.URL;
    import java.util.Arrays;
    import java.util.Collection;
    import java.util.Collections;
    import java.util.HashSet;
    import java.util.LinkedHashSet;
    import java.util.Set;
    
    import javax.servlet.http.HttpServletRequest;
    
    import org.springframework.web.servlet.mvc.condition.RequestCondition;
    
    public class SubdomainRequestCondition implements
            RequestCondition<SubdomainRequestCondition> {
    
        private final Set<String> subdomains;
        private final String tld;
    
        public SubdomainRequestCondition(String tld, String... subdomains) {
            this(tld, Arrays.asList(subdomains));
        }
    
        public SubdomainRequestCondition(String tld, Collection<String> subdomains) {
            this.subdomains = Collections.unmodifiableSet(new HashSet<String>(
                    subdomains));
            this.tld = tld;
        }
    
        @Override
        public SubdomainRequestCondition combine(SubdomainRequestCondition other) {
            Set<String> allRoles = new LinkedHashSet<String>(this.subdomains);
            allRoles.addAll(other.subdomains);
            return new SubdomainRequestCondition(tld, allRoles);
        }
    
        @Override
        public SubdomainRequestCondition getMatchingCondition(
                HttpServletRequest request) {
            try {
                URL uri = new URL(request.getRequestURL().toString());
                String[] parts = uri.getHost().split(this.tld);
                if (parts.length == 1) {
                    for (String s : this.subdomains) {
                        if (s.equalsIgnoreCase(parts[0])) {
                            return this;
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace(System.err);
            }
            return null;
        }
    
        @Override
        public int compareTo(SubdomainRequestCondition other,
                HttpServletRequest request) {
            return org.apache.commons.collections.CollectionUtils.removeAll(other.subdomains, this.subdomains).size();
        }
    
    }
    

    SubdomainRequestMappingHandlerMapping.java

    import java.lang.reflect.Method;
    
    import org.springframework.core.annotation.AnnotationUtils;
    import org.springframework.web.servlet.mvc.condition.RequestCondition;
    import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
    
    public class CustomRequestMappingHandlerMapping extends
            RequestMappingHandlerMapping {
    
        @Override
        protected RequestCondition<?> getCustomTypeCondition(Class<?> handlerType) {
            SubdomainMapping typeAnnotation = AnnotationUtils.findAnnotation(
                    handlerType, SubdomainMapping.class);
            return createCondition(typeAnnotation);
        }
    
        @Override
        protected RequestCondition<?> getCustomMethodCondition(Method method) {
            SubdomainMapping methodAnnotation = AnnotationUtils.findAnnotation(
                    method, SubdomainMapping.class);
            return createCondition(methodAnnotation);
        }
    
        private RequestCondition<?> createCondition(SubdomainMapping accessMapping) {
            return (accessMapping != null) ? new SubdomainRequestCondition(
                    accessMapping.tld(), accessMapping.value()) : null;
        }
    
    }
    

    Instalation

    IMPORTANT: So far, it is not possible to use this solution with XML element
    <mvc:annotation-driven />, see JIRA https://jira.springsource.org/browse/SPR-9344 for explanation

    • You have to register custom MappingHandler bean, pointing at this custom implementation SubdomainRequestMappingHandlerMapping class
    • You have to set it's order to be lower than default RequestMappingHandlerMapping
      OR
      Replace the registered RequestMappingHandlerMapping (possibly on order=0)

    For more wide explanation on implementing this solution, see the related github project

    0 讨论(0)
提交回复
热议问题