Java Spring MVC在控制器之间传递相同的对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21426519/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 08:40:15  来源:igfitidea点击:

Spring MVC pass same object between controller

javaspringspring-mvc

提问by Pratik Shelar

In Spring MVC how do I pass an object between two controller methods? I have an update form and an updateController. In the controller I have 2 methods, one for fetching the data and displaying it in a view. The second method of the controller is invoked when the user clicks update button with modified changes. What I am observing is that the object which I get in second method of the controller is not the same object which I passed to the view in the first controller method call. Its a new object altogether with all form fields mapped to it. How do I make sure that the same object is passed to the second controller method which was provided to the view by the first controller method?

在 Spring MVC 中,如何在两个控制器方法之间传递对象?我有一个更新表单和一个 updateController。在控制器中,我有两种方法,一种用于获取数据并将其显示在视图中。当用户单击带有修改更改的更新按钮时,将调用控制器的第二个方法。我观察到的是,我在控制器的第二个方法中获得的对象与我在第一个控制器方法调用中传递给视图的对象不同。它是一个新对象,所有表单字段都映射到它。如何确保将相同的对象传递给由第一个控制器方法提供给视图的第二个控制器方法?

@RequestMapping(value = "/showEmpDetail.html", method = RequestMethod.GET)
public String showEmpDetails(
        @RequestParam(value = "page", required = false) Integer page,
        HttpServletRequest request, @RequestParam("empId") Long empId,
        ModelMap model) {
    // Get employee using empId from DB
    model.addAttribute("emp",emp);
    return "showEmpDetail";
    }

The above controller method gets the emp values from Db and displays it correctly in the view. Now the user changes some details and clicks submit button. The following controller method is called.

上面的控制器方法从 Db 中获取 emp 值并在视图中正确显示它。现在用户更改了一些细节并点击提交按钮。调用以下控制器方法。

@RequestMapping(value = "/editEmpFormSubmission.html", method = RequestMethod.POST)
public String editEmpFormSubmission(
        @RequestParam(value = "page", required = false) Integer page,
        @ModelAttribute("emp") Employee emp, BindingResult result,
        ModelMap model, HttpServletRequest request) {
     // update changes in DB
    }

In the above controller method when I check the emp object its not the same object which I passed in previous controller call. The fields which are not form backed but had values were changed to null. How can I make sure the same object is passed by view. I do not want to add the object as sessionAttribute since a user might modify many employees in a session.

在上面的控制器方法中,当我检查 emp 对象时,它与我在之前的控制器调用中传递的对象不同。没有表单支持但有值的字段被更改为空。如何确保视图传递相同的对象。我不想将对象添加为 sessionAttribute,因为用户可能会在会话中修改许多员工。

回答by Tarmo

How can I make sure the same object is passed by view. I do not want to add the object as sessionAttribute since a user might modify many employees in a session

如何确保视图传递相同的对象。我不想将对象添加为 sessionAttribute,因为用户可能会在会话中修改许多员工

You could make a field in the object that is filled with a random number at the time of initial render and then store that object in the session. In the view you can map that field with a hidden input and now when user sends a request to edit action you can get that hidden field and fetch the original object from session by the number in the hidden field. That would resolve the multiple edits in different tabs conflict.

您可以在初始渲染时用随机数填充的对象中创建一个字段,然后将该对象存储在会话中。在视图中,您可以使用隐藏输入映射该字段,现在当用户发送编辑操作请求时,您可以获取该隐藏字段并通过隐藏字段中的数字从会话中获取原始对象。这将解决不同选项卡中的多个编辑冲突。

回答by M. Deinum

You have 3 options

你有3个选择

  1. Use @SessionAttributesto store the object in the session in between requests.
  2. Use a @ModelAttributeannotated method to retrieve the object before each request
  3. Write your own code and store it in the session (similair to 1 but more work on your part).
  1. 用于@SessionAttributes在请求之间的会话中存储对象。
  2. @ModelAttribute在每次请求之前使用带注释的方法检索对象
  3. 编写您自己的代码并将其存储在会话中(类似于 1,但您需要做更多的工作)。

Option 1

选项1

  1. Add the @SessionAttributesannotation to your controller class
  2. Add the SessionStatusas a parameter to your update method and the setComplete()method when you are finished with the object
  1. @SessionAttributes注释添加到您的控制器类
  2. SessionStatus作为参数添加到更新方法和setComplete()完成对象后的方法


@SessionAttributes("emp")
public class EmployeeController {
@RequestMapping(value = "/editEmpFormSubmission.html", method = RequestMethod.POST)
public String editEmpFormSubmission(
    @RequestParam(value = "page", required = false) Integer page,
    @ModelAttribute("emp") Employee emp, BindingResult result,
    ModelMap model, HttpServletRequest request
    SessionStatus status) {
 // update changes in DB
 status.setComplete();
}    
} 

Option 2

选项 2

  1. Add the method which retrieves the object from the database and annotate it with @ModelAttribute
  2. Cleanup your showEmpDetailsmethod as it should only return a view name
  1. 添加从数据库中检索对象并使用注释的方法 @ModelAttribute
  2. 清理你的showEmpDetails方法,因为它应该只返回一个视图名称


public class EmployeeController {

    @ModelAttribute("emp")
    public Employee getEmployee(@RequestParam("empdId") Long id) {
        // Get employee using empId from DB
        return  emp;
    }

    @RequestMapping(value = "/showEmpDetail.html", method = RequestMethod.GET)
    public String showEmpDetails() {) {
        return "showEmpDetail";
    }
}

Option 3

选项 3

  1. In your methods add the HttpSessionas an argument
  2. In your showDetailsmethod next to adding it to the model add it to the session
  3. In your editEmpFormSubmissionuse the one from the session and copy all non-null fields to the object from the session and store that in the database.
  1. 在您的方法中添加HttpSession作为参数
  2. 在您showDetails将其添加到模型旁边的方法中,将其添加到会话中
  3. 在您editEmpFormSubmission使用会话中的一个并将所有非空字段从会话复制到对象并将其存储在数据库中。

I wouldn't go for option, I strongly would suggest option 1 especially including the setComplete()on the SessionStatusobject for cleanup. You could also combine 1 and 2 (have a @ModelAttributeannotated method and still use @SessionAttributes.).

我不会选择,我强烈建议选项 1,特别是包括用于清理setComplete()SessionStatus对象。你也可以结合 1 和 2(有一个带@ModelAttribute注释的方法并且仍然使用@SessionAttributes.)。