2012-04-25 40 views
3

使用Spring MVC,有什麼辦法可以將org.springframework.ui.Model分解,以便不必在任何控制器中的方法參數中指定它?如何分解控制器中的模型?

換句話說,我正在做這樣的:

public abstract class AbstractController { 

    @Autowired 
    protected MultipartHttpServletRequest request; 

} 

@Controller 
public class SigninController extends AbstractController { 

    @RequestMapping(value = "/signin", method = RequestMethod.GET) 
    public String signin(@ModelAttribute User user, Model model) { 
     // do stuff with user (parameter) 
     // do stuff with model (parameter) <-- 
     // do stuff with request (attribute) 
     return "/signin/index"; 
    } 

} 

,我願做這樣的:

public abstract class AbstractController { 

    @Autowired 
    protected MultipartHttpServletRequest request; 

    @Autowired 
    protected Model model; 

} 

@Controller 
public class SigninController extends AbstractController { 

    @RequestMapping(value = "/signin", method = RequestMethod.GET) 
    public String signin(@ModelAttribute User user) { 
     // do stuff with user (parameter) 
     // do stuff with model (attribute) <-- 
     // do stuff with request (attribute) 
     return "/signin/index"; 
    } 

} 

但在調用URL時,拋出一個異常:

...Could not autowire field: protected org.springframework.ui.Model... 
...No matching bean of type [org.springframework.ui.Model] found for dependency... 

我在使用org.springframework.ui.ModelMap時得到了同樣的錯誤。

任何解決方案?

感謝您的幫助:)

+0

@ sp00m ..我只是想知道這樣做的目的。 – raddykrish 2012-04-25 16:51:57

+0

@raddykrish我只是發現我的控制器更具可讀性,我不是那種有n個參數的方法(3 sp00m 2012-04-25 18:04:40

+0

我明白你的觀點。我的想法是,由於Model和ModelMap不是Spring託管類,我想知道我們是否可以做到這一點。 – raddykrish 2012-04-25 18:46:27

回答

1

我終於找到了解決方案。我不知道遊戲是值得的,但它的工作原理:)

首先,在你AbstractController添加這些東西:

public abstract class AbstractController { 

    @Autowired 
    protected MultipartHttpServletRequest request; 

    protected ModelMap model; 

    public void setModel(ModelMap model) { 
     this.model = model; 
    } 

    public ModelMap getModel() { 
     return model; 
    } 

} 

然後,創建實施org.springframework.web.servlet.HandlerInterceptor這樣一個攔截器:

public class UserContextInterceptor implements HandlerInterceptor { 

    @Override 
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException { 
     if (handler instanceof AbstractController) { 
      AbstractController controller = (AbstractController) handler; 
      controller.setModel(new ModelMap()); 
     } 
     return true; 
    } 

    @Override 
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { 
     if (handler instanceof AbstractController && modelAndView != null) { 
      AbstractController controller = (AbstractController) handler; 
      modelAndView.addAllObjects(controller.getModel()); 
     } 
    } 

    @Override 
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { 
    } 

} 

最後,在applicationContext.xml加上這些行:

<mvc:interceptors> 
    <bean class="path.to.my.just.created.UserContextInterceptor" /> 
</mvc:interceptors> 

當然,讓你的控制器執行你的AbstractController

這是!你不需要在你的控制器方法參數中指定你的request或你的model :)我並不真的相信這個技巧的用處,但是是的。如果它可以讓瘋狂的開發者更快樂:)

仍然開放到更容易雖然解決方案。

+0

您是否檢查過我以前的評論。我已經提到過這樣的事情(但不是通過攔截器)。無論如何高度瞭解這個解決方案。 – raddykrish 2012-04-25 22:35:00

+0

是的,抱歉沒有回答。我嘗試過這個。好的一點是,這個異常不再被拋出,所以這個bean被正確的自動裝配了(也拋出了'NullPointerException')。但是模型沒有發送到視圖,所以我沒有從我的JSP頁面訪問我的屬性。不過謝謝你的答案! – sp00m 2012-04-26 06:57:46

+0

Ohh ...但我認爲你仍然可以通過返回ModelView而不是String來將模型發送到視圖,因爲在你的攔截器中,你已經使用了類似'modelAndView.addAllObjects(controller.getModel());',同樣可以也用於控制器中。無論如何,很高興知道你嘗試了我提到的選項。謝謝!!! – raddykrish 2012-04-26 17:21:07