关于JSP/Servlet字符编码

首先,来说一下HTML和JSP的区别:

HTML属于前台,纯展示页面,请求HTML时,容器(如Tomcat)会读取HTML文件的内容,通过socket遵循HTTP协议发送到浏览器

JSP属于后台,请求JSP时,容器会首先读取JSP文件的内容,然后根据JSP文件内容生成对应的java类文件(这个类是继承自HttpJspBase的,而HttpJspBase是继承自HttpServlet的,所以JSP生成了一个对应的Servlet),接着编译出class文件(在Tomcat中,生成java和class文件是由 org.apache.jasper.compiler.Compiler 完成的),然后由Tomcat类加载器加载class文件,由生成的Servlet来处理请求,最后由HttpServletResponse以"text/html;charset=UTF-8"的形式发送到浏览器,显示HTML。

关于JSP/Servlet字符编码 关于JSP/Servlet字符编码

通常,在JSP中的Java代码中,或在Servlet的doGet、doPost中,调用request.getParameter(name)获取前台传来的参数时,经常会出现乱码问题。

乱码问题,究其原因,就是因为 前台页面编码、前台发请求时传参数所用编码、后台JSP/Servlet中从socket流读取参数解析参数时所用编码不统一。

首先,编写HTML文件时,就应该明确规定页面采用的编码:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

页面采用的编码,就是form提交时采用的编码,如果页面不明确指定编码,就会由浏览器自己决定了,这就出现了极大的不确定性。

指定编码时:

关于JSP/Servlet字符编码

不指定编码时:

关于JSP/Servlet字符编码


对于Chrome、Firefox也是如此。 

Tomcat读取JSP页面内容采用的编码:

关于JSP/Servlet字符编码

这张图画的有问题,Tomcat的代码写的太绕了,想知道详情,就去看代码吧[ParserController.determineSyntaxAndEncoding()]

因此,如果在JSP中pageEncoding和contentType都不指定的话,显示出来的页面可能会出乱码。


当使用JSP/Servlet获取前台传递的参数时:

<%@ page language="java" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
<%@page import="java.util.Enumeration"%>
<%
	out.println("Headers<br>");
	Enumeration headers = request.getHeaderNames();
	String name;
	while(headers.hasMoreElements()) {
		name = headers.nextElement()+"";
		out.println(name + " : " + request.getHeader(name));	
		out.println("<br>");
	}
	out.println("<br>");
	
	String v = request.getParameter("v");
	String username = request.getParameter("username");
	String password = request.getParameter("password");
	
	out.println("Default encoding:");
	out.println("v=" + v);
	out.println("username=" + username);
	out.println("password=" + password);
	out.println("<br>");
	
	out.println("GB2312:");
	out.println("v=" + new String(v.getBytes("ISO-8859-1"), "GB2312"));
	out.println("username=" + new String(username.getBytes("ISO-8859-1"), "GB2312"));
	out.println("password=" + new String(password.getBytes("ISO-8859-1"), "GB2312"));
	out.println("<br>");
	
	out.println("UTF-8:");
	out.println("v=" + new String(v.getBytes("ISO-8859-1"), "UTF-8"));
	out.println("username=" + new String(username.getBytes("ISO-8859-1"), "UTF-8"));
	out.println("password=" + new String(password.getBytes("ISO-8859-1"), "UTF-8"));
	out.println("<br>");
%>


如果HTML中没有在meta的http-equiv中指定Content-Type,提交form的时候:

关于JSP/Servlet字符编码

如果HTML中指定了Content-Type:

关于JSP/Servlet字符编码



Tomcat在读取参数时,如果在HTTP Request Header中没有指定Content-Type,读取参数流使用的编码是“ISO-8859-1”,这个参数由request.setCharacterEncoding()指定,不过需要在第一次执行request.getParameter()之前调用才可以。通过这个API,可以使用编码过滤器的方式来免去JSP/Servlet中获取参数时需要进行的编码转换。

package jspservlet;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class EncodingFilter 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");
		
		chain.doFilter(request, response);
	}

	@Override
	public void destroy() {
	}
}

添加了这个EncodingFilter之后,再调用request.getParameter()就不用再new String(value.getBytes("ISO-8859-1"), "UTF-8")了。



关于JSP/Servlet字符编码,布布扣,bubuko.com

关于JSP/Servlet字符编码

上一篇:Windows中的SID(Security Identifiers)是什么


下一篇:爬虫_随机UA(不含手机端)