ServletJSP:下

#过滤器

  • 过滤器是Servlet2.3规范中定义的一种小型的,可插入的web组件,用来拦截Servlet容器的请求和响应过程,以便查看、提取或以某种方式操作正在客户机和服务器之间交换的数据
  • 过滤器通常是封装了一些功能的web组件,这些功能很重要,但对于处理客户端请求或发送响应来说不是决定性的

这里写图片描述

#使用过滤器

  • step1. 写一个java类,实现Filter接口。
  • step2. 在接口方法当中,实现拦截处理逻辑。
public class CommentFilter implements Filter{
	private FilterConfig config;
	/**
	 * 容器在销毁过滤器实例之前,会调用此方法。
	 */
	public void destroy() {
		System.out.println("destroy()");
	}

	/**
	 * 容器会调用doFilter方法来处理请求
	 * FilterChain(过滤器链):如果调用了该对象的
	 * doFilter方法,则继续向后执行,否则中断请求。
	 */
	public void doFilter(ServletRequest request, ServletResponse response,FilterChain arg2)throws IOException, ServletException {
		System.out.println("doFilter begin...");
	    request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		String content = request.getParameter("content");
		//读取初始化参数
		String illegal = config.getInitParameter("illegal");
		if(content.indexOf(illegal) != -1){
			out.println("<h1>评论内容非法</h1>");
		}else{
			//继续向后执行
			arg2.doFilter(request, response);
		}
		System.out.println("doFilter end.");
	}
	/**
	 * 容器启动之后,会立即创建过滤器实例(只会创建一个)
	 * 接下来,会调用该实例的init方法(只会执行一次)
	 * FilterConfig:用来读取初始化参数。
	 */
	public void init(FilterConfig arg0) throws ServletException {
		System.out.println("init()");
		//将容器传递过来的FilterConfig对象保存下来
		config = arg0;
	}
  • step3. 配置过滤器。
    配置文件必须写对,不然问题很多,比如404或者无法启动服务器。
<filter>
  	<filter-name>commentFilter</filter-name>
  	<filter-class>web.CommentFilter</filter-class>
  	<!-- 配置初始化参数 -->
  	<init-param>
  		<param-name>illegal</param-name>
  		<param-value>猫</param-value>
  	</init-param>
  </filter>
  <filter-mapping>
  	<filter-name>commentFilter</filter-name>
  	<url-pattern>/comment</url-pattern><!-- 这个位置要和需要滤的servlet相同 -->
  </filter-mapping>

##过滤器的优先级
当有多个过滤器都满足过滤的条件
则容器依据<filter-mapping> 配置的先后顺序来执行。
##优点

  • 在不修改原有代码的基础上,为程序添加新的功能。
  • 将多个模块相同的代码集中写在一个类里面,方便代码的维护。
    #监听器

servlet规范当中定义的一种特殊的组件,
用来监听容器产生的事件并进行相应的处理。

##容器会产生两大类事件

  • 生命周期相关的事件
    容器创建或者销毁request,session,servlet上下文产生的事件。
    ServletRequestListener
    HttpSessionListener
    ServletContextListener
  • 绑订数据相关的事件
    调用了request,session,servlet上下文的setAttribute,removeAttribute产生的事件。
    ServletRequestAttributeListener
    HttpSessionAttributeListener
    ServletContextAttributeListener
    ##编写监听器步骤
  • step1. 写一个java类,依据监听的事件类型来实现相应的接口。
    比如,要监听session对象的创建和销毁,可以实现
    HttpSessionListener接口。
  • step2. 在监听器接口方法当中,实现监听处理逻辑。
public class CountListener implements HttpSessionListener{
/**
	 * session对象创建之后,会执行此方法
	 *  arg0:事件对象
	 */
	public void sessionCreated(HttpSessionEvent arg0) {
		System.out.println("sessionCreated()");
		//获得Servlet上下文
		HttpSession session = arg0.getSession();
		ServletContext sc = session.getServletContext();
		//获取Servlet上下文上绑订的人数
		Integer count = (Integer)sc.getAttribute("count");
		if(count == null){
			//第一个用户
			count = 1;
		}else{
			//非第一个用户,累加
			count ++;
		}
		sc.setAttribute("count", count);	
	}
	/**
	 * session对象销毁之后,会执行此方法。
	 */
	public void sessionDestroyed(HttpSessionEvent arg0) {
		System.out.println("sessionDestroyed()");
		ServletContext sc = arg0.getSession().getServletContext();
		Integer count = (Integer) sc.getAttribute("count");
		count --;
		sc.setAttribute("count", count);
	}
}
  • step3. 配置监听器
    web.xml中
<!-- 配置监听器 -->
  <listener>
  	<listener-class>web.CountListener</listener-class>
  </listener>

##应用场景

  • 在contextDestroyed方法中对应用级别的资源进行释放
  • 统计在线人数可以通过HttpSessionListener监听器的sessionCreated方法监听session的创建动作

#容器处理异常

这里写图片描述

这里写图片描述

#jsp标签和el表达式
##jsp标签
jsp标签类似于html标签,用来替换jsp中的java代码。
因为直接在jsp文件中写java代码,不利于jsp文件的维护(比如,将包含有大量java代码的jsp交给美工去修改就很不方便),所以,sun公司制订了jsp标签技术规范。使用jsp标签代替java代码之后,jsp文件变得简洁,便于维护。而且便于代码的复用。
##el表达式
是一套运算规则,用于给jsp标签的属性赋值,也可以直接输出。

###使用

  • 访问bean的属性 (e1.jsp)
  • 方式一
  • ${user.name} : 容器依次pageContext,request,session,application中查找绑订名为"user"的对象(getAttribute),找到之后,会调用该对象的"getName"方法,然后输出;如果找不到,会输出""。
    - 依次,指的是先从pageContext上去查找,如果没有,再查找request,如果找到,则不再向下查找了。
    - 如果值为null,会转换成""输出。如果要指定查找范围,可以使用pageScope,requestScope,sessionScope,applicationScope。
    比如:${requestScope.user.name}。
  • 方式二 ${user['name']} 等价于${user.name}
    • []可以使用绑订名。
    • []可以使用从0开始的下标,用来读取数组中的某个元素。
<body style="font-size:30px;">
		<%
			User user = new User();
			user.setName("Sally");
			user.setAge(22);
			user.setInterest(new String[]{"cooking","snooker"});
			request.setAttribute("user", user);
			User user2 = new User();
			user2.setName("Tom");
			user2.setAge(33);
			session.setAttribute("user", user2);
		%>
		name:<%
			//User user1 = (User)request.getAttribute(
			//		"user");
			//out.println(user1.getName());
		%>
		<br/>
		name:${user.name}<br/>
		name:${sessionScope.user.name} <br/>
		name:${user['name']}<br/>
		<%
			request.setAttribute("prop", "age");
		%>
		${user[prop]}<br/>	
		${user.interest[0]}		
	</body>
  • 做一些简单的运算
  • 算术运算 +,-,*,/,% : + 只能求和。
  • 关系运算 >,>=,<,<=,==,!=
  • 逻辑运算 && || !
  • empty运算 empty
<body style="font-size:30px;">
		1 + 1 = ${1 + 1} <br/>
		"a"  + "b" = ${"1" + "1" } <br/>
		1 < 2吗? ${1 < 2} <br/>
		<%
			request.setAttribute("s1", "abc");
		%>
		${sesionScope.s1 == 'abc'}
		
		${1 < 2 && 2 > 3}
		
		empty运算: <br/>
		<%
			request.setAttribute("s2", "");
			List list1 = new ArrayList();
			request.setAttribute("list1", list1);
		%>
		空字符串:${empty s2}<br/>
		空的集合:${empty list1} <br/>
		null值: ${empty null}
		找不到任何数据:${empty a}		
	</body>
            用来判断集合是否为空,或者是否为一个空字符串。 
  • 读取请求参数值
    ${param.username}等价于request.getParameter("username");
    ${paramValues.city}等价于request.getParameterValues("city");
    <body style="font-size:30px;">
			username:${param.username}<br/>
			city:${paramValues.city[0]}
	</body>

##jstl(java standard taglib)标签
apache开发的一套标签,后来捐献给了sun。
1)如何使用jstl标签。
step1.导包。(jstl.jar)
step2.使用taglib指令,导入要使用的标签。
###核心标签

  • if标签
        <c:if test="" var="" scope="">
            标签体
        </c:if>

a1. c是命名空间的前缀(别名)。
命名空间(namespace): 为了区分同名的元素而添加的一个 限定。
a2. 如果test属性值为true,则执行标签体的内容。
test属性可以使用el表达式来计算。
a3. var属性指定一个绑订名,scope属性指定绑订的
范围(“page”,“request”,“session”,“application”)

<body style="font-size:30px;">
		<%
			User user = new User();
			user.setName("花千骨");
			user.setGender("f");
			request.setAttribute("user", user);
		%>
		姓名:${user.name}
		性别:
		<c:if test="${user.gender == 'm'}">男</c:if>
		<c:if test="${user.gender == 'f'}">女</c:if>
		
		<br/>
		性别:
		<c:if test="${user.gender == 'm'}">男</c:if>	
		<c:if test="${user.gender != 'm'}">女</c:if>
		
		性别:
		<c:if test="${user.gender == 'm'}" 
		var="rs" scope="page">男</c:if>
		<c:if test="${!rs}">女</c:if>
	</body>
  • choose标签
        <c:choose>
            <c:when test="">
            </c:when>
            <c:otherwise>
            </c:otherwise>
        </c:choose>

b1.when表示一个分支,如果test属性值为true,
则执行该分支。(可以出现1次或者多次)
b2.otherwise表示例外,可以出现0次或者1次。

<body style="font-size:30px;">
		<%
			User user = new User();
			user.setGender("x");
			request.setAttribute("user", user);
		%>
		性别:
		<c:choose>
			<c:when test="${user.gender == 'm'}">男</c:when>
			<c:when test="${user.gender == 'f'}">女</c:when>
			<c:otherwise>保密</c:otherwise>
		</c:choose>
  • forEach标签
        <c:forEach items="" var="" varStatus="">
        </c:forEach>

c1.用来遍历集合或者数组。
c2.items属性用来指定要遍历的集合或者数组,
可以使用el表达式。
c3.var属性用来指定绑订名(绑订范围是pageContext)。
c4.varStatus属性用来指定绑订名(绑订范围是pageContext),绑订值是一个特殊的对象(由该标签
创建,作用是用来获得当前遍历的状态,比如getIndex
方法:获得当前被遍历的元素的下标。getCount方法用
来获得当前是第几次遍历) 。

<c:forEach items="${users}" var="u" 
			varStatus="s">
				<tr class="row${s.index % 2 + 1}">
					<td>${u.name}</td>
					<td>${u.gender}</td>
					<td>${s.index}</td>
					<td>${s.count}</td>
				</tr>
			</c:forEach>

###自定义jsp标签
(1)编程步骤

  • step1. 写一个java类,继承SimpleTagSupport类。

step2. override doTag方法,在该方法里面,写处理逻辑。

package tag;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class HelloTag extends SimpleTagSupport{
	private String msg;
	private int qty;
	
	
	public HelloTag() {
		System.out.println("HelloTag()");
	}

	public String getMsg() {
		return msg;
	}

	public void setMsg(String msg) {
		System.out.println("setMsg() " + msg);
		this.msg = msg;
	}

	public int getQty() {
		return qty;
	}

	public void setQty(int qty) {
		System.out.println("setQty() " + qty);
		this.qty = qty;
	}


	@Override
	public void doTag() throws JspException, IOException {
		System.out.println("doTag()");
		
		/* 可以通过继承自SimpleTagSupport类提供的方法
		 * 来获得pageContext。
		 * pageContext提供了获得其它所有隐含对象的
		 * 方法。
		 */
		PageContext pc = 
				(PageContext)getJspContext();
		JspWriter out = pc.getOut();
		
		for(int i = 0; i < qty; i ++){
			out.println(msg + "<br/>");
		}
	}

}

step3. 在.tld文件当中描述标签。
<body-content>的值可以是emtpy,scriptless,JSP
empty:标签没有标签体。
scriptless:标签可以有标签体,但是标签体的内容不能够
出现java代码(<% %>,<%= %>,<%! %>)。
JSP:标签可以有标签体,标签体的内容可以出现java代码。但是,只有复杂标签技术才支持。

<?xml version="1.0" encoding="UTF-8" ?>

<taglib xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
    version="2.1">
   
  	<tlib-version>1.1</tlib-version>
  	<short-name>t1</short-name>
  	<uri>test</uri>
  	
  	
  	<tag>
    <name>hello</name>
    <tag-class>tag.HelloTag</tag-class>
    <body-content>empty</body-content>
    <attribute>
        <name>msg</name>
        <!-- true表示该属性必选 -->
        <required>true</required>
        <!-- true表示该属性可以动态赋值 -->
        <rtexprvalue>false</rtexprvalue>
    </attribute>
    <attribute>
    		<name>qty</name>
    		<required>true</required>
    		<rtexprvalue>true</rtexprvalue>
    </attribute>
  </tag>
</taglib>
  • 使用
<%@page pageEncoding="utf-8" 
contentType="text/html; charset=utf-8" %>
<%@ taglib uri="test" prefix="t1" %>
<html>
	<head></head>
	<body style="font-size:30px;">
		<t1:hello msg="Hello World" qty="${1 + 3}"/>
		
	</body>
</html>

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值