8.乱码问题
8.1 ServletAPI方式
- 乱码出现在HTTP请求方式是POST;Get不乱码,但是地址栏会暴露传递的数据,
- 回顾之前servlet Web解决乱码问题时:要么在servlet方法里面加乱码设置
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
String username = req.getParameter("username");
}
}
- 要么加自定义过滤器之后在web.xml中注册,这两种方式都可以解决
public class SysFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
chain.doFilter(request,response);
}
@Override
public void destroy() {
}
}
web.xml中如果还有其他过滤器。编码过滤器filter一定要放在web.xml的第一个,不然还是会乱码
拦截路径要用/*不然不会拦截jsp,了解下tomcat的默认JspServlet配置映射路径
<filter>
<filter-name>SysFilter</filter-name>
<filter-class>com.zk.myfilter.SysFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SysFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
8.2 springmvc乱码处理
- springmvc这块乱码的原因是controller的方法参数已经经接收流并编码了后面再编码就没用了,所以只能外加编码过滤器
- 可以用自定义过滤器可以处理
自定义过滤器思想:对post方式提交的数据直接使用utf-8编码;对get方式提交的数据是将字符以ISO-8859-1解码为二进制流,再以UTF-8编码为字符
- 可以用springmvc自带的编码过滤器,直接在web.xml中注册即可
<filter>
<filter-name>encodingFilter</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>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
这个过滤器在某些情况下对get支持不好
- 乱码情况也要注意下tomcat配置文件中编码设置!
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
connectionTimeout="20000"
redirectPort="8443" URIEncoding="utf-8" executor="tomcatThreadPool"/>
8.3 Spring Json乱码
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/gj01")
@ResponseBody
public String getjson01(){
User user = new User("张三", 18, LocalDate.now());
return user.toString();
}
}
-
http://localhost:8080/user/gj01地址栏直接访问出现乱码
-
返回string,则使用 StringHttpMessageConverter,而这个convert使用的是字符集是iso-8859-1,而且是final的。所以在当返回json中有中文时会出现乱码。
@ResponseBody作用是将标注该注解的处理方法的返回结果直接写入 HTTP Response Body**(Response 对象的 body 数据区)中。一般情况下,@ResponseBody 都会在异步获取数据时使用**,被其标注的处理方法返回的数据都将输出到响应流中,客户端获取并显示数据。
-
StringHttpMessageConverter在写入输出消息时,它还增加了对Content-Type和Content-Length的支持。
-
解决方式1:
- produces 属性用于指定返回的内容类型,返回的内容类型必须是 request 请求头(Accept)中所包含的类型。还可以指定返回值的编码
解决方式1@RequestMapping(value = "toUser",produces = "application/json;charset=UTF-8")。
-
解决方式2:统一解决json乱码的方式不用每个方法上添加produces = "application/json;charset=utf-8"属性
-
如果用Jackson 开源工具进行json格式处理时乱码解决:
在springmvc-servlet.xml配置文件中添加一段消息转换配置StringHttpMessageConverter
<!--json乱码问题统一配置-->
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<!--乱码问题解决-->
<constructor-arg name="defaultCharset" value="UTF-8"/>
</bean>
<!--具体那种消息转换配置去实现-->
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
- 如果用fastjson进行json格式处理时乱码解决:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--开启注解-->
<context:component-scan base-package="com.zk"/>
<!--让spring-mvc不处理静态资源.css .js-->
<mvc:default-servlet-handler/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- annotation-driven用于简化开发的配置,注解DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter -->
<!-- 使用resources过滤掉不需要dispatcherservlet的资源(即静态资源,例如css、js、html、images)。
在使用resources时必须使用annotation-driven,否则resources元素会阻止任意控制器被调用 -->
<!-- 允许js目录下的所有文件可见 -->
<!--<mvc:resources mapping="/**" location="/"/>-->
<!--json乱码问题统一配置-->
<mvc:annotation-driven conversion-service="formattingConversionService">
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<!--乱码问题解决-->
<constructor-arg name="defaultCharset" value="UTF-8"/>
</bean>
<bean class="com.alibaba.fastjson2.support.spring.http.converter.FastJsonHttpMessageConverter">
</bean>
<!--<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
</bean>-->
</mvc:message-converters>
</mvc:annotation-driven>
<!--注册MyFormatter -->
<bean class="org.springframework.format.support.FormattingConversionServiceFactoryBean" id="formattingConversionService">
<property name="formatters">
<list>
<bean class="com.zk.formatter.MyFormatter"/>
</list>
</property>
</bean>
<!--<bean id="fastJsonpResponseBodyAdvice"
class="com.alibaba.fastjson2.support.spring.FastJsonpResponseBodyAdvice">
<constructor-arg>
<list>
<value>callback</value>
<value>jsonp</value>
</list>
</constructor-arg>
</bean>-->
</beans>
-
举例:利用ajax将json数据传到后台接收,后台在将json数据回显到页面展示
-
实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
String username;
String pwd;
Date birthday;
}
- controller
@Controller
@RequestMapping("/stu")
public class StudentController {
@RequestMapping("/getInfo")
@ResponseBody
public Student getInfo(@RequestBody Student student){
// 打印接收的 JSON数据
System.out.println("接收的student数据:"+student.toString());
return student;
}
}
方法中的 @RequestBody 注解用于将前端请求体中的 JSON 格式数据绑定到形参 user 上,@ResponseBody 注解用于直接返回 Student对象(当返回 POJO 对象时默认转换为 JSON 格式数据进行响应)。
- 参数日期格式化类
@Component
public class MyFormatter implements Formatter<Date> {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
public Date parse(String text, Locale locale) throws ParseException {
return dateFormat.parse(text);
}
@Override
public String print(Date object, Locale locale) {
return dateFormat.format(object);
}
}
- springmvc-servlet.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--开启注解-->
<context:component-scan base-package="com.zk"/>
<!--让spring-mvc不处理静态资源.css .js-->
<mvc:default-servlet-handler/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- annotation-driven用于简化开发的配置,注解DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter -->
<!-- 使用resources过滤掉不需要dispatcherservlet的资源(即静态资源,例如css、js、html、images)。
在使用resources时必须使用annotation-driven,否则resources元素会阻止任意控制器被调用 -->
<!-- 允许js目录下的所有文件可见 -->
<!--<mvc:resources mapping="/**" location="/"/>-->
<!--json乱码问题统一配置-->
<mvc:annotation-driven conversion-service="formattingConversionService">
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<!--乱码问题解决-->
<constructor-arg name="defaultCharset" value="UTF-8"/>
</bean>
<bean class="com.alibaba.fastjson2.support.spring.http.converter.FastJsonHttpMessageConverter">
</bean>
<!--<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
</bean>-->
</mvc:message-converters>
</mvc:annotation-driven>
<!--注册MyFormatter -->
<bean class="org.springframework.format.support.FormattingConversionServiceFactoryBean" id="formattingConversionService">
<property name="formatters">
<list>
<bean class="com.zk.formatter.MyFormatter"/>
</list>
</property>
</bean>
</beans>
- index.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
<script src="http://cdn.static.runoob.com/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- 新 Bootstrap 核心 CSS 文件 -->
<link href="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<!-- 可选的Bootstrap主题文件(一般不使用) -->
<script src="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap-theme.min.css"></script>
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<html>
<head>
<title>testJSON发送和回显</title>
<script type="text/javascript">
$(function () {
$("#add").click(function () {
let username = $("#username").val();
let pwd = $("#pwd").val();
let birthday = $("#birthday").val();
$.ajax({
url:"${pageContext.request.contextPath}/stu/getInfo",
//请求类型
type:"post",
//data表示发送的数据
data : JSON.stringify({
username : username,
pwd : pwd,
birthday:birthday
}), //定义发送请求的数据格式为JSON字符串
contentType : "application/json;charset=utf-8",
//定义回调响应的数据格式为JSON字符串,该属性可以省略
dataType : "json",
//成功响应的结果
success:function (data) {
let html = "";
if (data != null) {
html+= "<tr><td class='info'>"+data.username+"</td><td class='info'>"+data.pwd+"</td><td class='info'>"+data.birthday+"</td></tr>"
}
alert(html);
$("#content").html(html);
}
})
})
})
</script>
</head>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<small>学生账号信息JSON发送和回显</small>
</div>
</div>
</div>
<form method="post" action="#">
<div class="form-group">
<label for="username">学生账号</label>
<input type="text" class="form-control" id="username" name="username" placeholder="学生姓名" required>
</div>
<div class="form-group">
<label for="pwd">密码</label>
<input type="text" class="form-control" id="pwd" name="pwd" placeholder="密码" required>
</div>
<div class="form-group">
<label for="birthday">登录日期</label>
<input type="datetime-local" name="birthday" id="birthday" class="form-control" placeholder="登录日期">
</div>
<button type="button" class="btn btn-primary btn-block" id="add">添加</button>
</form>
</div>
<div>
<table class="table">
<thead>
<tr>
<th>学生账号</th>
<th>密码</th>
<th>登录日期</th>
</tr>
</thead>
<tbody id="content">
</tbody>
</table>
</div>
</body>
</html>