如何实现@RequestMapping 自定义属性 [英] How to implement @RequestMapping custom properties
问题描述
以示例为例,以子域映射为例.
本文:管理多个域和子同一应用程序的 Google App Engine 上的域建议在 Filter 上解析子域并将变量分配给 ServletRequest 标头.
This article: Managing multiple Domain and Sub Domain on Google App Engine for Same Application recommends to resolve subdomain on Filter and assign variable to ServletRequest headers.
然后映射将如下所示:
@RequestMapping(value = "/path", headers="subdomain=www")
public String subsiteIndexPage(Model model,HttpServletRequest request) { ... }
如果我们想创建自定义@RequestMapping 属性,例如子域,例如.像这样创建映射:
If we'd like to create custom @RequestMapping property, such as subdomain, eg. to create mapping like this:
@RequestMapping(value = "/some/action", subdomain = "www")
public String handlerFunction(){ ... }
我们应该用我们自己的实现覆盖 @RequestMapping @interface
定义和覆盖 RequestMappingHandlerMapping 受保护的方法
(如 JIRA 所述:允许自定义请求映射条件 SPR-7812").
we should override @RequestMapping @interface
definition and override RequestMappingHandlerMapping protected methods, with our own implementation
(as stated on JIRA: "Allow custom request mapping conditions SPR-7812").
是吗?任何人都可以提供提示,如何实现此功能?
Is it right? Can anybody provide a hint, how to achieve this functionality?
想法 1:
正如原始 jira 线程所建议的,是创建自己的 RequestCondition
github 上有一个使用此解决方案的项目:https://github.com/rstoyanchev/spring-mvc-31-demo/
There is an project which uses this solution available on github: https://github.com/rstoyanchev/spring-mvc-31-demo/
以及相关的 SO 问题:在 Spring mvc 3.1 中添加自定义 RequestCondition
And related SO question: Adding custom RequestCondition's in Spring mvc 3.1
也许像 @Subdomain("www")
这样的类型和方法的映射,是可能的解决方案吗?
Maybe mapping like @Subdomain("www")
for both Type and Method, is possible solution?
链接到 forum.springsource.com 上的相同问题
推荐答案
我已经根据引用的 创建了解决方案spring-mvc-31-demo
截至目前,此解决方案仅可用于映射单个 RequestCondition.我创建了两个问题来通知,这应该改变:
https://github.com/rstoyanchev/spring-mvc-31-demo/issues/5
https://jira.springsource.org/browse/SPR-9350
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
这个方案使用了Spring 3.1.1.RELEASE平台的自定义@RequestCondition特性
用法
示例 1:
@Controller
@SubdomainMapping(value = "subdomain", tld = ".mydomain.com")
class MyController1 {
// Code here will be executed only on address match:
// subdomain.mydomain.com
}
示例 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
}
}
我们需要三个文件
- 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;
}
}
安装
重要提示:到目前为止,无法将此解决方案与 XML 元素一起使用
<mvc:annotation-driven/>,参见 JIRA https://jira.springsource.org/browse/SPR-9344 解释
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
- 必须注册自定义MappingHandler bean,指向这个自定义实现
SubdomainRequestMappingHandlerMapping
类 - 您必须将它的顺序设置为低于默认
RequestMappingHandlerMapping
或
替换已注册的RequestMappingHandlerMapping
(可能在 order=0 上) - 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 registeredRequestMappingHandlerMapping
(possibly on order=0)
有关实现此解决方案的更广泛的解释,请参阅相关的 github 项目
这篇关于如何实现@RequestMapping 自定义属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!