SpringMVC系列十: 中文乱码处理与JSON处理

文章目录

上一讲, 我们学习的是 SpringMVC系列九: 数据格式化与验证及国际化

现在打开springmvc项目

中文乱码处理

自定义中文乱码过滤器

●说明

当表单提交数据为中文时, 会出现乱码,我们来解决一下( 提示: 先恢复name 属性的绑定)

1.创建过滤器 JavaWeb过滤器

com.zzw.web.filter包下新建MyCharacterFilter

java 复制代码
/**
 * @author 赵志伟
 * @version 1.0
 * 编写过滤器, 处理中文乱码
 */
@SuppressWarnings({"all"})
public class MyCharacterFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //这里加入对编码的处理
        servletRequest.setCharacterEncoding("utf-8");
        //放行请求, 这个规则和前面见过的java web过滤器一样
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }
}

2.在web.xml中配置.

注意: 不要乱写, 过滤器一般写在web.xml的最上面, 多个过滤器之间会形成过滤器链, 要注意顺序.
JavaWeb系列十五: JavaWeb三大组件之过滤器Filter

xml 复制代码
<!--配置处理中文乱码的过滤器
拦截所有请求, 处理编码.把过滤器配置到web.xml前面-->
<filter>
    <filter-name>MyCharacterFilter</filter-name>
    <filter-class>com.zzw.web.filter.MyCharacterFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>MyCharacterFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

3.完成测试.

Spring提供的过滤器处理中文

1.修改web.xml , 换成Spring提供的过滤器, 处理中文乱码.

xml 复制代码
<!--配置Spring提供的过滤器, 解决中文乱码问题-->
<filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>utf-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

2.完成测试

处理json和HttpMessageConverter

处理JSON-@ResponseBody

●说明

项目开发中, 我们往往需要服务器返回的数据格式是按照json 来返回的, 我们看一下SpringMVC是如何处理的,

●应用案例

1.引入处理json 需要的jar 包, 注意spring5.x 需要使用jackson-2.9.x.jar 的包. springmvc处理json需要jar

2.在web路径下创建json.jsp

html 复制代码
<head>
    <title>json提交</title>
    <%--引入jquery--%>

    <%--编写jquery代码和请求--%>
</head>
<body>
<h1>请求一个json数据</h1>
<a href="?" id="getJson">点击获取json数据</a>
</body>

3.在com.zzw.web.json.entity包 下新建 Dog.java

java 复制代码
public class Dog {
    private String name;
    private String address;

	//全参构造器, 无参构造器, setter,getter,toString方法
}

4.新建src/com/zzw/web/json/JsonHandler.java

java 复制代码
@Controller
public class JsonHandler {

    /**
     * 解读
     * 1.目标方法 @ResponseBody, 表示返回的数据是json格式
     * 2.springmvc底层根据目标方法@ResponseBody, 返回指定格式,
     * 3.底层原理我们在前面自定义@ResponseBody讲过, 这里原生的springmvc使用转换器
     * 4.HttpMessageConverter [一会我们debug]
     * @return
     */
    @RequestMapping(value = "/json/dog")
    @ResponseBody
    public Dog getJson() {

        //返回对象
        //springmvc会根据你的设置, 转成json格式数据返回
        Dog dog = new Dog();
        dog.setName("大黄");
        dog.setAddress("蜡笔小新");

        return dog;
    }
}

5.回填json.jsp的action
JavaWeb系列十九: jQuery的DOM操作 上

html 复制代码
<html>
<head>
    <title>json提交</title>
    <%--引入jquery--%>
    <script type="text/javascript" src="script/jquery-3.6.0.min.js"></script>

    <%--编写jquery代码和请求--%>
    <script type="text/javascript">
        $(function () {
            //给id="getJson"绑定一个点击事件
            $("#getJson").click(function () {
                console.log("ok");//测试一下

                let url = this.href;//this是dom对象
                let args = {"time": new Date};//这老师要发送数据, 为了防止页面缓存
                $.post(
                    url,
                    args,
                    function(data) {//data就是后台返回的数据, 是json格式
                        console.log("data=", data);
                        console.log("name=", data.name);
                        console.log("address=", data.address);

                    },
                    "json"
                )
                return false;//这里我们返回false, 就不使用href默认机制
            });
        })
    </script>
</head>
<body>
<h1>请求一个json数据</h1>
<%--处理
1.当用户点击超链接时, 我们发出一个ajax请求
2.接收到请求后, 我们查看这个数据
3.使用我们前面见过的jquery发出ajax请求的知识
--%>
<a href="<%=request.getContextPath()%>/json/dog" id="getJson">点击获取json数据</a>
</body>
</html>

6.完成测试(浏览器)

7.用postman完成测试

处理JSON-@RequestBody

●应用案例

-前面我们是通过表单, 或者 url 请求携带 参数=参数值 把数据提交给目标方法

1)给大家举例客户端发送 json字符串数据

2)使用SpringMVC@RequestBody 将客户端提交的json 数据, 封装成JavaBean 对象

3)再把这个javabeanjson 的对象形式返回

4)完成效果示意图 [空]

1.修改json.jsp , 增加发送json数据代码

html 复制代码
<html>
<head>
    <title>json提交</title>
    <%--引入jquery--%>
    <script type="text/javascript" src="script/jquery-3.6.0.min.js"></script>

    <%--编写jquery代码和请求--%>
    <script type="text/javascript">
        $(function () {
            //....
            
            //绑定按钮点击事件, 提交json数据
            //springmvc 可以在后台将json转成对象
            $("button[name='butt1']").click(function () {
                //todo 具体的业务代码以后再写
            })
        })
    </script>
</head>
<body>
<%--.....--%>
<h1>发出一个json数据</h1>
u:<input id="username" type="text"/><br/>
a:<input id="age" type="text"/><br/>
<button name="butt1">添加用户</button>
</body>
</html>

2.在com.zzw.web.json.entity包 下新建 User.java

java 复制代码
public class User {
    private String userName;
    private Integer age;

	//全参构造器, 无参构造器, setter,getter,toString方法
}

3.修改JsonHandler.java , 增加处理json 代码. 注意: 老韩用的是 @PostMapping , 等价: @RequestMapping(method = RequestMethod.POST)

java 复制代码
@Controller
public class JsonHandler {
	//...
	
    @RequestMapping(value = "/save2")
    @ResponseBody
    public User save2(User user) {
        //将前台传过来的数据, 以json的格式返回给浏览器
        System.out.println("user=" + user);
        return user;
    }
}

4.回填json.jsp

js 复制代码
//绑定按钮点击事件, 提交json数据
//springmvc 可以在后台将json转成对象
$("button[name='butt1']").click(function () {
    //目标:将userName 和 age 封装成json字符串
    let url = "/springmvc/save2";
    let userName = $("#userName").val();
    let age = $("#age").val();
    //将json对象转成json字符串
    let args = JSON.stringify({"userName": userName, "age": age});
    $.ajax({
        url: url,
        type: "POST",
        data: args,
        success(data) {
            console.log("返回的data=", data);
        },
        //下面这个contentType参数, 是指定发送数据时的编码和格式
        //只有$.ajax才有, $.post没有
        contentType: "application/json;charset=utf-8"
    })
})

5.测试. 数据为空

后台. 数据为空

6.加上 @RequestBody注解

java 复制代码
/**
 * 老师解读
 * 1. @RequestBody User user 在形参指定了 @RequestBody
 * 2. springmvc就会将提交的json字符串数据填充给指定Javabean
 * @param user
 * @return
 */
@RequestMapping(value = "/save2")
@ResponseBody
public User save2(@RequestBody User user) {
    //将前台传过来的数据, 以json的格式返回给浏览器
    System.out.println("user=" + user);
    return user;
}

7.测试

后台

8.postman测试

postman提交json格式的数据


处理JSON-注意事项和细节

1.目标方法正常返回JSON需要的数据, 可以是一个对象, 也可以是一个集合

2.前面我们讲的是返回一个Dog 对象->转成Json数据格式返回

●应用实例
JsonHandler.java添加如下方法

java 复制代码
//编写方法, 以json格式返回多个Dog
@RequestMapping(value = "/json/dogs")
@ResponseBody
public List<Dog> getJsons() {

    List<Dog> dogs = new ArrayList<>();
    dogs.add(new Dog("大黄", "蜡笔小新之家"));
    dogs.add(new Dog("大黄2", "蜡笔小新之家2"));
    dogs.add(new Dog("大黄3", "蜡笔小新之家3"));

    return dogs;
}

postman测试

返回结果

3.@ResponseBody 可以直接写在controller上, 这样对所有方法都生效

●应用实例

完成测试
后台数据

postman测试

4.@ResponseBody + @Controller 可以直接写成 @RestController, 我们看一下源码

测试

HttpMessageConverter<T>

●基本说明
SpringMVC 处理 JSON- 底层实现是依靠 HttpMessageConverter<T> 来进行转换的

●工作机制简图

●处理JSON -底层实现(HttpMessageConverter<T> )

1.使用 HttpMessageConverter<T> 将请求信息转化并绑定到处理方法的入参中, 或将响应结果转为对应类型的相应信息, Spring 提供了两种途径:

√ 使用 @RequestBody / @ResponseBody 对目标方法进行标注

√ 使用 @HttpEntity<T> / ResponseEntity<T> 作为目标方法的入参或返回值

2.当控制器处理方法使用到 @RequestBody / @ResponseBodyHttpEntity<T> / ResponseEntity<T> 时, Spring 首先根据请求头或响应头的 Accept 属性选择匹配的 HttpMessageConverter , 进而根据参数类型或泛型类型的过滤得到匹配的 HttpMessageConverter , 若找不到可用的 HttpMessageConverter 将报错

Debug 源码-梳理一下

一. 将请求信息转化并绑定到处理方法的入参中







二. 将响应结果转为对应类型的相应信息


文件下载-ResponseEntity<T>

●说明

SpringMVC 中, 通过返回 ResponseEntity<T> 的类型, 可以实现文件下载的功能

●案例演示

准备工作: 在web路径/img下准备一个要下载的文件, 比如图片: 1.jpg

1.修改json.jsp

html 复制代码
<h1>下载文件的测试</h1>
<a href="?">点击下载文件</a>

2.修改JsonHandler.java, 增加方法

java 复制代码
//响应银狐下载文件的请求
@RequestMapping(value = "/downFile")
public ResponseEntity<byte[]>  downFile(HttpSession session) throws Exception {

    //1.先获取到下载文件的inputStream
    InputStream inputStream = session.getServletContext().getResourceAsStream("/img/1.jpg");

    //2.开辟一个存放文件的字节数组, 这里我们使用byte[] 是可以支持二进制数据(图片, 视频, 音频, doc文档)
    byte[] bytes = new byte[inputStream.available()];

    //3.将下载文件的数据, 读入到byte[]
    inputStream.read(bytes);

    /*
    public ResponseEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers, HttpStatus status) {
        this(body, headers, (Object) status);
    }
     */
    //4.创建返回的HttpStatus
    HttpStatus status = HttpStatus.OK;

    //5.创建 headers
    HttpHeaders headers = new HttpHeaders();
    //指定返回的数据, 客户端应当以附件形式处理
    headers.add("Content-Disposition", "attachment;filename=1.jpg");

    //构建一个ResponseEntity 对象
    ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers, status);

	//如果出现找不到文件, 解决方法 rebuild project 
    return responseEntity;
}

文件下载响应头的设置

content-type 指示响应内容的格式

content-disposition 指示如何处理响应内容

一般有两种方式:

inline: 直接在页面显示

attchment: 以附件形式下载

3.回填json.jsp

html 复制代码
<a href="<%=request.getContextPath()%>/downFile">点击下载文件</a>

4.完成测试

页面方式

postman测试, 返回二进制数据, 因为postman没有对数据进行解析

作业布置

1.把我们前面学过的数据格式化, 验证以及国际化, Json处理, 文件下载, 相关代码和案例, 自己写一遍. 一定要写一遍, 否则没有印象, 理解不会渗入

2.把Debug 过的HttpMessageConverter 源码, 自己再走一下, 加深理解(不用每条语句, 都debug, 找流程...)

3.DataBinder工作机制-将示意图画出

4,Debug 一下validate 得到验证errors信息, 加深理解(不用每一条语句都debug, 找流程)

Q

下一讲, 我们学习 SpringMVC系列九: 数据格式化与验证及国际化

相关推荐
椰椰椰耶9 分钟前
【多线程-从零开始-伍】volatile关键字和内存可见性问题
java·多线程
chenthe120 分钟前
Java过滤HTML标签,即提取HTML中的纯文本,不使用正则表达式【jsoup方式,超级简单】,附富文本方式
java·正则表达式·html
Mueisya21 分钟前
C++初学(11)
开发语言·c++
Mr.Demo.22 分钟前
[Spring] SpringBoot统一功能处理与图书管理系统
java·后端·spring
华农第一蒟蒻28 分钟前
有效的括号(简单)
java·开发语言·算法
小羊在奋斗32 分钟前
【C++】string类
开发语言·c++
林园85733 分钟前
Java程序员接单分享
java·开发语言
罗曼蒂克在消亡35 分钟前
HashTable源码
java·jdk
乐乐吃不饱1 小时前
java之WIFI模块实现文件传输(开源)
java·开发语言·开源
bryant_meng1 小时前
【python】OpenCV—Image Super Resolution
开发语言·python·opencv