JSP —— Filter 与 页面编码类型

一、jsp 页面编码

主要想弄清楚pageEncoding、page指令里的contentType、meta标签里声明的的contentType的关系。

新建一个jsp页面是这样的:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
</body>
</html>
页面有三处设置了编码,经测试,各处作用如下:

1、pageEncoding:设置页面执行时以何种方式编码(默认ISO-8859-1,此编码不支持中文,所以通常用UTF-8带替);

2、page指令中的contentType:告诉浏览器以何种方式对响应所接受的文件进行解码(一般需要与pageEncoding一致,否则可能出现乱码);

3、meta 标签中通过http-equiv对应的content值:作用与page指令中一致,都是告诉浏览器如何解码。


问题1:上面的第2与第3点作用相同,谁的优先级高?能否只设置一个或不设置?

答:通过测试发现,没有优先级的概念,如果在page指令中设置了contentType,则以它为准,否则以meta中设置的为准。如果两处都没设置,则以pageEncoding指定方式解码(如pageEncoding设置为GBK,则响应头中Content-Type为text/html,charset=GBK)。


注:通过浏览器的"查看"菜单项——>"编码"项查看默认编码(默认为utf-8)。eclipse中通过window——>references——>Web——JSP Files设置默认编码。

两者实际上都是设置HTTP 响应头的Content-Type 告诉浏览器该文件的编码方式,然后浏览器以该方式解码:。设置contentType为utf-8编码后,通过开发者工具查看:



问题2:为什么既要在page指令中设置contentType,还要在meta中通过http-equiv设置?

答:jsp页面中先判断page指令中有没有设置,再判断html标签的meta中有没有设置,只需在page指令中设置即可。html页面中只能在meta中设置。


以何种方式对页面进行编码,最好以该方式进行解码。

重点:两个页面是否相同没有必然关系!

如:如果两个页面的编码不同(a.jsp页面采用A编码,b.jsp页面采用B编码),则下面的代码思路是正确的,但却还是显示乱码:

//获取a.jsp页面传来的值
String aString=request.getAttribute("attrName");
//以a.jsp页面的编码方式解码,获得比特流
byte[] b=aString.getBytes("A");
//生成可在b.jsp页面正常使用的字符串
String bString=new String(b);

原因:

浏览器发送给服务器端的信息的编码是采用国际标准编码ISO-8859-1(对应中文),而非当前页面a.jsp的A编码方式,所以获取提交的中文信息应该如下:

String bString=new String(request.getAttribute("attrName").getBytes("ISO-8859-1"));//以ISO-8859-1方式对浏览器发来的中文信息进行解码

此外,注意不要对字符进行二次编码,如:

//假设页面采用GBK编码,则下列代码错误
String bString=new String(request.getAttribute("attrName").getBytes("ISO-8859-1"),"GBK");//错误,编码为GBK后,页面保存时会再次使用GBK编码,从而乱码


关于各种编码: https://wenku.baidu.com/view/cb9fe505cc17552707220865



二、JSP Filter

过滤器类似servlet,相当于一些应用组件,请求在到达请求资源前,或响应从资源到达客户端前都会先经过这些过滤器,可在过滤器中完成某些功能。

误区:不要把过滤器理解为对请求或响应的过滤,满足条件的通过,不满足的终止,实际上它们只是在请求或响应经过时先完成某些功能。


1、文档:

与过滤器相关的接口位于javax.servlet包中:



Filter 接口方法:

void init(FilterConfig config);
void doFilter(ServletRequest request,ServletResponse response,FilterChain chain);
void destroy();

FilterConfig 接口方法:

public String getFilterName();//如部署描述符中定义的那样,返回此过滤器的过滤器名称
public ServletContext getServletContext();//返回对调用者在其中执行操作的 ServletContext 的引用
public String getInitParameter(String name);//返回包含指定初始化参数的值的 String,如果参数不存在,则返回 null
public java.util.Enumeration<E> getInitParameterNames();//以 String 对象的 Enumeration 的形式返回过滤器初始化参数的名称,如果过滤器没有初始化参数,则返回一个空的 Enumeration


FilterChain 接口方法:

public void doFilter(ServletRequest request, ServletResponse response) throws java.io.IOException, ServletException;//导致链中的下一个过滤器被调用,如果调用的过滤器是链中的最后一个过滤器,则导致调用链末尾的资源。chain,链子,链条

说明:所有Filter组成一条链,Filter在链中的先后顺序是根据在web.xml中注册的先后顺序来的。


2、简单实践

每个过滤器类都要直接或间接地实现Filter 接口。下面演示使用Filter 统计访客。

编写Filter 实现类:

public class CountFilter implements Filter {

	private int count=1;
	@Override
	public void destroy() {}
	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		
		ServletContext application=request.getServletContext();
		String count = (String) application.getAttribute("count");
		if(count== null){
			this.count++;
			application.setAttribute("count", this.count+"");
		}
		else{
			this.count=Integer.parseInt(count);
			this.count++;
			application.setAttribute("count", this.count+"");
		}
		request.setAttribute("test", "sjadfklsadgjlas");//用于测试
		//向其他过滤器传递
		chain.doFilter(request, response);
	}
	
	@Override
	public void init(FilterConfig config) throws ServletException {
		
		this.count=Integer.parseInt(config.getInitParameter("count"));//从init-param元素中读取初始化参数。FilterConfig实例由容器自动创建
	}
	public void setCount(int count){
		this.count=count;
	}
}

配置该CountFilter:

<filter>
  	<filter-name>countFilter</filter-name>
  	<filter-class>com.milan.filters.CountFilter</filter-class>
  	<init-param>
  		<param-name>count</param-name>
  		<param-value>5000</param-value>
  	</init-param>
  </filter>
  <!-- 直接请求welcome.jsp时 -->
  <filter-mapping>
  	<filter-name>countFilter</filter-name>
  	<url-pattern>/welcome.jsp</url-pattern>
  </filter-mapping>
  <!-- 通过名称为resolveLogin的servlet中forward方式请求welcome.jsp时 -->
  <filter-mapping>
  	<filter-name>countFilter</filter-name>
  	<url-pattern>/resolveLogin</url-pattern>
  </filter-mapping>
说明:

filter-mapping元素中定义下面四个子元素:

每个filter-name只能对应其它三者之一,同servlet与servlet-mapping,可以有多个filter-mapping对应一个filter。修改配置信息重新访问网页时,最好清除浏览器缓存,被坑惨了。

<servlet-name>/resolveLogin</servlet-name>
<url-pattern>/welcome.jsp</url-pattern>
<dispatcher>REQUEST</dispatcher>
<filter-name></filter-name>
说明:
<dispatcher> 子元素可以设置的值及其意义:
REQUEST:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。
INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。
FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。
ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。
引用百度知道: https://zhidao.baidu.com/question/137194616.html

浏览器通过提交表单,访问resolveLogin的servlet,再forward到welcome.jsp。结果:

你好!xx,你是本站的第5003位访客!




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值