如何防止Spring 3.0 MVC @ModelAttribute变量出现在URL中?

Chr*_*ian 56 java spring spring-mvc

使用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;

  }

}
Run Code Online (Sandbox Code Playgroud)

Controller从填充HTML表单的命令对象中读取Intake信息,验证命令对象,将信息持久保存到数据库,并返回案例编号.

一切都很好,除了当我重定向到intakeDetails.htm页面时,我得到一个如下所示的URL:

http://localhost:8080/project/intakeDetails.htm?caseNumber=1&users=user1&users=user2&users=user3&users=user4...

如何防止用户集合显示在URL中?

小智 38

model.asMap().clear();
return "redirect:" + news.getUrl();
Run Code Online (Sandbox Code Playgroud)

:)

  • 这个页面上有很多更复杂的解决方案,但是这个解决方案可以解决这个问题.我想补充一点,你需要将Model参数添加到你的addIntake方法......`public String addIntake(@ModelAttribute("intake")Intake intake,Model model,BindingResult results) (2认同)

ela*_*ich 30

从Spring 3.1开始,RequestMappingHandlerAdapter提供了一个标志ignoreDefaultModelOnRedirect,如果控制器重定向,您可以使用该标志来防止使用defautl模型的内容.

  • 更像是:<mvc:annotation-driven ignore-default-model-on-redirect ="true"/>并检查你是否在xml标题中导入了正确的(3.1+)模式(如果你指定了一个带有版本的xsd)它) (6认同)
  • 即`<mvc:annotation-driven ignoreDefaultModelOnRedirect ="true"/>` (3认同)

axt*_*avt 18

没有好的方法可以解决这个问题(即没有创建自定义组件,没有过多的显式xml配置且没有手动实例化RedirectView).

您可以RedirectView通过其4参数构造函数手动实例化,也可以在上下文中声明以下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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我使用了4参数RedirectView解决方案:返回新的ModelAndView(new RedirectView("intakeDetails.htm?caseNumber ="+ caseNumber,false,true,false)); (7认同)

ska*_*man 18

@ModelAttribute方法注释旨在被用于参照数据曝光到视图层.在你的情况下,我不能肯定地说,但我不会说一组用户符合参考数据.我建议您在@RequestMapping注释的处理程序方法中明确地将此信息传递给模型.

如果你还想使用@ModelAttribute,这里有一个博客条目讨论重定向问题.

但是所有前面的示例都有一个共同的问题,因为所有@ModelAttribute方法都在执行处理程序之前运行,如果处理程序返回重定向,则模型数据将作为查询字符串添加到url中.应该不惜一切代价避免这种情况,因为它可能会泄露一些关于如何整理应用程序的秘密.

他建议的解决方案(参见博客的第4部分)是使用a HandlerInterceptorAdapter来使视图可以看到公共参考数据.由于参考数据不应与控制器紧密耦合,因此在设计方面不应造成问题.

  • 哇,建筑师流行语宾果用一个词完成:HandlerInterceptorAdapter! (12认同)
  • @RobertGrant Buzzzz [AbstractAnnotationConfigDispatcherServletInitializer](http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/support/AbstractAnnotationConfigDispatcherServletInitializer.html) (2认同)

kal*_*ech 5

我知道这个问题和答案是陈旧的,但我在自己遇到类似问题之后偶然发现了它,并且我找不到其他很多信息.

我认为接受的答案不是很好.axtavt下方的答案要好得多.问题不在于控制器上的注释模型属性是否有意义.它是关于如何从通常使用ModelAttributes的控制器中发出"干净"重定向.控制器本身通常需要参考数据,但有时它需要在其他地方重定向以获得异常条件或其他任何东西,并且传递参考数据没有意义.我认为这是一种有效且常见的模式.

(Fwiw,我在Tomcat中意外地遇到了这个问题.重定向根本就没有用了,我得到了奇怪的错误消息,如:java.lang.ArrayIndexOutOfBoundsException:8192.我最终确定Tomcat的默认最大标头长度是8192.我没有' t意识到ModelAttributes被自动添加到重定向URL,这导致标头长度超过Tomcat的最大标头长度.)


Ano*_*ose 5

我实现了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;
    }

}
Run Code Online (Sandbox Code Playgroud)

这还需要定义视图解析器bean:

<bean id="viewResolver" class="com.example.RedirectsNotExposingModelUrlBasedViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
</bean>
Run Code Online (Sandbox Code Playgroud)