@produces
注解@Produces用于定义方法的响应实体的数据类型,可以定义一个或多个,然后与请求头中Accept匹配,匹配成功则将响应数据进行对应转换。
@RequestMapping(value = "/produces", produces = "application/json"):表示该功能处理方法将生产json格式的数据,此时根据http请求头中的Accept进行匹配,如请求头“Accept:application/json”时即可匹配;
该功能处理方法将生产xml格式的数据,此时根据http请求头中的Accept进行匹配,如请求头“Accept:application/xml”时即可匹配。
headers = "Accept=application/json"”更能表明你的目的。
服务器控制器代码详解cn.javass.chapter6.web.controller.consumesproduces.ProducesController;
客户端代码类似于之前的Content-Type中的客户端,详见ProducesController.java代码。
当你有如下Accept头:
①Accept:text/html,application/xml,application/json
将按照如下顺序进行produces的匹配 ①text/html ②application/xml ③application/json
②Accept:application/xml;q=0.5,application/json;q=0.9,text/html
将按照如下顺序进行produces的匹配 ①text/html ②application/json ③application/xml
q参数为媒体类型的质量因子,越大则优先权越高(从0到1)
③Accept:*/*,text/*,text/html
将按照如下顺序进行produces的匹配 ①text/html ②text/* ③*/*
即匹配规则为:最明确的优先匹配。
代码详见ProducesPrecedenceController1、ProducesPrecedenceController2、ProducesPrecedenceController3。
Accept详细信息,请参考http://tools.ietf.org/html/rfc2616#section-14.1。
方法级别的注解覆盖类级别上的注解
类级别上映射为 @RequestMapping(value="/narrow", produces="text/html"),
方法级别上映射为@RequestMapping(produces="application/xml"),
此时方法级别的映射将覆盖类级别,因此请求头是“Accept:application/xml”则能成功,请求头为“text/html”将不能匹配,匹配不成功(或转换失败,如json转换缺依赖包)会报406错误码,表示不支持的请求媒体类型。
详见cn.javass.chapter6.web.controller.consumesproduces.NarrowController。
只有生产者/消费者 模式 是 覆盖,其他的使用方法是继承,如headers、params等都是继承。
四、组合使用是“或”的关系
@RequestMapping(produces={"text/html", "application/json"}) :
将匹配“Accept:text/html”或“Accept:application/json”。
五、问题
消费的数据,如JSON数据、XML数据都是由我们读取请求的InputStream并根据需要自己转换为相应的模型数据,比较麻烦;
生产的数据,如JSON数据、XML数据都是由我们自己先把模型数据转换为json/xml等数据,然后输出响应流,也是比较麻烦的。
@RequestBody、@ResponseBody
)和一组转换类(HttpMessageConverter
)来完成我们遇到的问题。
@ResponseBody,@RequestBody,@PathVariable
控制器:
1. @Controller
2. public class
3.
4. /**
5. * 查询个人信息
6. *
7. * @param id
8. * @return
9. */
10. @RequestMapping(value = "/person/profile/{id}/{name}/{status}", method = RequestMethod.GET)
11. public @ResponseBody
12. @PathVariable int id, @PathVariable
13. @PathVariable boolean
14. return new
15. }
16.
17. /**
18. * 登录
19. *
20. * @param person
21. * @return
22. */
23. @RequestMapping(value = "/person/login", method = RequestMethod.POST)
24. public @ResponseBody
25. @RequestBody
26. return
27. }
28. }
备注:
@RequestMapping(value = "/person/profile/{id}/{name}/{status}", method = RequestMethod.GET) 中的 {id}/{name}/{status} 与 @PathVariable int id, @PathVariable String name,@PathVariable boolean status 一一对应,按名匹配。
这是restful式风格。
如果映射名称有所不一,可以参考如下方式:
1. @RequestMapping(value = "/person/profile/{id}", method = RequestMethod.GET)
2. public @ResponseBody
3. Person porfile(@PathVariable("id") int
4. return new
5. }
- GET模式下,这里使用了@PathVariable绑定输入参数,非常适合Restful风格。因为隐藏了参数与路径的关系,可以提升网站的安全性,静态化页面,降低恶意攻击风险。
- POST模式下,使用@RequestBody绑定请求对象,Spring会帮你进行协议转换,将Json、Xml协议转换成你需要的对象。
- @ResponseBody可以标注任何对象,由Srping完成对象——协议的转换。
@
RequestParam用法与@
PathVariable
类似,功能类似request.getparameter("xx"),xx名称应与请求参数匹配。
@RequestMapping(value="fileupload", method=RequestMethod.POST,produces="text/html;charset=utf-8")
public @ResponseBody String addPic(HttpServletResponse response,HttpServletRequest request,
@RequestParam(value="file", required=false) MultipartFile file) throws IOException{
System.out.println(file.getOriginalFilename());
String path = request.getSession().getServletContext().getRealPath("upload");
if (path ==null){path="D:\\fileupload";}
File targetfile=new File(path,file.getOriginalFilename());
if (!targetfile.exists()){
targetfile.mkdirs();
}
try{
file.transferTo(targetfile);
return "success";
}catch(Exception e){
e.printStackTrace();
return "unkonw error";
}