zoukankan      html  css  js  c++  java
  • 比较合适的前后端交互方式

    这篇博客是对过去博客的整理与总结,现在,以下的博客都可以认为过时了。

    使用Ajax向SpringMVC传递Json数据

    存在日期类型的JSON数据,进行SpringMVC参数绑定时存在的问题和解决方案

    SpringMVC配置数据验证(JSR-303)

    前端发送请求

        var jsonObj = {
            'name' : '啊aaaa',                 // 乱码问题
            'date' : '1905-01-02 14:23:59',    // 时间转化问题
            'money' : '10.333',                // 小数
            'no' : '9',                        // 数字
            'serial' : '2147483999'            // Long
        };
    
        $.ajax({
            type : "post",
            url : "/interaction",
            dataType : "json",
            contentType : 'application/json',
            data : JSON.stringify(jsonObj),
            success : function(data) {
                alter(data);
            },
            error : function(data) {
                // TODO
            }
        });

    没什么问题。

    后端绑定参数

    1、首先需要指定SpringMVC参数绑定之前的JSON转化策略,选择Jackson。

    2、其次需要自定义一个ObjectMapper类,目的是在Jackson的ObjectMapper上追加定制对于日期转化的策略。

    3、最后,把这些策略反映在SpringMVC的配置文件中。

            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>2.9.0</version>
            </dependency>
    public class JacksonObjectMapper extends ObjectMapper {
    
        private static final long serialVersionUID = -8909209092708797621L;
    
        public JacksonObjectMapper() {
            super();
            configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        }
    
    }
        <mvc:annotation-driven>
            <mvc:message-converters>
                <bean
                    class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                    <property name="objectMapper">
                        <bean
                            class="io.spldeolin.bestpractice.util.JacksonObjectMapper"/>
                    </property>
                </bean>
            </mvc:message-converters>
        </mvc:annotation-driven>

    通过写个请求方法和实体类来测试一下

        @RequestMapping(value = "interaction", method = RequestMethod.POST)
        @ResponseBody
        public String interaction(@RequestBody InteractionInput input) {
            LOG.info(input);
            return "success";
        }
    package io.spldeolin.bestpractice.input;
    
    import java.math.BigDecimal;
    import java.util.Date;
    
    public class InteractionInput {
    
        private String name;
    
        private Date date;
    
        private BigDecimal money;
    
        private Integer no;
    
        private Long serial;
    
      // getters and setters
    
    }

    结果

    绑定失败时的处理

    示例中,如果前端把jsonObj.date改成"1905-------01-------02 14爱上打是的:23ssssss:59"这样的非法格式,绑定就会失败,如图所示

    这样的提示实际上不够友好(虽然发生的原因基本上是前端BUG),但最好还是捕获一下。

        @ExceptionHandler(HttpMessageNotReadableException.class)
        @ResponseStatus(HttpStatus.OK)
        @ResponseBody
        public String processHttpMessageNotReadableException(HttpMessageNotReadableException e) {
            return "请求不可读(可能原因:1.没有Request Body 2.Request Body格式有误)";
        }

    结果

    参数校验

    参数绑定成功了,但最好再加一层校验,比如年龄,用Integer类型绑定,虽然上万的数字也可以成功绑定,但显然是不合理的。所以应该引入JSR303的实现

            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-validator</artifactId>
                <version>5.4.1.Final</version>
            </dependency>
    package io.spldeolin.bestpractice.input;
    
    import java.math.BigDecimal;
    import java.util.Date;
    import javax.validation.constraints.Max;
    
    public class InteractionInput {
    
        private String name;
    
        private Date date;
    
        @Max(value = 10L, message = "钱太多")
        private BigDecimal money;
    
        private Integer no;
    
        private Long serial;
    
      // getters and setters
    
    }
        @RequestMapping(value = "interaction", method = RequestMethod.POST)
        @ResponseBody
        public String interaction(@RequestBody @Valid InteractionInput input, BindingResult checker) {
            // 这里只是为了演示,实际上这段解析BindingResult对象的代码最好抽到共通类中
            if (checker.hasFieldErrors()) {
                for (FieldError error : checker.getFieldErrors()) {
                    String errmsg = error.getDefaultMessage();
                    LOG.error(errmsg);
                    return errmsg;
                }
            }
            LOG.info(input);
            return "success";
        }

    返回值

    最好返回一个实体类对象,而不是一个具体的String什么的,比如

        @RequestMapping(value = "interaction", method = RequestMethod.POST)
        @ResponseBody
        public RequestResult interaction(@RequestBody @Valid InteractionInput input, BindingResult checker) {
            // 这里只是为了演示,实际上这段解析BindingResult对象的代码最好抽到共通类中
            if (checker.hasFieldErrors()) {
                for (FieldError error : checker.getFieldErrors()) {
                    String errmsg = error.getDefaultMessage();
                    LOG.error(errmsg);
                    return RequestResult.failure().errmsg(errmsg);
                }
            }
            LOG.info(input);
            return RequestResult.success().data("交互成功。(实际开发中data参数可以放各种想要传给前端的对象)");
        }
    function interaction() {
        var jsonObj = {
            'name' : '啊aaaa', // 乱码问题
            'date' : '1905-01-02 14:23:59', // 时间转化问题
            'money' : '10.333', // 小数
            'no' : '9', // 数字
            'serial' : '2147483999' // Long
        };
        $.ajax({
            type : "post",
            url : "/interaction",
            dataType : "json",
            contentType : 'application/json',
            data : JSON.stringify(jsonObj),
            success : function(resp) {
                if (resp.result) {
                    alert(resp.data);
                    // 或者解析这个resp.data
                } else {
                    alert(resp.errmsg);
                }
            },
            error : function(data) {
                // TODO
            }
        });
    }
    public class RequestResult {
    
        private boolean result;
    
        private Object data;
    
        private String errmsg;
    
        public boolean isResult() {
            return result;
        }
    
        private RequestResult() {}
    
        public static RequestResult success() {
            RequestResult instance = new RequestResult();
            instance.setResult(true);
            return instance;
        }
    
        public static RequestResult failure() {
            RequestResult instance = new RequestResult();
            instance.setResult(false);
            return instance;
        }
    
        public RequestResult data(Object data) {
            this.data = data;
            return this;
        }
    
        public RequestResult errmsg(String errmsg) {
            this.errmsg = errmsg;
            return this;
        }
    
    }
  • 相关阅读:
    Quartz入门例子简介 从入门到菜鸟(一)
    初识Quartz之第一个Quartz实例
    @DisallowConcurrentExecution 注解的作用 【定时器执行完当前任务才开启下一个线程的方式】
    no identities are available for signing
    Unity3D研究院之在把代码混淆过的游戏返混淆回来
    安沃广告问题
    IOS 接ShareSDK问题
    网页中插入Flvplayer视频播放器代码
    unity Android 打包后读取 xml 文件
    unity3d 下操作excel 与打印
  • 原文地址:https://www.cnblogs.com/deolin/p/7993428.html
Copyright © 2011-2022 走看看