[英]How do I prevent Spring 4.0 MVC @ModelAttribute variables from appearing in URL?
[英]How do I prevent Spring 3.0 MVC @ModelAttribute variables from appearing in URL?
使用Spring MVC 3.0.0.RELEASE,我有以下Controller:
@Controller
@RequestMapping("/addIntake.htm")
public class AddIntakeController{
private final Collection<String> users;
public AddIntakeController(){
users = new ArrayList<String>();
users.add("user1");
users.add("user2");
// ...
users.add("userN");
}
@ModelAttribute("users")
public Collection<String> getUsers(){
return this.users;
}
@RequestMapping(method=RequestMethod.GET)
public String setupForm(ModelMap model){
// Set up command object
Intake intake = new Intake();
intake.setIntakeDate(new Date());
model.addAttribute("intake", intake);
return "addIntake";
}
@RequestMapping(method=RequestMethod.POST)
public String addIntake(@ModelAttribute("intake")Intake intake, BindingResult result){
// Validate Intake command object and persist to database
// ...
String caseNumber = assignIntakeACaseNumber();
return "redirect:intakeDetails.htm?caseNumber=" + caseNumber;
}
}
Controller從填充HTML表單的命令對象中讀取Intake信息,驗證命令對象,將信息持久保存到數據庫,並返回案例編號。
一切都很好,除了當我重定向到intakeDetails.htm頁面時,我得到一個如下所示的URL:
http://localhost:8080/project/intakeDetails.htm?caseNumber=1&users=user1&users=user2&users=user3&users=user4...
如何防止用戶集合顯示在URL中?
model.asMap().clear();
return "redirect:" + news.getUrl();
:)
從Spring 3.1開始, RequestMappingHandlerAdapter
提供了一個名為ignoreDefaultModelOnRedirect
的標志,如果控制器重定向,您可以使用該標志來防止使用defautl模型的內容。
沒有好的方法可以解決這個問題(即沒有創建自定義組件,沒有過多的顯式xml配置,也沒有RedirectView
手動實例化)。
您可以通過其4參數構造函數手動實例化RedirectView
也可以在上下文中聲明以下bean(在其他視圖解析器附近):
public class RedirectViewResolver implements ViewResolver, Ordered {
// Have a highest priority by default
private int order = Integer.MIN_VALUE;
// Uses this prefix to avoid interference with the default behaviour
public static final String REDIRECT_URL_PREFIX = "redirectWithoutModel:";
public View resolveViewName(String viewName, Locale arg1) throws Exception {
if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
return new RedirectView(redirectUrl, true, true, false);
}
return null;
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
}
@ModelAttribute
方法注釋旨在用於將參考數據公開給視圖層。 在你的情況下,我不能肯定地說,但我不會說一組用戶符合參考數據。 我建議您在@RequestMapping
-annotated處理程序方法中明確地將此信息傳遞給模型。
如果你仍然想使用@ModelAttribute
,那么這里有一個討論重定向問題的博客條目。
但是所有前面的示例都有一個共同的問題,因為所有@ModelAttribute方法都在執行處理程序之前運行,如果處理程序返回重定向,則模型數據將作為查詢字符串添加到url中。 應該不惜一切代價避免這種情況,因為它可能會泄露一些關於如何整理應用程序的秘密。
他建議的解決方案(參見博客的第4部分)是使用HandlerInterceptorAdapter
使公共參考數據對視圖可見。 由於參考數據不應與控制器緊密耦合,因此在設計方面不應造成問題。
我實現了Sid答案的變體,減少了復制和粘貼:
public class RedirectsNotExposingModelUrlBasedViewResolver extends UrlBasedViewResolver {
@Override
protected View createView(String viewName, Locale locale) throws Exception {
View view = super.createView(viewName, locale);
if (view instanceof RedirectView) {
((RedirectView) view).setExposeModelAttributes(false);
}
return view;
}
}
這還需要定義視圖解析器bean:
<bean id="viewResolver" class="com.example.RedirectsNotExposingModelUrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
</bean>
我知道這個問題和答案是陳舊的,但我在自己遇到類似問題之后偶然發現了它,而且我找不到其他很多信息。
我認為接受的答案不是很好。 axtavt下方的答案要好得多。 問題不在於控制器上的注釋模型屬性是否有意義。 它是關於如何從通常使用ModelAttributes的控制器中發出“干凈”重定向。 控制器本身通常需要參考數據,但有時它需要在其他地方重定向以獲得異常條件或其他任何東西,並且傳遞參考數據沒有意義。 我認為這是一種有效且常見的模式。
(Fwiw,我在Tomcat中意外地遇到了這個問題。重定向根本就沒有用了,我得到了奇怪的錯誤消息,如:java.lang.ArrayIndexOutOfBoundsException:8192。我最終確定Tomcat的默認最大標頭長度是8192.我沒有' t意識到ModelAttributes被自動添加到重定向URL,這導致標頭長度超過Tomcat的最大標頭長度。)
在我的應用程序中,我沒有任何用於在重定向中公開模型屬性的用例,因此我擴展了org.springframework.web.servlet.view.UrlBasedViewResolver以覆蓋createView方法並在應用程序上下文中使用聲明:
public class UrlBasedViewResolverWithouthIncludingModeAtttributesInRedirect extends UrlBasedViewResolver {
@Override
protected View createView(String viewName, Locale locale) throws Exception {
// If this resolver is not supposed to handle the given view,
// return null to pass on to the next resolver in the chain.
if (!canHandle(viewName, locale)) {
return null;
}
// Check for special "redirect:" prefix.
if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
boolean exposeModelAttributes = false;
return new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible(), exposeModelAttributes);
}
// Check for special "forward:" prefix.
if (viewName.startsWith(FORWARD_URL_PREFIX)) {
String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());
return new InternalResourceView(forwardUrl);
}
// Else fall back to superclass implementation: calling loadView.
return super.createView(viewName, locale);
}
}
<bean id="viewResolver" class="com.acme.spring.UrlBasedViewResolverWithouthIncludingModeAtttributesInRedirect">
</bean>
手動創建一個RedirectView對象為我工作:
@RequestMapping(method=RequestMethod.POST)
public ModelAndView addIntake(@ModelAttribute("intake")Intake intake, BindingResult result){
// Validate Intake command object and persist to database
// ...
String caseNumber = assignIntakeACaseNumber();
RedirectView rv = new RedirectView("redirect:intakeDetails.htm?caseNumber=" + caseNumber);
rv.setExposeModelAttributes(false);
return new ModelAndView(rv);
}
恕我直言,這應該是重定向時的默認行為
以下是如何使用基於Java的配置(Spring 3.1+,我認為,使用4.2測試):
@Configuration
public class MvcConfig extends WebMvcConfigurationSupport {
@Override
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter();
adapter.setIgnoreDefaultModelOnRedirect(true);
return adapter;
}
// possible other overrides as well
}
或者,將該請求設為POST。 獲取請求僅顯示模型屬性作為URL中出現的請求參數。
不要使用@ModelAttribute
。 將用戶顯式存儲在ModelMap
。 無論如何,你正在使用命令對象。
@RequestMapping(method=RequestMethod.GET)
public String setupForm(ModelMap model){
// Set up command object
Intake intake = new Intake();
intake.setIntakeDate(new Date());
model.addAttribute("intake", intake);
model.addAttribute("users", users);
return "addIntake";
}
這樣做的缺點是如果在addIntake()
發生驗證錯誤。 如果您只想返回表單的邏輯名稱,您還必須記住與用戶重新填充模型,否則表單將無法正確設置。
嘗試將以下代碼添加到servlet-config.xml中
<mvc:annotation-driven ignoreDefaultModelOnRedirect="true" />
有時這會解決問題。
如果有助於您的事業,有一個解決方法。
@ModelAttribute("users")
public Collection<String> getUsers(){
return this.users;
}
在這里你已經返回String of Collection。 使其成為User的集合(它可以是表示用戶的類包裝字符串,或者是具有關於用戶的一堆數據的類)。 只有字符串才會出現問題。 如果返回的Collection包含任何其他對象,則不會發生這種情況。 但是,這只是一種解決方法,可能根本不需要。 只是我的兩分錢。 就這樣 -
@ModelAttribute("users")
public Collection<User> getUsers(){
return this.users;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.