热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

这篇博客是对过去博客的整理与总结,现在,以下的博客都可以认为过时了。使用Ajax向SpringMVC传递Json数据存在日期类型的JSON数据,进行SpringMVC参数绑定时存在

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

使用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.coregroupId>
            <artifactId>jackson-databindartifactId>
            <version>2.9.0version>
        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.hibernategroupId>
            <artifactId>hibernate-validatorartifactId>
            <version>5.4.1.Finalversion>
        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;
    }

}

 


推荐阅读
  • 在使用 Qt 进行 YUV420 图像渲染时,由于 Qt 本身不支持直接绘制 YUV 数据,因此需要借助 QOpenGLWidget 和 OpenGL 技术来实现。通过继承 QOpenGLWidget 类并重写其绘图方法,可以利用 GPU 的高效渲染能力,实现高质量的 YUV420 图像显示。此外,这种方法还能显著提高图像处理的性能和流畅性。 ... [详细]
  • 深入探索HTTP协议的学习与实践
    在初次访问某个网站时,由于本地没有缓存,服务器会返回一个200状态码的响应,并在响应头中设置Etag和Last-Modified等缓存控制字段。这些字段用于后续请求时验证资源是否已更新,从而提高页面加载速度和减少带宽消耗。本文将深入探讨HTTP缓存机制及其在实际应用中的优化策略,帮助读者更好地理解和运用HTTP协议。 ... [详细]
  • 在编译 PHP7 的 PDO MySQL 扩展时,可能会遇到 `[mysql_driver.lo]` 错误 1。该问题通常出现在 `pdo_mysql_fetch_error_func` 函数中。本文详细介绍了导致这一错误的常见原因,包括依赖库版本不匹配、编译选项设置不当等,并提供了具体的解决步骤和调试方法,帮助开发者快速定位并解决问题。 ... [详细]
  • 本文介绍了如何利用Struts1框架构建一个简易的四则运算计算器。通过采用DispatchAction来处理不同类型的计算请求,并使用动态Form来优化开发流程,确保代码的简洁性和可维护性。同时,系统提供了用户友好的错误提示,以增强用户体验。 ... [详细]
  • 深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案
    深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案 ... [详细]
  • 本指南介绍了如何在ASP.NET Web应用程序中利用C#和JavaScript实现基于指纹识别的登录系统。通过集成指纹识别技术,用户无需输入传统的登录ID即可完成身份验证,从而提升用户体验和安全性。我们将详细探讨如何配置和部署这一功能,确保系统的稳定性和可靠性。 ... [详细]
  • 优化后的标题:深入探讨网关安全:将微服务升级为OAuth2资源服务器的最佳实践
    本文深入探讨了如何将微服务升级为OAuth2资源服务器,以订单服务为例,详细介绍了在POM文件中添加 `spring-cloud-starter-oauth2` 依赖,并配置Spring Security以实现对微服务的保护。通过这一过程,不仅增强了系统的安全性,还提高了资源访问的可控性和灵活性。文章还讨论了最佳实践,包括如何配置OAuth2客户端和资源服务器,以及如何处理常见的安全问题和错误。 ... [详细]
  • 在本文中,我们将详细介绍如何构建一个用于自动回复消息的XML类。当微信服务器接收到用户消息时,该类将生成相应的自动回复消息。以下是具体的代码实现:```phpclass We_Xml { // 代码内容}```通过这个类,开发者可以轻松地处理各种消息类型,并实现高效的自动回复功能。我们将深入探讨类的各个方法和属性,帮助读者更好地理解和应用这一技术。 ... [详细]
  • C++ 异步编程中获取线程执行结果的方法与技巧及其在前端开发中的应用探讨
    本文探讨了C++异步编程中获取线程执行结果的方法与技巧,并深入分析了这些技术在前端开发中的应用。通过对比不同的异步编程模型,本文详细介绍了如何高效地处理多线程任务,确保程序的稳定性和性能。同时,文章还结合实际案例,展示了这些方法在前端异步编程中的具体实现和优化策略。 ... [详细]
  • 在PHP中,高效地分割字符串是一项常见的需求。本文探讨了多种技术,用于在特定字符(如“或”)后进行字符串分割。通过使用正则表达式和内置函数,可以实现更加灵活和高效的字符串处理。例如,可以使用 `preg_split` 函数来实现这一目标,该函数允许指定复杂的分隔符模式,从而提高代码的可读性和性能。此外,文章还介绍了如何优化分割操作以减少内存消耗和提高执行速度。 ... [详细]
  • 本文探讨了如何利用Java代码获取当前本地操作系统中正在运行的进程列表及其详细信息。通过引入必要的包和类,开发者可以轻松地实现这一功能,为系统监控和管理提供有力支持。示例代码展示了具体实现方法,适用于需要了解系统进程状态的开发人员。 ... [详细]
  • 使用Maven JAR插件将单个或多个文件及其依赖项合并为一个可引用的JAR包
    本文介绍了如何利用Maven中的maven-assembly-plugin插件将单个或多个Java文件及其依赖项打包成一个可引用的JAR文件。首先,需要创建一个新的Maven项目,并将待打包的Java文件复制到该项目中。通过配置maven-assembly-plugin,可以实现将所有文件及其依赖项合并为一个独立的JAR包,方便在其他项目中引用和使用。此外,该方法还支持自定义装配描述符,以满足不同场景下的需求。 ... [详细]
  • 本文深入探讨了Java多线程环境下的同步机制及其应用,重点介绍了`synchronized`关键字的使用方法和原理。`synchronized`关键字主要用于确保多个线程在访问共享资源时的互斥性和原子性。通过具体示例,如在一个类中使用`synchronized`修饰方法,展示了如何实现线程安全的代码块。此外,文章还讨论了`ReentrantLock`等其他同步工具的优缺点,并提供了实际应用场景中的最佳实践。 ... [详细]
  • Spring框架中枚举参数的正确使用方法与技巧
    本文详细阐述了在Spring Boot框架中正确使用枚举参数的方法与技巧,旨在帮助开发者更高效地掌握和应用枚举类型的数据传递,适合对Spring Boot感兴趣的读者深入学习。 ... [详细]
  • 2018 HDU 多校联合第五场 G题:Glad You Game(线段树优化解法)
    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6356在《Glad You Game》中,Steve 面临一个复杂的区间操作问题。该题可以通过线段树进行高效优化。具体来说,线段树能够快速处理区间更新和查询操作,从而大大提高了算法的效率。本文详细介绍了线段树的构建和维护方法,并给出了具体的代码实现,帮助读者更好地理解和应用这一数据结构。 ... [详细]
author-avatar
mobiledu2502853587
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有