2015-08-25 30 views
1

我有一个项目被分成不同的模块,例如你有一个网站和一个论坛。拦截请求并在内部转发给控制器?

论坛,可以发现:

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/ 

[forum]和[site]部分是可变的。在我的数据库中,我查找“nice”是一个网站,“helpme”是一个论坛。

我有我的ForumController弹簧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) { 

我有一个网站samething,所以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个控制器具有相同requestmapping不好。

我可以创建一个FrontController与上述请求映射,查找什么simpleTitle(论坛或网站)和调用功能来显示论坛或网站。这样可行。

但它并不是非常“春天”的喜欢和结构。

是否有可能“拦截”一个请求,并在控制器上自己内部转发(或调用该函数)?

这样我可以让Interceptor看起来很简单,决定它是论坛还是站点,并且“转发”/“调用”正确的控制器。

+0

不知道这是否是你的spring-ish,但你可以通过参数S(对于站点)或F(对于论坛)来获得spring bean,并且这个bean将在内部执行重定向。您将为(S)ite和(F)orum的实现实现通用接口。您可以在另一个bean中抽象出路径的检索。 –

+0

@LuiggiMendoza这听起来确实是春天;-)虽然我很难理解它,但是你能否再解释一下?没有大的例子需要,只是基本知识或者可能只是一个解释它多一点的网址。 – TinusSky

回答

0

干杯Luiggi门多萨和witchedwiz伟大的想法!

虽然我在吃东西,但我想出了一个非常简单的解决方案:使用servlet过滤器。在doFilter中添加一个带有HttpServletRequestWrapper的请求头(类型:forum或type:site)。

在@RequestMapping中添加一个标题属性,如headers =“type = forum”。

现在@RequestMapping可以具有相同的URL,它们在请求头部中有所不同。尽管到目前为止我只做了一个简单的测试用例,但所有的弹簧功能都可以工作

WebApplicationContextUtils帮助在servlet过滤器中获得spring bean。

+0

我已经避免了这种替代方法,因为它会包裹所有的路径,它不是春季伊斯兰教:P。 Anway,很高兴知道你发现了一些有用的东西。 –

2

坦白说,我喜欢@Luiggi门多萨的解决方案,但如果你想选择,使用这样的:

  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>