我正在运行带有嵌入式Tomcat的Spring Boot 1.2.3应用程序。
我想根据URL的第一部分在每个请求上注入一个自定义的contextPath。
例子:
http://localhost:8080/foo
有默认情况下contextPath=""
,应该得到contextPath="foo"
http://localhost:8080/foo/bar
有默认情况下contextPath=""
,应该得到contextPath="foo"
(没有路径的网址应保持原样)
我试着写一个定制的javax.servlet.Filter
带@Order(Ordered.HIGHEST_PRECEDENCE)
,但好像我失去了一些东西。这是代码:
@Component @Order(Ordered.HIGHEST_PRECEDENCE)
public class MultiTenancyFilter implements Filter {
private final static Pattern pattern = Pattern.compile("^/(?<contextpath>[^/]+).*$");
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
final HttpServletRequest req = (HttpServletRequest) request;
final String requestURI = req.getRequestURI();
Matcher matcher = pattern.matcher(requestURI);
if(matcher.matches()) {
chain.doFilter(new HttpServletRequestWrapper(req) {
@Override
public String getContextPath() {
return "/"+matcher.group("contextpath");
}
}, response);
}
}
@Override public void init(FilterConfig filterConfig) throws ServletException {}
@Override public void destroy() {}
}
这应该只是在第一个字符串之后/
和第二个字符串之前(如果有)之前获取String /
,然后将其用作返回值getContextPath()
。
但是Spring @Controller @RequestMapping和Spring SecurityantMatchers("/")
似乎并不尊重它。两者仍然像工作contextPath=""
。
如何动态覆盖每个请求的上下文路径?
得到它的工作!
Spring Security文档(http://docs.spring.io/spring-security/site/docs/3.1.x/reference/security-filter-chain.html)说:“ Spring Security只对保护应用程序中的路径感兴趣daccess-ods.un.org daccess-ods.un.org daccess-ods.un.org daccess_ods.un.org模式与连接的ServletPath和pathInfo的大小写不区分大小写的匹配,忽略了queryString。”
所以我只是重写了servletPath
and contextPath
(即使Spring Security不使用它)。另外,我添加了一些小的重定向,因为通常在http://localhost:8080/myContext
您点击时会被重定向到,http://localhost:8080/myContext/
而Spring Securities Ant Matcher不喜欢缺少的斜杠。
所以这是我的MultiTenancyFilter
代码:
@Component @Order(Ordered.HIGHEST_PRECEDENCE)
public class MultiTenancyFilter extends OncePerRequestFilter {
private final static Pattern pattern = Pattern.compile("^(?<contextPath>/[^/]+)(?<servletPath>.*)$");
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
Matcher matcher = pattern.matcher(request.getServletPath());
if(matcher.matches()) {
final String contextPath = matcher.group("contextPath");
final String servletPath = matcher.group("servletPath");
if(servletPath.trim().isEmpty()) {
response.sendRedirect(contextPath+"/");
return;
}
filterChain.doFilter(new HttpServletRequestWrapper(request) {
@Override
public String getContextPath() {
return contextPath;
}
@Override
public String getServletPath() {
return servletPath;
}
}, response);
} else {
filterChain.doFilter(request, response);
}
}
@Override
protected String getAlreadyFilteredAttributeName() {
return "multiTenancyFilter" + OncePerRequestFilter.ALREADY_FILTERED_SUFFIX;
}
}
它仅使用此处提到的URL模式提取contextPath和servletPath:https ://theholyjava.wordpress.com/2014/03/24/httpservletrequest-requesturirequesturlcontextpathservletpathpathinfoquerystring/
另外,我必须提供一个自定义getAlreadyFilteredAttributeName
方法,因为否则过滤器将被调用两次。(这导致contextPath
两次剥离)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句