EL表达式
EL快速入门
使用EL表达式能够简化JSP页面中Java代码的编写。格式非常简单,只需要在JSP页面中嵌入${表达式}
即可。
<%--将用户名存入请求域--%>
<%request.setAttribute("username","zhangsan");%> <br>
Java代码获取数据:<%out.println(request.getAttribute("username"));%><br>
JSP表达式:<%=request.getAttribute("username")%><br>
EL获取数据:${username}
EL获取域值
EL表达式根据域对象中存储的数据类型不同,获取方式也稍有不同。
EL获取基本类型数据
<!--在request域中存数据-->
<% request.setAttribute("num",10); %>
<!--获取num的值-->
${num} <br>
EL获取自定义对象
<!--request域中存储Student对象-->
<%
Student stu=new Student("张三",20);
request.setAttribute("stu",stu);
%>
<!--EL获取Student对象的属性值-->
学生对象:${stu} <br>
学生姓名:${stu.name} <br>
学生年龄:${stu.age} <br>
EL获取List集合
<!--request域中存储List集合-->
<%
ArrayList<Student> list=new ArrayList<>();
list.add(new Student("张三",20));
list.add(new Student("李四",30));
request.setAttribute("list",list);
%>
<!--EL获取request域中的list集合,以及其元素-->
获取list集合:${list} <br>
获取list集合的0索引学生:${list[0]}<br>
获取list集合的1索引学生姓名:${list[1].name}<br>
EL获取Map集合
<!--request域中存储Map集合-->
<%
Map<String,String> map=new HashMap<>();
map.put("孙悟空","花果山");
map.put("猪八戒","高老庄");
map.put("沙和尚","流沙河");
request.setAttribute("map",map);
%>
<!--EL获取request域中的map集合,以及其元素-->
获取map集合:${map} <br>
获取map集合中键对应的值:${map["孙悟空"]} <br>
EL运算符
算数运算符:+ - * / %
比较运算符:== != > >= < <=
逻辑运算符:&& || !
空运算符:empty
功能:用于判断集合、数组、字符串是否为null并且长度是否为0
${empty list}
根据域中存储的数据,让单选框选中男或女
<%request.setAttribute("gender","女");%>
<input type="radio" value="男" ${gender=="男"?"checked":""}> 男
<input type="radio" value="女"${gender=="女"?"checked":""}> 女
EL表达式细节
1.EL表达式可以获取四大域的数据,依次从小到大的域中查找指定键名对应的值,如果找到了就不再往下找.
2.EL表达式可以获取八大隐式对象
JSTL标签库
JSTL(全称JavaServer Pages Tag Library)意为JSP标准标签库,可以用来简化在JSP页面中Java代码的编写。
在JSP页面导入JSTL包
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
常用JSTL标签
<!--if标签:相当于Java的if语句-->
<c:if test="${number%2==0}">
${number}是偶数
</c:if>
<!--choose标签:相当于Java的switch语句-->
<c:choose>
<c:when test="${number==1}">星期一</c:when>
<c:when test="${number==2}">星期二</c:when>
<c:when test="${number==3}">星期三</c:when>
</c:choose>
<!--foreach标签:相当于Java的for循环-->
<c:forEach begin="0" end="${list.size()}" step="1" var="i">
<c:if test="${list[i]!=null}">
${list[i].name},${list[i].age}<br>
</c:if>
</c:forEach>
<!--foreach标签:类似Java增强for循环-->
<c:forEach items="${list}" var="element">
${element.name},${element.age}<br>
</c:forEach>
过滤器Filter
当客户端访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能。举个例子帮助大家理解,比如2020年初在爆发了新冠病毒疫情,为了防止病毒扩算到全国,武汉市宣布封城,所有交通渠道限制通行,在各个出入口设卡拦截,只有体温正常的医务人员和急救物资才能进入城区。这里武汉市各个出入口的关卡,起到的就是过滤器的作用。
在程序中是同样的道理,比如用户在访问服务器资源时只允许登录过的用户才能正常访问。这里登录校验起到的就是过滤器的作用。除了登录校验,在程序中过滤器的用处还有统一编码处理,铭感词汇过滤等等。
过滤器统一编码
@WebFilter("/*")
public class FilterDemo1 implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("FilterDemo1过滤器执行了");
servletResponse.setContentType("text/html;charset=utf-8");
filterChain.doFilter(servletRequest,servletResponse);
}
}
过滤器拦截配置
1. 具体资源路径: /index.jsp
只有访问index.jsp资源时,过滤器才会被执行
2. 拦截目录: /user/*
访问/user下的所有资源时,过滤器都会被执行
3. 后缀名拦截: *.jsp
访问所有后缀名为jsp资源时,过滤器都会被执行
4. 拦截所有资源:/*
访问所有资源时,过滤器都会被执行
过滤器的生命周期
1. init:在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源
2. doFilter:每一次请求被拦截资源时,会执行。执行多次
3. destroy:在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源
配置方式
方式一:注解方式: @WebFilter("拦截路径")
方式二:XML配置,如下:
多个过滤器使用顺序
如果有多个过滤器,取决于过滤器映射的顺序,也就是<filter-mapping>
的配置顺序。
如果是注解的方式配置Filter,那么Filter的执行顺序和类名有关,但是不靠谱,建议使用xml方式配置Filter,使用
<filter-mapping>
配置执行顺序。
核心方法
代码演示
配置初始化参数
<filter>
<filter-name>filterDemo04</filter-name>
<filter-class>com.itheima.filter.FilterDemo04</filter-class>
<init-param>
<param-name>username</param-name>
<param-value>zhangsan</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>filterDemo04</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
获取初始化参数
//@WebFilter("/*")
public class FilterDemo04 implements Filter{
/*
初始化方法
*/
@Override
public void init(FilterConfig filterConfig) {
System.out.println("对象初始化成功了...");
//获取过滤器名称
String filterName = filterConfig.getFilterName();
System.out.println(filterName);
//根据name获取value
String username = filterConfig.getInitParameter("username");
System.out.println(username);
}
//其他方法省略不写了...
}
过滤器五种拦截行为【补充】
问题:如何使过滤器拦截转发的请求和响应?
介绍
Filter 过滤器默认拦截的是客户端发送过来的请求,但是在实际开发中,我们还有请求转发,以及由服务器触发调用的全局错误页面。默认情况下过滤器是不参与过滤的,要想使用,就需要我们配置。
拦截方式
<filter>
<filter-name>filterDemo05</filter-name>
<filter-class>com.itheima.filter.FilterDemo05</filter-class>
<!--配置开启异步支持,当dispatcher配置ASYNC时,需要配置此行-->
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>filterDemo05</filter-name>
<!--<url-pattern>/error.jsp</url-pattern>-->
<url-pattern>/*</url-pattern>
<!--过滤客户端发送的请求:默认值。-->
<dispatcher>REQUEST</dispatcher>
<!--过滤请求转发:当请求转发时,过滤器工作。-->
<dispatcher>FORWARD</dispatcher>
<!--过滤全局错误页面:当由服务器调用全局错误页面时,过滤器工作-->
<dispatcher>ERROR</dispatcher>
<!--过滤请求包含:当请求包含时,过滤器工作。它只能过滤动态包含,jsp的include指令是静态包含,过滤器不会起作用-->
<dispatcher>INCLUDE</dispatcher>
<!--过滤异步类型,它要求我们在filter标签中配置开启异步支持-->
<dispatcher>ASYNC</dispatcher>
</filter-mapping>
核心:知道REQUEST和FORWARD就行了,REQUEST表示拦截客户端浏览器发送的请求,FORWARD拦截转发的请求。
如果是使用注解配置过滤器,那么拦截方式设置如下:@WebFilter(value = {"/servletDemo01","/servletDemo02"},dispatcherTypes = {DispatcherType.FORWARD,DispatcherType.REQUEST})
监听器Listener
监听器用于监听web应用中某些对象的创建和销毁,属性的增加、修改和删除等事件。当事件发生时,作出相应的响应处理。常用于统计在线人数,系统加载时进行信息初始化,统计网站的访问量等等。
对象监听器
ServletContextListener
监听应用的创建和销毁
ServletRequestListener
监听请求的创建和销毁
HttpSessionListener
监听Session的创建和销毁
属性监听器
ServletContextAttributeListener
监听应用域属性的添加,修改和删除
ServletRequestAttributeListener
监听请求域属性的添加,修改和删除
HttpSessionAttributeListener
监听Session域属性的添加,修改和删除
统计访问人数
定义Session对象监听器,只有一个用户访问就会为该用户创建一个HttpSeesion对象。当用户关闭浏览器时
@WebListener
public class ListenerDemo1 implements HttpSessionListener {
private int number=0;
@Override
public void sessionCreated(HttpSessionEvent se) {
number++;
se.getSession().setAttribute("number",number);
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
number--;
se.getSession().setAttribute("number",number);
}
}
总结
1 EL表达式
作用:简化jsp页面java代码的书写,用来从域对象中获取数据。
语法:${表达式}
EL表达式获取不同类型数据:
request.setAttribute("num",10); ------> ${num}
request.setAttribute("stu",student); ------> ${stu.name} ${stu.name}
request.setAttribute("students",list); --> ${students[1].name} ${students[1].name}
EL中使用运算符:
${empty stu?"":stu.name}
${not empty stu?stu.name:""}
EL获取虚拟目录:
${pageContext.request.contextPath}
2 JSTL标签库
【第一步】添加jstl对应的jar包
【第二步】在jsp页面使用taglib引入核心标签库
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
【第三步】使用标签库中的标签
<c:if test="${}">
</c:if>
<c:choose>
<c:when test=${}></c:when>
<c:when test=${}></c:when>
... ...
<c:otherwise></c:otherwise>
</c:choose>
<c:forEach var="i" begin="0" end="${list.size()-1}" step="1">
</c:forEach>
<c:forEach items="${list}" var="stu" varStatus="statu">
</c:forEach>
3 Filter过滤器【重要】
作用:拦截请求和响应,拦截到之后我们可以放行也可以不放行。
定义一个filter过滤器:在包上鼠标右键--->web filter【重要】
@WebFilter("/*")
public class FilterDemo01 implements Filter{
public void init(FilterConfig config) throws ServletException {}
public void destroy() {}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
//放行
chain.doFilter(request,response);
}
}
使用细节:
1 如果有多个过滤器,过滤器的执行顺序由filter-mapping的先后位置绝对。
2 服务器启动的时候就会创建Filter过滤器
3 如果要拦截转发的请求,需要设置dispatcher。
xml配置:
<!--过滤客户端发送的请求:默认值。-->
<dispatcher>REQUEST</dispatcher>
<!--过滤请求转发:当请求转发时,过滤器工作。-->
<dispatcher>FORWARD</dispatcher>
注解配置:
dispatcherTypes = {DispatcherType.FORWARD,DispatcherType.REQUEST}
4 Listener监听器
作用:监听域对象的创建/销毁,监听域对象中值的变化(添加值,替换值,移除值),监听session中存储对象的变化(绑定/解绑,钝化/活化)
@WebListener
public class ContextLoaderListener implements ServletContextListener{
//重写监听器中的所有抽象方法
}