Spring boot 如果引发异常并返回表单,则将url更改回原始url

Spring boot 如果引发异常并返回表单,则将url更改回原始url,spring-boot,thymeleaf,Spring Boot,Thymeleaf,我有一个thymeleaf注册表单,如果我们提交该表单,则会调用“/signup_do”处的控制器,该控制器将验证用户并将其保存到数据库: <form action="/signup_do" method="post"> ... </form> 帐户注册方法可以引发异常SignupFormException,该异常由该控制器类中定义的@ExceptionHandler处理: @ExceptionHandler(value=SignupFormException.

我有一个thymeleaf注册表单,如果我们提交该表单,则会调用“/signup_do”处的控制器,该控制器将验证用户并将其保存到数据库:

<form action="/signup_do" method="post">
    ...
</form>
帐户注册方法可以引发异常SignupFormException,该异常由该控制器类中定义的@ExceptionHandler处理:

@ExceptionHandler(value=SignupFormException.class)
public String handle(HttpSession session, Model response) {

    Account returnDataToForm = (Account) session.getAttribute("accountToRegister");
    response.addAttribute("name", returnDataToForm.getFirstName());
    session.invalidate();

    return "signup";
}
现在问题是当出现异常时,表单中输入的输入会传递回注册表单,输入的数据保持不变,但是url仍然保持为/signup\u do

我尝试使用return“redirect:/signup”来代替,这确实会更改url,但它最终会向/signup url发出get请求,如

/signup?name=John...
但是my/signup控制器不是为处理get请求而设计的,它只知道显示表单,因此信息丢失

@GetMapping("/signup")
public String signupPage() {return "signup";}

我也尝试过使用forward:/signup,但最终抛出405错误。

重定向将向控制器发出get请求,以查找要显示的视图,在您的情况下,这意味着由于您给出的原因而丢失数据。我可以想出两个变通办法:

  • 不要在每次进入此视图时使用javascript手动重定向和更改URL。如果您不喜欢视图中有一个“错误”的URL,那么手动编辑它看起来是最合理和直接的方法。您可以看到如何执行此操作,包括在每次页面加载/按下提交按钮时执行的脚本中

  • 执行重定向并避免丢失您的信息,方法是将信息在会话中存储一段时间,以某种方式在thymeleaf中访问信息,而不是从模型属性获取信息。这意味着您以后必须小心删除此会话属性。对于表单视图的get请求包含用户信息也不是很“干净”,因此如果可以避免的话,我不会使用这个解决方案


  • 问了这个问题几个小时后,我想出了一个干净的解决办法

    我所做的是将处理注册过程的控制器的名称也更改为(“/signup”)。由于显示页面的控制器是@GetMapping(“/signup”),而处理注册过程的控制器是@PostMapping(“/signup”),因此没有冲突

    现在,即使控制器发生更改,url也保持不变,因为它们都已注册

    @GetMapping("/signup")
    public String signupPage() {return "signup";}
    
    @PostMapping("/signup")
    public String register(Account account, HttpSession session) {
    
        session.setAttribute("accountToRegister", account);
        accountManagement.accountRegistration(account);
    
        return "success";
    }
    

    这正是我想要的

    我想出了第三种方法,这是非常整洁,看看我的答案…如果它的工作,它的工作!选择越多越好。
    @GetMapping("/signup")
    public String signupPage() {return "signup";}
    
    @PostMapping("/signup")
    public String register(Account account, HttpSession session) {
    
        session.setAttribute("accountToRegister", account);
        accountManagement.accountRegistration(account);
    
        return "success";
    }