簡體   English   中英

如何將對象從一個控制器傳遞到另一個控制器

[英]How to pass an object from one controller to another controller

我想傳遞對象(放置在第一個控制器中的函數模型中)以由第二個控制器的函數接收,並將接收到的對象放在函數的模型中。

我理解HTTP是無狀態的,但有沒有辦法將一個對象從一個控制器傳遞到另一個控制器而不使用Spring MVC中的會話? 謝謝。

請參閱下面給出的示例代碼。

FirstController.java

@RequestMapping(value="search-user",method=RequestMethod.POST)
public ModelAndView searchUser (HttpServletRequest request) {
    //Retrieve the search query by request.getParameter
    String searchQuery = request.getParameter("searchQuery");

    //Search for the user (this is the object that I want to pass)
    User user = userDao.searchUser(searchQuery);

    ModelAndView mav = new ModelAndView(new RedirectView("display-searched-user"));
    mav.addObject("user",user);

    return mav;
}

SecondController.java

@RequestMapping(value="display-searched-user",method={RequestMethod.GET,RequestMethod.POST})
public ModelAndView displayResultUser (HttpServletRequest request) {
    ModelAndView mav = new ModelAndView();
    mav.setViewName("result");

    //I want to receive the object from the FirstController and set that object in this function's model.

    return mav;
}

您需要從客戶端發送2個呼叫並將“用戶”發送到第二個控制器(您應該修改它以接受用戶)。 因此,對“/ search-user”的第一次調用返回包含用戶的對象。 客戶端提取用戶並將其發送到“/ display-searching-user”。

另一種方法可能是,第二個控制器中的請求也接受參數“searchQuery”。 在這種情況下,只需修改您的第二個控制器,如下所示:

@RequestMapping(value="display-searched-user",method={RequestMethod.GET,RequestMethod.POST})
public ModelAndView displayResultUser (HttpServletRequest request) {
    ModelAndView mav = new ModelAndView();
    mav.setViewName("result");

    FirstController fc = new FirstController();
    return fc.searchUser(request);
}

編輯:

我剛剛閱讀了CrazySabbath關於創建交通運輸類的建議。 假設兩個控制器都可以訪問它,我將實現這樣的傳輸類:

public class UserTransporter {

    private static boolean userAvailable = false;
    private static User user;

    public static boolean isUserAvailable() {
        return userAvailable;
    }

    public static void setUser(User user) {
        UserTransporter.user = user;
        userAvailable = true;
    }

    public static User getUser() {
        userAvailable = false;
        return user;
    }
}

為了清楚起見:我添加了布爾變量,因為我想讓它無法獲得null或獲取用戶,這是之前通過調用獲得的。 如果您不想檢查它,只需刪除布爾值以及我使用它的任何行。

第一個控制器需要更改為:

@RequestMapping(value="search-user",method=RequestMethod.POST)
public ModelAndView searchUser (HttpServletRequest request) {
    //Retrieve the search query by request.getParameter
    String searchQuery = request.getParameter("searchQuery");

    //Search for the user (this is the object that I want to pass)
    User user = userDao.searchUser(searchQuery);

    ModelAndView mav = new ModelAndView(new RedirectView("display-searched-user"));
    mav.addObject("user",user);

    UserTransporter.setUser(user);

    return mav;
}

第二個控制器需要更改為:

@RequestMapping(value="display-searched-user",method={RequestMethod.GET,RequestMethod.POST})
public ModelAndView displayResultUser (HttpServletRequest request) {
    ModelAndView mav = new ModelAndView();
    mav.setViewName("result");

    User user;
    if(UserTransporter.isUserAvailable()) user = UserTransporter.getUser();
    else return "ERROR, no user available to display";

    //do something with the obtained user object

    return mav;
}

您可以使用RedirectAttributesModelAttribute實現此目的

通常我會說只使用flash屬性,但由於這些屬性存儲在會話中並且你想在沒有會話的情況下執行此操作,因此您必須使用常規屬性執行此操作。

實際上 ,在再次閱讀您的代碼后,我認為您真正想要做的是使用會話和Flash屬性。 不使用一個安全性較低(信任客戶端攜帶用戶對象)和/或容易出錯。

重定向屬性通過在重定向URL上添加重定向屬性作為參數來工作,並發送比簡單字符串,整數,雙精度等更復雜的任何內容。我們需要先將其序列化。 在這里,我通過將對象轉換為JSON然后對其進行Base64編碼來完成此操作。

這是一個完整的,有效的例子:

@Controller
@SpringBootApplication
public class RedirectController {

    @Autowired
    private ObjectMapper objectMapper;

    // Bean for converting from TestThing to base64 encoded string
    @Bean
    public Converter<TestThing, String> testThingToStringConverter() {
        return new Converter<TestThing, String>() {
            public String convert(TestThing thing) {
                try {
                    return Base64.getUrlEncoder().encodeToString(
                            objectMapper.writeValueAsString(thing)
                                    .getBytes(StandardCharsets.UTF_8));
                } catch (IOException e){
                    throw new RuntimeException(e);
                }
            }
        };
    }

    // Bean for converting from base64 encoded string to TestThing
    @Bean
    public Converter<String, TestThing> stringToTestThingConverter() {
        return new Converter<String, TestThing>() {
            public TestThing convert(String thing) {
                try {
                    return objectMapper.readValue(Base64.getUrlDecoder().decode(thing), TestThing.class);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        };
    }

    public static class TestThing implements Serializable {

        private String firstString;
        private String secondString;

        public String getFirstString() {
            return firstString;
        }

        public void setFirstString(String firstString) {
            this.firstString = firstString;
        }

        public String getSecondString() {
            return secondString;
        }

        public void setSecondString(String secondString) {
            this.secondString = secondString;
        }
    }


    @GetMapping("/test")
    public String testValidation(@RequestParam String firstString,
                                 @RequestParam String secondString,
                                 RedirectAttributes redirectAttributes) {
        TestThing redirectObject = new TestThing();
        redirectObject.firstString = firstString;
        redirectObject.secondString = secondString;

        redirectAttributes.addAttribute("redirectObject", redirectObject);

        return "redirect:/redirected";
    }

    @ResponseBody
    @GetMapping("/redirected")
    public TestThing redirected(@ModelAttribute("redirectObject") TestThing thing) {
        return thing;
    }
    public static void main(String[] args) {
        SpringApplication.run(RedirectController.class, args);
    }
}

如果我們使用Curl與我們的控制器交談,我們可以看到它的工作原理:

# -L follows redirects
$ curl -L "localhost:8080/test?firstString=first&secondString=second
{"firstString":"first","secondString":"second"}% 

# Now let's do it manually
curl -v "localhost:8080/test?firstString=first&secondString=second"
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /test?firstString=first&secondString=second HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.57.0
> Accept: */*
> 
< HTTP/1.1 302 
< Location: http://localhost:8080/redirected?redirectObject=eyJmaXJzdFN0cmluZyI6ImZpcnN0Iiwic2Vjb25kU3RyaW5nIjoic2Vjb25kIn0%3D
< Content-Language: en-GB
< Content-Length: 0
< Date: Thu, 07 Dec 2017 15:38:02 GMT
< 
* Connection #0 to host localhost left intact

$ curl http://localhost:8080/redirected\?redirectObject\=eyJmaXJzdFN0cmluZyI6ImZpcnN0Iiwic2Vjb25kU3RyaW5nIjoic2Vjb25kIn0%3D
{"firstString":"first","secondString":"second"}

如果您使用flash屬性,示例是相同的,但您不需要兩個Converter並且您使用addFlashAttribute而不是addAttribute

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM