Java Spring MVC进阶(2)--@produces、@PathVariable、@RequestParam等


@produces

注解@Produces用于定义方法的响应实体的数据类型,可以定义一个或多个,然后与请求头中Accept匹配,匹配成功则将响应数据进行对应转换。

@RequestMapping(value = "/produces", produces = "application/json"):表示该功能处理方法将生产json格式的数据,此时根据http请求头中的Accept进行匹配,如请求头“Accept:application/json”时即可匹配;

@RequestMapping(value = "/produces", produces = "application/xml"):表示功能处理方法将生产xml格式的数据,此时根据http请求头中的Accept进行匹配,如请求头“Accept:application/xml”时即可匹配。

   

此种方式相对使用@RequestMapping的“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等数据,然后输出响应流,也是比较麻烦的。

 

Spring提供了一组注解(@RequestBody、@ResponseBody)和一组转换类(HttpMessageConverter)来完成我们遇到的问题。



@ResponseBody,@RequestBody,@PathVariable 
控制器: 

Java代码   收藏代码
  1. @Controller  
  2. public class PersonController {  
  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.     Person porfile(@PathVariable int id, @PathVariable String name,  
  13.             @PathVariable boolean status) {  
  14.         return new Person(id, name, status);  
  15.     }  
  16.   
  17.     /** 
  18.      * 登录 
  19.      *  
  20.      * @param person 
  21.      * @return 
  22.      */  
  23.     @RequestMapping(value = "/person/login", method = RequestMethod.POST)  
  24.     public @ResponseBody  
  25.     Person login(@RequestBody Person person) {  
  26.         return person;  
  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式风格。 
如果映射名称有所不一,可以参考如下方式: 

Java代码   收藏代码
  1. @RequestMapping(value = "/person/profile/{id}", method = RequestMethod.GET)  
  2. public @ResponseBody  
  3. Person porfile(@PathVariable("id"int uid) {  
  4.     return new Person(uid, name, status);  
  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";
      }




你可能感兴趣的:(spring,mvc)