1、问题由来
众所知周,因为编码问题,如果向 Cookie 中放入中文字符串,将会引发 java.lang.IllegalArgumentException: Control character in cookie value or attribute 异常。要解决这个问题,需要对中文字符串进行 base64 或者 URLEncoder 编码。而这样又引发新的问题:如果用 EL 表达式获取 Cookie 中的值,得到的将是编码后的字符串,譬如:%E5%BC%A0%E4%B8%89
public class LoginServlet extends HttpServlet
{
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("username");
/* 将参数中的用户名经过 URL 编码后添加到 cookie 中 */
response.addCookie(new Cookie("username", URLEncoder.encode(username, "utf-8")));
}
}
2、解决办法
(1) 在 JSP 页面中使用 Java 代码获取
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page import="java.net.URLDecoder" %> <!-- 导入 URL 包 -->
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>登录</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<%
String username = "";
Cookie[] cookies = request.getCookies();
if(cookies != null)
{
for(Cookie cookie : cookies)
{
if(cookie.getName().equals("username"))
{
if(cookie.getValue() != null)
{
/* 获取名为 username 的 Cookie 中的值并用 URL 解码 */
username = URLDecoder.decode(cookie.getValue(), "utf-8");
}
break;
}
}
}
%>
<h1><%=username %></h1>
</body>
</html>
(2) 在 JSP 页面中使用 EL 表达式获取
大家都知道,用 EL 表达式获取 Cookie 的代码更加简洁,只需要 ${cookie.username.value } 一句代码即可获取到名为 username 这个 Cookie 对象的值,但是这样获取到的内容是 %E5%BC%A0%E4%B8%89 这样编码后的值,所以我们需要对 ${cookie.username.value } 的内容进行解码,要做到这一点,我们需要自定义 EL 函数库或者 JSTL 标签,这里我们以自定义 EL 函数库为例
Ⅰ定义名为 URLFunctions.java
public class URLFunctions
{
/**
* 以指定的编码方式对字符串进行解码
* @param s:要解码的字符串
* @param enc:解码的编码方式,如 utf-8
* @return 解码后的字符串
*/
public static String decode(String s, String enc)
{
try
{
return URLDecoder.decode(s, enc);
}
catch (UnsupportedEncodingException e)
{
throw new RuntimeException(e);
}
}
/**
* 以指定的编码方式对字符串进行编码
* @param s:要编码的字符串
* @param enc:解码的编码方式,如 utf-8
* @return 编码后的字符串
*/
public static String encode(String s, String enc)
{
try
{
return URLEncoder.encode(s, enc);
}
catch (UnsupportedEncodingException e)
{
throw new RuntimeException(e);
}
}
}
Ⅱ 在 WEB-INF/tlds/ 目录下创建 urlFunctions.tld 文件
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<description>url function library</description>
<display-name>url functions</display-name>
<tlib-version>1.0</tlib-version>
<short-name>ufn</short-name>
<uri>http://www.zwj.com/jsp/jstl/urlFunctions</uri>
<function>
<description>
以 enc 编码方式编码输入的字符串 s
</description>
<name>encode</name>
<function-class>com.zwj.web.el.URLFunctions</function-class>
<function-signature>java.lang.String encode(java.lang.String, java.lang.String)</function-signature>
</function>
<function>
<description>
以 enc 编码方式解码输入的字符串 s
</description>
<name>decode</name>
<function-class>com.zwj.web.el.URLFunctions</function-class>
<function-signature>java.lang.String decode(java.lang.String, java.lang.String)</function-signature>
</function>
</taglib>
Ⅲ 在 JSP 中使用函数库
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="ufn" uri="WEB-INF/tlds/urlFunctions.tld" %> <!-- 导入自定义 EL 函数库 -->
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>登录</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<h1>${ufn:decode(cookie.username.value,"utf-8") }</h1>
</body>
</html>