我有一个分为不同模块的项目,例如一个网站和一个论坛。
论坛可在以下网址找到:
http://example.com/[forum]/
例如可以是:
http://example.com/support/
http://example.com/helpme/
http://example.com/aforum/
该网站位于:
http://example.com/[site]/
例如可以是:
http://example.com/site1/
http://example.com/nice/
http://example.com/something/
[论坛]和[网站]部分是可变的。在我的数据库中,我查找了#34; nice"是一个网站," helpme"是一个论坛。
我的ForumController有一个Spring RequestMapping:
@RequestMapping(value = { "/{simpleTitle:[0-9a-z-]+}" }, method = RequestMethod.GET, produces = "text/html")
public void list(@PathVariable String simpleTitle, Model model, HttpServletRequest req, HttpServletResponse resp) {
我对网站有同样的东西,所以一个SiteController:
@RequestMapping(value = { "/{simpleTitle:[0-9a-z-]+}" }, method = RequestMethod.GET, produces = "text/html")
public void list(@PathVariable String simpleTitle, Model model, HttpServletRequest req, HttpServletResponse resp) {
这当然很糟糕,因为2个具有相同请求映射的控制器并不好。
我可以创建一个FrontController,它具有上面的请求映射,查找simpleTitle(论坛或网站)和调用函数来显示论坛或网站。这很有效。
但它并非如此"春天"喜欢和结构化。
是否有可能"拦截"请求并在控制器上内部转发(或调用函数)?
这样我就可以拥有看起来像一个简单标题的拦截器,决定它是一个论坛还是一个网站,并且"转发" /"调用"正确的控制者。
答案 0 :(得分:2)
坦率地说,我喜欢@Luiggi Mendoza解决方案,但如果您想要替代方案,请使用以下内容:
package eu.europa.acer.aris.ceremp.filter;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
@Component(value = "yourCustomFilter")
public class YourCustomFilter extends OncePerRequestFilter{
private static final Logger logger = LoggerFactory.getLogger(YourCustomFilter.class);
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
//String[] path = request.getRequestURL().toString().split("/");
if (letPagePass(request.getRequestURL().toString()) == false)
{
// if request is bound to static resource like js//img do nothing, the filter chain will activate
if (letResourcePass(request.getRequestURL().toString()))
{
}
else
{
String[] urlInfos = obtainUrlAndParametersLast(request.getRequestURL().toString());
// last element will always give back last part including any parameter
// first element will always be a controller modifier
response.sendRedirect(request.getContextPath()+rebuildControllerPath(urlInfos));
return;
}
}
filterChain.doFilter(request, response);
}
private String rebuildControllerPath(String[] pathElement )
{
//do your thing here
if ("forum".equals(pathElement[0]))
{
String addenda = "/forumController/";
for (String singlePart: pathElement)
{
addenda = addenda+singlePart+"/";
}
return addenda;
}
}
// bind forceful redirect
public boolean letPagePass(String url)
{
// if you have some page that are naturally unique among controllers that you want always to process natively
String[] path = url.split("/");
if (path[path.length-2].startsWith("yourCertainUrlIgnoringParameters"))
{
return true;
}
// directcall
else if (path[path.length-2].startsWith("yourCertainUrlIgnoringParameters2"))
{
return true;
}
else
{
return false;
}
}
public boolean letResourcePass(String url)
{
String[] path = url.split("/");
/*
this assumes you have always a strict structure so your image//js//reource will always be in
https://domainname/a/lot/of/folder/img/actuaresource.png
or
https://domainname/a/lot/of/folder/js/actuaresource.js
etc
*/
//image pass
if (path[path.length-2].equals("img") || url.contains("/img/"))
{
return true;
}
//css pass
else if (path[path.length-2].equals("css") || url.contains("/css/"))
{
return true;
}
//js pass
else if (path[path.length-2].equals("js") || url.contains("/js/"))
{
return true;
}
else
{
return false;
}
}
@Override
public void destroy() {
}
}
并在web.xml文件中添加以下xml代码段
<!-- your fi Filter -->
<filter>
<filter-name>yourCustomFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>yourCustomFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
答案 1 :(得分:0)
干杯Luiggi Mendoza和witchedwiz为伟大的想法!
在我吃饭的时候,我提出了一个非常简单的解决方案:使用servlet过滤器。在doFilter中添加一个带有HttpServletRequestWrapper(类型:forum或type:site)的请求头。
在@RequestMapping中添加header属性,例如headers =“type = forum”。
现在@RequestMapping可以有相同的网址,它们在请求标头中有所不同。并且所有弹簧功能都有效,尽管到目前为止我只做了一个简单的测试用例。
WebApplicationContextUtils帮助在servlet过滤器中获取了spring bean。