2015-08-25 58 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>