篇十六:application/json请求

一、Post请求的集中方式

1、基础知识

  HTTP/1.1 协议规定的 HTTP 请求方法有 OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE、CONNECT 这几种。其中 POST 一般用来向服务端提交数据,协议规定 POST 提交的数据必须放在消息主体(entity-body)中,但协议并没有规定数据必须使用什么编码方式。实际上,开发者完全可以自己决定消息主体的格式,只要最后发送的 HTTP 请求满足上面的格式就可以。

 

2、application/x-www-form-urlencoded

  最常见的 POST 提交数据的方式,典型的key-val键值对

  优点:无需转化,在request中直接获取,框架也会将同名属性封装到接收对象中,form表单默认此方式提交请求

  缺点:消息包大,耗流量

 

3、multipart/form-data

  最常见的 POST 提交数据的方式,也是典型的key-val键值对,

  优点:无需转化,在request中直接获取,框架也会将同名属性封装到接收对象中,支持文件流上传

<form id="form1" runat="server" enctype="multipart/form-data" >
    
</form>

 

4、application/json

  postman设置请求方式

 

  

 

二、application/json请求的解析

使用jackson

1、下载jar包

            <dependency>
                <groupId>org.codehaus.jackson</groupId>
                <artifactId>jackson-core-asl</artifactId>
                <version>1.9.13</version>
            </dependency>
            <dependency>
                <groupId>org.codehaus.jackson</groupId>
                <artifactId>jackson-mapper-asl</artifactId>
                <version>1.9.13</version>
            </dependency>            

2、配置spring-context.xml

    <!-- json转化器 -->
     <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">      
        <property name="messageConverters">      
            <list >      
                <ref bean="mappingJacksonHttpMessageConverter" />      
            </list>      
        </property>      
     </bean> 

     <bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">    
        <property name="supportedMediaTypes">    
            <list>    
                <value>application/json;charset=UTF-8</value>    
           </list>    
        </property>  
     </bean> 

3、在Controller中用对象接收参数,使用注解@ResponseBody

  目前使用@ResponseBody只能获取一次,传输是基于流的

  a.使用任意@ResponseBody String msg接收,获取请求的json字符串,然后手动解析获取值

  b.使用对象,对象中的同名属性会被赋值,但是限制条件就是必须使用一个对象接收

@ResponseBody
    @RequestMapping(value="/NewsAttention" ,method=RequestMethod.POST)
    public String saveNewsAttention(HttpServletRequest req,@RequestBody NewsBasic mNewsBasic) {
     ....      
  }

 

三、拦截器中获取application/json的body

public class AppManagerInterceptor extends HandlerInterceptorAdapter
{
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        
        HttpServletRequest req = request;
        String message = "";
        
        String submitMehtod = req.getMethod();  
        // GET  
        if (submitMehtod.equals("GET")) {  
            message =  new String(req.getQueryString().getBytes("iso-8859-1"),"utf-8").replaceAll("%22", "\"");  
        // POST  
        } else {  
            message =  getRequestPostStr(req);  
        }  
        
        boolean isAppmanager = true;
        HandlerMethod invocation = (HandlerMethod)handler;
        if (invocation.getMethod().isAnnotationPresent(AppManagerCheck.class)) {
            JSONObject json = JSONObject.parseObject(message);
            //获取用户id
            String userId = json.getString("userId");
            //校验用户是否是APP管理员
            if(isAppmanager)
            {
                return true;
            }else{
                response.sendRedirect(req.getContextPath()+"/mobile/usereckAppManager");
                return false;
            }
            
        }
        return isAppmanager;
        
    }

    
     /**       
     * 描述:获取 post 请求的 byte[] 数组 
     * <pre> 
     * 举例: 
     * </pre> 
     * @param request 
     * @return 
     * @throws IOException       
     */  
    public static byte[] getRequestPostBytes(HttpServletRequest request)  
            throws IOException {  
        int contentLength = request.getContentLength();  
        if(contentLength<0){  
            return null;  
        }  
        byte buffer[] = new byte[contentLength];  
        for (int i = 0; i < contentLength;) {  
  
            int readlen = request.getInputStream().read(buffer, i,  
                    contentLength - i);  
            if (readlen == -1) {  
                break;  
            }  
            i += readlen;  
        }  
        return buffer;  
    }  
    
    /**       
     * 描述:获取 post 请求内容 
     * <pre> 
     * 举例: 
     * </pre> 
     * @param request 
     * @return 
     * @throws IOException       
     */  
    public static String getRequestPostStr(HttpServletRequest request)  
            throws IOException {  
        byte buffer[] = getRequestPostBytes(request);  
        String charEncoding = request.getCharacterEncoding();  
        if (charEncoding == null) {  
            charEncoding = "UTF-8";  
        }  
        return new String(buffer, charEncoding);  
    }  
}

 

四、application/json的拦截器

  问题:application/json请求的数据存储在六中,整个请求过程中,只能读取一次,拦截器中把校验参数放在body,会使校验一次以后,Controller中获取不到body

  方案一:将校验参数存放现在header中,获取header中的值不影响流

  java中获取header

    //知道Key获取值,当不存在时,返回Null,不报错
    private String getUserAgent() {
        return request.getHeader("user-agent");
    }
    //批量获取headers中的值,封装成键值对
    private Map<String, String> getHeadersInfo() {
        Map<String, String> map = new HashMap<String, String>();
        Enumeration headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = (String) headerNames.nextElement();
            String value = request.getHeader(key);
            map.put(key, value);
        }
        return map;
    }

 

  

 

posted @ 2016-11-17 21:28  刘广平  阅读(4363)  评论(0)    收藏  举报