zoukankan      html  css  js  c++  java
  • 统一前后台数据交互格式

    公司前后台数据交互的格式是统一的,前台对jquery的ajax方法进行了一些封装,也就是说开发的时候并不是自己去调用$.ajax方法,而是调用统一的方法去处理.

    我感觉还是比较方便的..确实可以少写一些代码(因为通用代码被封装了),而且管理起来比较方便,统一..然后观察了一些网上的其他网站...发现很多网站都是这么做的...于是我也想自己动手来试试....我自己是使用springmvc与fastjson来实现的...下面分享一下我的经验.

    网上例子:

    首先先来找个网上的例子:

    这个页面的地址是https://www.bugclose.com/login.html 是我随便找的一个例子.

    仔细观察上面2张图片,我们可以发现几个特点:

    1.前台错误提示的样式是一样的,不同的错误的弹出框是一模一样的,只是里面的文字换了而已.

    2.2次请求返回的数据格式基本是一样的.

    我的思考:

    第一张图片里的输出信息是来自root.email,第二张图片里的输出信息是来自errorMessage.

    如果我把2种错误输出信息都写到errorMessage里.那我js是不是可以有个通用的请求方法

     1 function commonAjax(data, url, callBack){
     2     $.ajax({
     3         contentType : 'application/json',
     4         url : url,
     5         data : data,
     6         type : 'POST',
     7         success : function(response){
     8             if(response.success == true){
     9                 callBack();//请求成功,就调用后续方法
    10             } else{
    11                 alert(response.errorMessage);//请求失败,用前端框架输出错误信息
    12             }        
    13         }
    14     });
    15 }

    大家不要吐槽上面这段JS有什么什么错误(我前端不是很好....我只是表达下大致意思..)

    这个网站的所有页面只要有弹框提示错误信息,都可以用这个方法.这样我觉得可以省不少力气,不用每次自己去写ajax,而且做到了统一,下次需求要求输出errorcode,或者换个提示样式的时候都只要修改一个地方就行了.不用每个页面都去改一遍.

    另外这种封装我觉得是可行的.一般做个页面肯定会用一个前端框架.提示信息的样式一定是统一的.不会这里用alert那里用框架自带的消息框.

    利用SpringMVC与fastjson实现前后台数据格式统一

    公司是用SpringMVC与jackson来做统一的...我不太喜欢和别人代码一样,另外公司的实现代码比较多...我这里只是写个demo,用不着那么多功能...所以我自己用springmvc与fastjson来做了一次尝试.

    首先我要介绍一些背景(据我所知):

    SpringMVC有内置的converter可以解析http请求.但是功能比较简单.json字符串默认是不支持的.

    前台一般页面写的都是JS代码,传过来的数据一般都是json格式.而fastjson可以方便的将json字符串转化成java对象.

    既然如此.我们要做的就是去实现一个converter,将前台传送过来的字符串解析成java对象.

    幸运的是fastjson自带了这个一个converter. 叫做FastJsonHttpMessageConverter. 所以只要配置这个converter就行了.

    在Springmvc的配置XML中加入下面这段代码就可以了.

     1 <mvc:annotation-driven>
     2         <mvc:message-converters>
     3             <bean
     4                 class="com.labofjet.web.CustomerFastJsonHttpMessageConverter">
     5                 <property name="features">
     6                     <list>
     7                         <value>WriteMapNullValue</value>
     8                         <value>SortField</value>
     9                     </list>
    10                 </property>
    11             </bean>
    12         </mvc:message-converters>
    13     </mvc:annotation-driven>

    我的class是我自己写的一个converter..继承了FastJsonHttpMessageConverter.feature是FastJsonHttpMessageConverter允许的一些特性.不写也可以.另外mvc:message-converters这个标签貌似对springmvc的版本有些要求.反正我http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd是验证不通过的..我用的是http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd....mvc:message-converters这个标签允许配置多个converter(看有个s就知道肯定允许多个).我这里只写了一个converter.对我来说足够了.因为我的目标就是前后台数据格式统一,所以只需要这么一个converter..哪天要加XML格式的时候我再加一个XML的converter就可以了.

    然后要用到2个注解:@ResponseBody和@RequestBody..分别对应AbstractHttpMessageConverter中的writeInternal与readInternal方法...对应向HTTP响应写入数据与从HTTP请求中读取数据返回java对象.

    converter可以有多个,所以到底哪个converter来处理呢? 这要看converter支持什么类型的MediaType.

    如上图,这次请求的ContentType是blablabla.......(看截图红色区域)

    而fastjson允许的MediaType是:

    1     public FastJsonHttpMessageConverter(){
    2         super(new MediaType("application", "json", UTF8), new MediaType("application", "*+json", UTF8));
    3     }

    所以我的commonAjax方法里需要指明

    contentType : 'application/json'

    这样才能被fastjson的converter解析...当然你也可以自己写一个converter去映射N种MediaType.

    这样做了以后前后台json格式的数据都可以被fastjson的converter去处理了.然后我们来定义一个统一的数据格式:

     1 package com.labofjet.web;
     2 
     3 import java.util.HashMap;
     4 import java.util.Map;
     5 
     6 import com.alibaba.fastjson.JSON;
     7 import com.alibaba.fastjson.JSONObject;
     8 import com.labofjet.exception.BaseException;
     9 
    10 /**
    11  * 用于前后台数据交互时候格式的统一
    12  * 
    13  * @author jyzjyz12@163.com
    14  * 
    15  */
    16 public class ContextDTO {
    17     private boolean success;
    18     private Map<String, Object> data;
    19     private BaseException exception;
    20 
    21     public boolean getSuccess() {
    22         return success;
    23     }
    24 
    25     public void setSuccess(boolean success) {
    26         this.success = success;
    27     }
    28 
    29     public Map<String, Object> getData() {
    30         return data;
    31     }
    32 
    33     public void setData(Map<String, Object> data) {
    34         this.data = data;
    35     }
    36 
    37     public BaseException getException() {
    38         return exception;
    39     }
    40 
    41     public void setException(BaseException exception) {
    42         this.exception = exception;
    43     }
    44 
    45     public <T> T getDTOFromData(String name, Class<T> dtoClass){
    46         JSONObject o = (JSONObject) data.get(name);
    47         return JSON.parseObject(o.toJSONString(), dtoClass);
    48     }
    49     
    50     public void putData(String name, Object obj){
    51         if(data == null){
    52             data = new HashMap<String, Object>();
    53         }
    54         data.put(name, obj);
    55     }   
    56 }

    假设我的通用格式是这个..

    然后我有个和某些业务相关的DTO(我这里随便找了个entity...只是测试用....举个例子而已..大家无视没用的注解....)

    package com.labofjet.entity;
    
    import javax.persistence.Embedded;
    import javax.persistence.EmbeddedId;
    import javax.persistence.Entity;
    import javax.persistence.NamedStoredProcedureQueries;
    import javax.persistence.NamedStoredProcedureQuery;
    import javax.persistence.ParameterMode;
    import javax.persistence.StoredProcedureParameter;
    
    import org.apache.commons.lang3.builder.ToStringBuilder;
    
    @Entity
    @NamedStoredProcedureQueries({
            @NamedStoredProcedureQuery(name = "User.plus1", procedureName = "plus1inout", parameters = {
                    @StoredProcedureParameter(mode = ParameterMode.IN, name = "arg", type = Integer.class),
                    @StoredProcedureParameter(mode = ParameterMode.OUT, name = "res", type = Integer.class) }),
            @NamedStoredProcedureQuery(name = "User.mytest", procedureName = "mytest") })
    public class A {
        @EmbeddedId
        APK id;
    
        String age;
    
        @Embedded
        AComponent acomponent;
    
        int b;
        
        public AComponent getAcomponent() {
            return acomponent;
        }
    
        public void setAcomponent(AComponent acomponent) {
            this.acomponent = acomponent;
        }
    
        public String getAge() {
            return age;
        }
    
        public void setAge(String age) {
            this.age = age;
        }
    
        public APK getId() {
            return id;
        }
    
        public void setId(APK id) {
            this.id = id;
        }
    
        
        
        /**
         * @return the b
         */
        public int getB() {
            return b;
        }
    
        /**
         * @param b the b to set
         */
        public void setB(int b) {
            this.b = b;
        }
    
        @Override
        public int hashCode() {
            // TODO Auto-generated method stub
            System.out.println("Ahash");
            return super.hashCode();
        }
    
        @Override
        public boolean equals(Object obj) {
            // TODO Auto-generated method stub
            System.out.println("Aequals");
            return super.equals(obj);
        }
        
        @Override
        public String toString() {
            return ToStringBuilder.reflectionToString(this);
        }
    }
    
    
    
    
    package com.labofjet.entity;
    
    import java.io.Serializable;
    
    public class APK implements Serializable{
        String id;
        String name;
        public String getId() {
            return id;
        }
        public void setId(String id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        
        public APK() {
            // TODO Auto-generated constructor stub
        }
        
        public APK(String id, String name){
            this.id = id;
            this.name = name;
        }
        
        
        
        @Override
        public int hashCode() {
            // TODO Auto-generated method stub
            System.out.println("APKhash");
            return super.hashCode();
        }
        
        @Override
        public boolean equals(Object obj) {
            // TODO Auto-generated method stub
            System.out.println("APKequals");
            return super.equals(obj);
        }
        
    }

    然后我在controller里的测试代码

    1     @RequestMapping("/test15")
    2     @ResponseBody
    3     public Object index15(@RequestBody ContextDTO context) {
    4         A a = context.getDTOFromData("aName", A.class);
    5         ContextDTO dto = new ContextDTO();
    6         dto.putData("aDataName", a);
    7         dto.setSuccess(true);
    8         return dto;
    9     }

    前台请求:

    后台返回给前台的数据

    后台获取到的数据

    是不是很简单呀....

  • 相关阅读:
    Oracle函数如何把符串装换为小写的格式
    Oralce中的synonym同义词
    JS中getYear()的兼容问题
    How to do SSH Tunneling (Port Forwarding)
    所谓深度链接(Deep linking)
    upload size of asp.net
    发一个自动刷网站PV流量的小工具
    解决Visual Studio 2008 下,打开.dbml(LINQ) 文件时,提示"The operation could not be completed." 的问题。
    在资源管理器中使鼠标右键增加一个命令,运行cmd,同时使得当前路径为资源管理器当前的目录
    使用SQL语句获取Sql Server数据库的版本
  • 原文地址:https://www.cnblogs.com/abcwt112/p/5169250.html
Copyright © 2011-2022 走看看