#过滤器
- 过滤器是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>