欢迎使用CSDN-markdown编辑器

来源:互联网 发布:唯品会淘宝天猫哪个好 编辑:程序博客网 时间:2024/06/18 17:23

SpringMVC项目中中文字符乱码问题及解决办法

一个不容易查询的错误

<!-- 配置字符集 -->    <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>        <init-param>            <param-name>forceEncoding</param-name>            <param-value>true</param-value>        </init-param>    </filter>    <filter-mapping>        <filter-name>encodingFilter</filter-name>        <url-pattern>/*</url-pattern>    </filter-mapping>

错误写法,这里写图片描述

奇怪的问题。

这里需要注意的是,最好把这段代码放在web.xml中开头的位置,因为拦截有顺序,如果放在后面的话容易拦截不到。

页面写法

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";System.out.print(basePath);%><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>注册</title></head><body>    <form action="<%=basePath%>user/register.do" method="post">        用户名:<input type="text" name="username" /><br /> 密码:<input            type="password" name="password"><br /> <input type="submit"            value="提交">    </form></body></html>

只要 保持 这两处配置,中文就没有乱码了,

其他地方不需要配置。

网上其他的处理,可参考:

1.客户的发送方法稍微改一下,这个方式是最好的:connection.setRequestProperty("content-type", "text/html;charset=GBk");

2

 @RequestMapping(value="/add", method=RequestMethod.POST, produces="text/html;charset=UTF-8")  

3

spring配置文件中 <mvc:annotation-driven /> 改下
  <mvc:annotation-driven >    <mvc:message-converters register-defaults="true">    <!-- 解决@ResponseBody中文乱码 -->    <bean class="org.springframework.http.converter.StringHttpMessageConverter">      <property name="supportedMediaTypes" value = "text/plain;charset=UTF-8" />    </bean>   </mvc:message-converters>  </mvc:annotation-driven>

写成/和/*的区别

<url-pattern>/</url-pattern>

会匹配到/springmvc这样的路径型url,不会匹配到模式为*.jsp这样的后缀型url。

<url-pattern>/*</url-pattern>

会匹配所有的url:路径型的和后缀型的url(包括/springmvc,.jsp,.js和*.html等)。
下面是关于这个问题在stack overflow上的解释:
原文链接:http://stackoverflow.com/questions/4140448/difference-between-and-in-servlet-mapping-url-pattern
简单的翻译如下:

<url-pattern>/*</url-pattern>

这种形式将会覆盖所有其它的servlet。不管你发出了什么样的请求,最终都会在这个servlet中结束。因此,对于servlet来说,这是一个很糟糕的URL模式。通常来讲,你只会想要在一个Filter中使用这种模式。它可以通过调用doFilter()方法来使请求继续。

<url-pattern>/</url-pattern>

这种形式不会覆盖任何其它的servlet。它仅仅替换了servlet容器中内建的默认servlet。这种形式通常只用来请求静态资源(CSS/JS/image等)和展示目录的列表。servlet容器内建的默认servlet同样可以处理HTTP cache请求、媒体(声音/视频)流以及文件的下载。通常来说,你不会想要覆盖这个默认的servlet,否则,你将不得不自己处理一些琐碎的任务。因此,对于sevlet来说,这同样是一个糟糕的URL模式。说到为什么JSP页面的请求并不会命中这个servlet,那是因为servlet容器内建的JSP servlet将会被调用,而这个容器内建的JSP servlet已经默认地映射在了*.jsp上。

<url-pattern></url-pattern> 

这种空串的形式。当上下文的根被请求的时候,它将被调用。这与的方式是不同的,因为这种形式在当任何子目录被请求的时候不会被调用。当你期望一个“首页servlet”的时候,这种URL模式就是适合你的。

  此处需要特别强调的是
  

 <url-pattern>/</url-pattern>

  
  使用的是/,而不是/,如果使用/,那么请求时可以通过DispatcherServlet转发到相应的Action或者Controller中的,但是返回的内容,如返回的jsp还会再次被拦截,这样导致404错误,即访问不到jsp。所以如果以后发现总是有404错误的时候,别忘了check一下
  

 <url-pattern>/</url-pattern>

  
  的配置是否是/*.
  二、其实Spring 的Servlet拦截器匹配规则(即 … )都可以自己定义,例:当映射为@RequestMapping(“/user/add”)时
  1、拦截.do、.htm, 例如:/user/add.do
  这是最传统的方式,最简单也最实用。不会导致静态文件(jpg,js,css)被拦截。
  2、拦截/,例如:/user/add
  可以实现现在很流行的REST风格。很多互联网类型的应用很喜欢这种风格的URL。
  弊端:会导致静态文件(jpg,js,css)被拦截后不能正常显示。想实现REST风格,事情就是麻烦一些。后面有解决办法还算简单。
  3、拦截/*,这是一个错误的方式,请求可以走到Action中,但转到jsp时再次被拦截,不能访问到jsp。
  三、如何访问到静态的文件,如jpg,js,css?
  如果你的DispatcherServlet拦截”*.do”这样的有后缀的URL,就不存在访问不到静态资源的问题。
  如果你的DispatcherServlet拦截”/”,为了实现REST风格,拦截了所有的请求,那么同时对.js,.jpg等静态文件的访问也就被拦截了。
  我们要解决这个问题。
  目的:可以正常访问静态文件,不可以找不到静态文件报404。
  方案一:激活Tomcat的defaultServlet来处理静态文件

  <servlet-mapping>  <servlet-name>default</servlet-name>  <url-pattern>*.jpg</url-pattern>  </servlet-mapping>  <servlet-mapping>  <servlet-name>default</servlet-name>  <url-pattern>*.js</url-pattern>  </servlet-mapping>  <servlet-mapping>  <servlet-name>default</servlet-name>  <url-pattern>*.css</url-pattern>  </servlet-mapping>

  特点:1. 要配置多个,每种文件配置一个。
  2. 要写在DispatcherServlet的前面, 让 defaultServlet先拦截请求,这样请求就不会进入Spring了。
  3. 高性能。
  备注:
  Tomcat, Jetty, JBoss, and GlassFish 自带的默认Servlet的名字 – “default”
  Google App Engine 自带的 默认Servlet的名字 – “_ah_default”
  Resin 自带的 默认Servlet的名字 – “resin-file”
  WebLogic 自带的 默认Servlet的名字 – “FileServlet”
  WebSphere 自带的 默认Servlet的名字 – “SimpleFileServlet”
  方案二: 在spring3.0.4以后版本提供了mvc:resources , 使用方法:
  

<!-- 对静态资源文件的访问 -->  <mvc:resources mapping="/images/**" location="/images/" />

  
  images/**映射到 ResourceHttpRequestHandler进行处理,location指定静态资源的位置.可以是web application根目录下、jar包里面,这样可以把静态资源压缩到jar包中。cache-period 可以使得静态资源进行web cache
  
  如果出现下面的错误,可能是没有配置的原因。
  报错WARNING: No mapping found for HTTP request with URI [/mvc/user/findUser/lisi/770] in DispatcherServlet with name ‘springMVC’
  
  使用元素,把mapping的URI注册到SimpleUrlHandlerMapping的urlMap中,
  key为mapping的URI pattern值,而value为ResourceHttpRequestHandler,
  这样就巧妙的把对静态资源的访问由HandlerMapping转到ResourceHttpRequestHandler处理并返回,所以就支持classpath目录,jar包内静态资源的访问.
  另外需要注意的一点是,不要对SimpleUrlHandlerMapping设置defaultHandler.因为对static uri的defaultHandler就是ResourceHttpRequestHandler,
  否则无法处理static resources request.
  方案三 ,使用
  

 <mvc:default-servlet-handler/>  <mvc:default-servlet-handler/>

  会把”/**” url,注册到SimpleUrlHandlerMapping的urlMap中,把对静态资源的访问由HandlerMapping转到 org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler 处理并返回.
  DefaultServletHttpRequestHandler使用就是各个Servlet容器自己的默认Servlet.
  补充说明:多个HandlerMapping的执行顺序问题:
  DefaultAnnotationHandlerMapping的order属性值是:0
  < mvc:resources/ > 自动注册的 SimpleUrlHandlerMapping 的order属性值是: 2147483646
  

 <mvc:default-servlet-handler/>   

   自动注册 的SimpleUrlHandlerMapping 的order属性值是: 2147483647
  spring会先执行order值比较小的。当访问一个a.jpg图片文件时,先通过 DefaultAnnotationHandlerMapping 来找处理器,一定是找不到的,因为我们没有叫a.jpg的Action。然后再按order值升序找,由于最后一个 SimpleUrlHandlerMapping 是匹配 “/**”的,所以一定会匹配上,就可以响应图片。 访问一个图片,还要走层层匹配。不知性能如何?
  最后再说明一下,方案二、方案三 在访问静态资源时,如果有匹配的(近似)总拦截器,就会走拦截器。如果你在拦截中实现权限检查,要注意过滤这些对静态文件的请求。
  如何你的DispatcherServlet拦截 *.do这样的URL后缀,就不存上述问题了。还是有后缀方便。