JavaWeb EL表达式, JSTL标签及过滤器综合学习
1.项目结构如右边图所示:
(1)controller.filter包下面定义2个过滤器,EncodingFilter 类CheckUserFilter类(后面会有一个登陆验证的过滤器的测试学习),
(2)el包下面定义一个ElTestServlet类(el表达式使用,处理用户请求,把servlet中设定的数据读取到eltest.jsp页面中显示)和LoginSuccessServlet类,处理用户登陆信息
(3)user包下面定义user实体类(登陆验证过滤器使用)
(4)WebRoot 根目录下:
1)eltest.jsp: el表达式和JSTL表达式使用测试页面,把ElTestServlet类中的数据显示到页面上
2)error.jsp 和success.jsp页面是测试登陆验证过滤器的测试使用的
2.el表达式和jstl标签 及过滤器部分 (针对ElTestServlet代码中的注释,先忽略过滤器的作用 )
3.本次学习小项目的目的:从ElTestServlet中获取数据(2个名字相同,作用域不同的变量name,一个list对象,1个user对象),
然后在eltest.jsp页面中用EL表达式拿到并显示出来,这其中用到JSTL标签去遍历获取到的集合对象(EL表达式无法遍历集合)
然后,在这个基础上加上过滤器的知识,也就是增加一个EncodingFilter 类,在web.xml中进行配置,再去测试就OK了
ElTestServlet类定义如下:
1 package el; 2 3 import java.io.IOException; 4 import java.util.ArrayList; 5 import java.util.List; 6 7 import javax.servlet.ServletException; 8 import javax.servlet.http.HttpServlet; 9 import javax.servlet.http.HttpServletRequest; 10 import javax.servlet.http.HttpServletResponse; 11 12 import user.User; 13 14 public class ElTestServlet extends HttpServlet { 15 16 private static final long serialVersionUID = -831893763619493234L; 17 18 @Override 19 protected void service(HttpServletRequest req, HttpServletResponse resp) 20 throws ServletException, IOException { 21 //在serlvet服务代码中,对request对象了一个属性,名字是name,值是requestVar 22 req.setAttribute("name", "requsetVar"); 23 //在session对象中同样设置一个name属性,值是sessionVar,到时候看看eltest.jsp页面中${name}获取到的是哪一个name 24 req.getSession().setAttribute("name", "sessionVar"); 25 //创建2个user对象 26 User user1 = new User("张三", 1, "18855555555"); 27 User user2 = new User("李斯", 0, "18866666666"); 28 List<User> users = new ArrayList<User>(); 29 users.add(user1); 30 users.add(user2); 31 req.setAttribute("yonghu", users);//把装有多个User对象的list集合装到request对象中去 32 req.setAttribute("user1", user1);//把一个User对象装到request对象中 33 req.getRequestDispatcher("eltest.jsp").forward(req, resp);//把客户端请求转发到eltest.jsp 34 } 35 36 }
eltest.jsp页面:
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 <!-- 引入jstl,设定前缀 --> 3 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 4 5 <% 6 String path = request.getContextPath(); 7 String basePath = request.getScheme() + "://" 8 + request.getServerName() + ":" + request.getServerPort() 9 + path + "/"; 10 %> 11 12 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 13 <html> 14 <head> 15 <base href="<%=basePath%>"> 16 17 <title>My JSP 'index.jsp' starting page</title> 18 </head> 19 20 <body> 21 1.普通方式获取参数: <br> 22 <% 23 String name1 = (String) request.getAttribute("name"); 24 String name2 = (String) request.getSession().getAttribute( 25 "name"); 26 pageContext.setAttribute("name", "pageContextVar"); 27 application.setAttribute("name", "applicationVar"); 28 %> 29 request对象中的name: <%=name1%> <br> 30 sesssion对象中的name: <%=name2%> <br><hr> 31 2.使用el表达式获取四大作用域中的对象参数: <br> 32 未指定作用域时的name>>>${name}<br> 33 pageContext对象中的name>>> ${pageScope.name }<br> 34 request对象中的name>>>${requestScope.name}<br> 35 session对象中的name>>>${sessionScope.name}<br> 36 application对象中的name>>> ${applicationScope.name }<br><hr> 37 3.使用el表达式获取一个对象中的属性:<br> 38 姓名:${user1.name }<br> 39 性别:${user1.gender }<br> 40 电话:${user1.phone }<br><hr> 41 4.使用JSTL标签获取一个集合中的所有元素的属性:<br> 42 43 <c:choose> 44 <c:when test="${empty yonghu }"> 45 没有查询到相关数据 46 </c:when> 47 <c:otherwise> 48 <table border="1px"> 49 <tr> 50 <td>姓名</td> 51 <td>性别</td> 52 <td>电话</td> 53 </tr> 54 <c:forEach items="${yonghu }" var="user" > 55 <tr><!--把集合中的元素拿出来交给变量user,然后对user取属性值, 56 取到的就是servlet传过来的user对象的属性值 --> 57 <td>${user.name }</td> 58 <td> <c:if test="${user.gender==1}">男</c:if> 59 <c:if test="${user.gender==0}" >女</c:if> </td> 60 <td>${user.phone }</td> 61 </tr> 62 </c:forEach> 63 64 </table> 65 </c:otherwise> 66 </c:choose> 67 68 </body> 69 </html>
ElTestServlet和EncodingFilter 配置(Web.xml):
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 5 http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> 6 <display-name></display-name> 7 <welcome-file-list> 8 <welcome-file>index.jsp</welcome-file> 9 </welcome-file-list> 10 11 <!--ElTestServlet配置 --> 12 <servlet> 13 <servlet-name>ElTestServlet</servlet-name> 14 <servlet-class>el.ElTestServlet</servlet-class> 15 </servlet> 16 <servlet-mapping> 17 <servlet-name>ElTestServlet</servlet-name> 18 <url-pattern>/eltest</url-pattern> 19 </servlet-mapping> 20 21 <!-- Encoding过滤器设置 url-pattern设置为*表示对所有的项目进行过滤 --> 22 <filter> 23 <filter-name>EncodingFilter</filter-name> 24 <filter-class>controller.filter.EncodingFilter</filter-class> 25 <init-param> 26 <param-name>charset</param-name> 27 <param-value>UTF-8</param-value> 28 </init-param> 29 </filter> 30 <filter-mapping> 31 <filter-name>EncodingFilter</filter-name> 32 <url-pattern>/*</url-pattern> 33 </filter-mapping> 34 35 <!-- CheckUserFilter过滤器配置 <filter-name>是指定要被过滤器拦截的servlet, /eltest表示访问eltest路径下的资源时 36 会被过滤器拦截并处理 /*表示对该项目所有资源进行拦截过滤 --> 37 <filter> 38 <filter-name>CheckUserFilter</filter-name> 39 <filter-class>controller.filter.CheckUserFilter</filter-class> 40 </filter> 41 <filter-mapping> 42 <filter-name>CheckUserFilter</filter-name> 43 <url-pattern>/success</url-pattern> 44 </filter-mapping> 45 46 <!--LoginSuccessServlet servlet配置 --> 47 <servlet> 48 <servlet-name>LoginSuccessServlet</servlet-name> 49 <!--servlet服务类: LoginSuccessServlet --> 50 <servlet-class>el.LoginSuccessServlet</servlet-class> 51 </servlet> 52 <servlet-mapping> 53 <servlet-name>LoginSuccessServlet</servlet-name> 54 <url-pattern>/success</url-pattern> 55 <!--在浏览器中输入:协议名:/主机名:端口地址/web项目名/url-pattern指定的路径名, 就会进入LoginSuccessServlet,执行这个类中的服务了 --> 56 </servlet-mapping> 57 58 <!--在浏览器中输入localhost:8080/webstu5exercise/success 如果没有过滤器,会进入到LoginSuccessServlet 59 这个servlet中进行请求处理,当设置了过滤器,会先进入过滤器CheckUserFilter,进行登陆验证判断,如果用户名正确,就进入下一个 过滤器直至最后一个过滤器,
然后才会进入被拦截了的LoginSuccessServlet,处理其中的程序( 把页面转发到登陆成功页面:succes.jsp req.getRequestDispatcher("success.jsp").forward(req, 61 resp);),如果用户名不正确,则在过滤器里面就重定向 到error.jsp页面中去,LoginSuccessServlet根本不会执行到 if(name.equals("lch")){ 62 chain.doFilter(req, resp);//执行完,转到了eltest.jsp页面 }else { ((HttpServletResponse)resp).sendRedirect("error.jsp");//转到error.jsp 63 } --> 64 65 </web-app>
EncodingFilter过滤器定义:
1 package controller.filter; 2 3 import java.io.IOException; 4 5 import javax.servlet.Filter; 6 import javax.servlet.FilterChain; 7 import javax.servlet.FilterConfig; 8 import javax.servlet.ServletException; 9 import javax.servlet.ServletRequest; 10 import javax.servlet.ServletResponse; 11 12 public class EncodingFilter implements Filter{ 13 14 private String charset = ""; 15 @Override 16 public void destroy() { 17 System.out.println("-------------过滤器销毁-----------"); 18 19 } 20 21 @Override 22 public void doFilter(ServletRequest req, ServletResponse resp, 23 FilterChain chain) throws IOException, ServletException { 24 if(charset!=null && charset.trim().length()!=0){ 25 req.setCharacterEncoding(charset);//设定请求页面编码格式 26 resp.setCharacterEncoding(charset);//设定响应页面编码格式 27 } 28 //以下重要!!!如果不写,则只有这一个过滤器工作,后面的过滤器,web请求都无效 29 chain.doFilter(req, resp);//如果还有过滤器,就进入下一个过滤器,没有,进入调用web资源的过程 30 31 } 32 33 @Override 34 public void init(FilterConfig filterConfig) throws ServletException { 35 36 // 在过滤器初始化的时候获取配置文件中指定的字符集参数! 37 String initCharset = filterConfig.getInitParameter("charset"); 38 if(initCharset!=null && initCharset.trim().length()!=0){ 39 //如果从web.xml读取到的配置中的charset不为空,就赋值给当前过滤器的属性charset 40 charset = initCharset; 41 //动态赋值,配置文件中是什么编码,此处得到的是什么编码,不能在过滤器里边把编码格式写死 42 System.out.println("获取到配置文件中的字符编码格式为:"+charset); 43 System.out.println("--------初始化完成--------"); 44 } 45 } 46 47 }
上边几个写好并且配置好web.xml文档后,在浏览器输入:http://localhost:8080/webstu5exercise/eltest 并访问,结果如下:
可以看到,当四个作用域对象具有相同的属性名的属性时,如果不指定作用域,那么用el表达式获取到的是pageContext对象中的name属性的值,
如果取值时用${sessionScope.name}取到的才是session对象中的name属性的值。输出这样的结果,是因为,el表达式获取属性时,会从pageContex,request,session,application四个作用域对象中依次去查找,且优先从pageContext中去查找。如果pageContex中找到了,就拿过来用,如果pageContex中没有,就依次往更大的范围内去找,如果application对象中也没有,就什么也没取到,如果要在jsp页面上输出该属性的值,将会没有显示。