2

我即将编写一个 Spring MVC 控制器来服务/接收 HTML 表单和 JSON。最好的方法似乎是使用 RESTful 控制器,但作为我写的第一个控制器,我想把它做好!

是否有可能有一种方法,如果它是一个 HTML 请求,将返回一个由 InternalResourceViewResolver 呈现的视图,或者如果它是一个 ajax 请求,将一个实体呈现为 JSON?

更新也是如此,您能否编写一个控制器方法来接受从传入 JSON 转换的对象或来自 HTML 表单的 @Valid 对象,具体取决于内容类型?

在我看来,您必须能够做到,否则为什么使用 sf taglib 表单元素在 HTML 表单中支持 DELETE 和 PUT?只是似乎无法在任何地方找到如何做到这一点的解释!

干杯! NFV

4

2 回答 2

2

我会试一试。

这是我在Configuration课堂上的内容:

@Bean(name = "viewResolver")
public ContentNegotiatingViewResolver viewResolver() {
    final ContentNegotiatingViewResolver contentNegotiatingViewResolver = new ContentNegotiatingViewResolver();
    contentNegotiatingViewResolver.setOrder(1);
    contentNegotiatingViewResolver.setFavorPathExtension(true);
    contentNegotiatingViewResolver.setFavorParameter(true);
    contentNegotiatingViewResolver.setIgnoreAcceptHeader(false);
    final Map<String, String> mediaTypes = new HashMap<String, String>();
    mediaTypes.put("json", "application/x-json");
    mediaTypes.put("json", "text/json");
    mediaTypes.put("json", "text/x-json");
    mediaTypes.put("json", "application/json");
    mediaTypes.put("xml", "text/xml");
    mediaTypes.put("xml", "application/xml");
    contentNegotiatingViewResolver.setMediaTypes(mediaTypes);
    final List<View> defaultViews = new ArrayList<View>();
    defaultViews.add(jsonView());
    defaultViews.add(xmlView());
    contentNegotiatingViewResolver.setDefaultViews(defaultViews);
    return contentNegotiatingViewResolver;
}

@Bean(name = "xStreamMarshaller")
public XStreamMarshaller xStreamMarshaller() {
    return new XStreamMarshaller();
}

@Bean(name = "xmlView")
public MarshallingView xmlView() {
    final MarshallingView marshallingView = new MarshallingView(xStreamMarshaller());
    marshallingView.setContentType("application/xml");
    return marshallingView;
}

@Bean(name = "jsonView")
public MappingJacksonJsonView jsonView() {
    return new MappingJacksonJsonView();
}

这就是Controller.

@RequestMapping(value = { "/pets" }, method = RequestMethod.GET)
public String list(Model model) {
    model.addAttribute("pets", petRepository.findAll());
    return "pets/list";
}

@RequestMapping(value = { "/pets" }, method = RequestMethod.POST)
public String create(@Valid @RequestBody Pet pet, Model model) {
    petRepository.save(pet);
    return "redirect:pets/read/" + pet.getId();
}

@RequestMapping(value = { "/pets/{petId}" }, method = RequestMethod.GET)
public String read(@PathVariable Integer petId, Model model) {
    model.addAttribute("pet", petRepository.findOne(petId));
    return "pets/read";
}

@RequestMapping(value = { "/pets" }, method = RequestMethod.PUT)
public String update(@Valid @RequestBody Pet pet, Model model) {
    petRepository.save(pet);
    return "redirect:pets/read/" + pet.getId();
}

@RequestMapping(value = { "/pets/{orderId}" }, method = RequestMethod.DELETE)
public void delete(@PathVariable Integer petId, Model model) {
    petRepository.delete(petId);
}

根据我的经验,您可以将 HTML 表单或 JSON 对象作为@RequestBody. 试试看。

于 2012-10-09T18:27:08.573 回答
0

It's surely possible but I don't see why that would be useful.

In my opnion a controller method should be created for every action you will need, making a controller handle 2 different kinds of input will make this controller method complicated to read and maintain over time.

A way to do it is using consumes in @RequestMapping annotation like this, then you write 2 methods and each watches for it's kind of input.

@RequestMapping(value = "/pets", method = RequestMethod.POST, consumes="application/json");

source of this code

于 2012-10-09T11:16:52.780 回答