• 比较合适的前后端交互方式


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

    使用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;
        }
    
    }
  • 相关阅读:
    呈现系统-组件间的通信方式(7)
    web项目中图标的前端处理方案
    ADO--数据访问技术
    canvas--绘制路径
    canvas--改变颜色
    canvas-在画布中画两个方块(一个空心一个实体)
    canvas--画布《第一步》
    拼图游戏【简单】
    判断字符串是否为空--string.Empty、string=""、s.length==0
    判断Char是否为数字
  • 原文地址:https://www.cnblogs.com/deolin/p/7993428.html
Copyright © 2020-2023  润新知