我希望将对象(放置在第一个控制器中的函数模型中)传递给第二个控制器的函数,并将接收到的对象放在函数模型中。
我理解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;
}
答案 0 :(得分:2)
您需要从客户端发送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;
}
答案 1 :(得分:1)
您可以使用RedirectAttributes和ModelAttribute实现此目的。
通常情况下,我只是说使用flash属性,但由于这些属性存储在会话中,并且您希望在没有会话的情况下执行此操作,因此您必须使用常规属性执行此操作。
实际上,在再次阅读您的代码后,我认为您真正想要做的是使用会话和Flash属性。不使用一个安全性较低(信任客户端携带用户对象)和/或容易出错。
重定向属性的工作原理是在重定向网址上添加重定向属性作为参数,并发送比简单字符串,整数,双精度等更复杂的内容。我们需要先将其序列化。在这里,我将对象转换为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
。