- Java EE框架开发技术与案例教程
- 张继军 董卫
- 3595字
- 2025-02-25 22:03:12
2.2 控制层技术
控制层实现技术有Servlet技术、过滤器(Filter)和监听器(Listener),其中过滤器和监听器是两种特殊的Servlet技术。
2.2.1 Servlet技术与应用案例
Servlet是用Java语言编写的服务器端程序,是由服务器端调用执行、按照Servlet自身规范编写的Java类。Servlet可以处理客户端传来的HTTP请求,并返回响应。
1.Servlet编程接口
设计Servlet要在Servlet框架约束下进行,并遵守其中所要求的规则。Servlet框架是由javax.servlet和javax.servlet.http两个Java包组成的。表2-15列出了Servlet框架中部分接口与类。
表2-15 Servlet编程接口与类

2.设计Servlet
在Java EE中,开发设计Servlet就是开发一个遵守规范中所规定的各种特征的Java类。设计Servlet需要继承javax.servlet.http.HttpServlet类,其结构如下。
Servlet程序的基本结构如下。
package …; //省略了包名 import …; //省略了导入包 public class Servlet类名称extends HttpServlet{ public void init(){} public void doGet( HttpServletRequest request, HttpServletResponse response){} public void doPost(HttpServletRequest request, HttpServletResponse response){} public void destroy(){} }
说明:
1)Servlet类需要继承类HttpServlet。
2)Servlet的父类HttpServlet中包含了几个重要方法,常根据需要重写它们。
● init():初始化方法,Servlet对象创建后,接着执行该方法。
● doGet():当请求的类型是get时,调用该方法。
● doPost():当请求的类型是post时,调用该方法。
● destroy():Servlet对象注销时自动执行。
在设计时只需要重写doGet()和doPost()方法即可,同时要配置Servlet。
3.配置Servlet
Servlet需要配置,只有配置后才可以使用。配置有两种方式:一种是在web.xml中配置,另一种是直接在源代码中采用注释配置,本书采用注释配置Servlet。
采用注释配置Servlet,是在Servlet类定义的上方直接使用注释“@WebServlet”,注释格式如下。
@WebServlet("/请求名称") public class类名称extends HttpServlet{//实现代码}
在程序设计中一般使用注释配置。
【例2-7】实现一个简单的用户登录验证程序,如果用户名是abc,密码是123,则显示欢迎用户的信息,否则显示“用户名或密码不正确”。
【分析】该案例采用JSP页面只完成提交信息和验证结果的显示,而验证过程由Servlet完成,这些组件通过request(或HttpServletRequest)对象实现数据共享。由提交页面将数据传递给Servlet,而Servlet获取数据并实现验证,根据验证结果,转向显示验证结果的页面。
【设计】根据分析,该系统需要设计3个组件。
1)登录表单页面:login.jsp。
2)处理登录请求并实现验证的Servlet:LoginCheckServlet.java。
3)显示提示的页面:info.jsp。
假设组件之间共享数据的参数为:username(用户名称)和userpwd(密码)。
【实现】
(1)登录页面login.jsp

(2)处理登录的Servlet:LoginCheckServlet.java

(3)显示结果的页面info.jsp
<%@page pageEncoding="UTF-8"%> <html> <head><title>显示结果页面</title></head> <body> <%=request.getAttribute("outputMessage") %> </body> </html>
【运行测试】运行页面程序login.jsp,按题目要求输入相关信息并提交。
通过该例题可以看到,JSP与Servlet之间存在调用关系,同时它们之间也存在数据共享的关系。
2.2.2 过滤器技术与应用案例
过滤器(Filter)是一种特殊的Servlet技术。过滤器对用户的请求信息和响应信息进行过滤,常被用于权限检查和参数编码统一设置等。过滤器是在服务器上运行的,是位于请求与响应中间的起过滤功能的程序。
进行过滤器编程用到javax.servlet.jar中的一组接口(javax.servlet.Filter等),即设计过滤器需要实现Filter接口,并要根据处理的功能需要实现Filter接口中的3个方法。
public void init(FilterConfig filterConfig) throws ServletException{} public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException{} public void destroy(){}
1.过滤器基本结构
过滤器程序的基本结构如下。
package …; import …; public class过滤器类名称implements Filter{ public void destroy(){//添加代码} public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException{//添加代码} public void init(FilterConfig filterConfig) throws ServletException{//添加代码} }
2.过滤器的建立
在Eclipse开发环境下创建过滤器是很方便的,其创建过程如下。
1)创建实现Filter接口的类:在项目的src下,创建一个或多个过滤器,并采用“包”结构的方式组织所有的过滤器。
2)实现init方法,读取过滤器的初始化函数。
3)将过滤行为放入doFilter()方法中:实现doFilter(),完成该过滤器所需要的过滤功能。
4)调用filterchain对象的doFilter方法:filterChain对象是过滤器接口的doFilter方法的一个参数,调用Filterchain的doFilter方法时,下一个关联的过滤器将被调用,若没有其他与Servlet或JSP相关联的过滤器,就调用Servlet或JSP本身。
5)将过滤器与特定的Servlet或JSP页面关联:使用部署配置文件(web.xml)中的filter元素和filter-mapping元素。
另外,必须对过滤器进行配置(在web.xml内),指定要过滤的URL等信息。
【例2-8】在一个Web应用程序中,有些JSP页面或Servlet必须是注册用户登录后才有权访问。设计一个过滤器,用于对用户是否是登录用户进行检验。
【分析】判断一个用户是否登录的方法通常是:当用户登录成功后,将用户名存放到session范围内(session.setAttribute("u_name", username)),判断时,从session中取出u_name属性(session.getAttribute("u_name")),若取值不为空就是登录用户,否则,就不是登录用户,可转入注册页面。
在每个需要登录用户才可以访问的页面或Servlet中加入登录检验代码很冗余,通过编写过滤器,将过滤地址设为需要进行登录检验的那些Servlet或JSP的地址。
【设计关键】在过滤器中获取session对象(HttpSession)。
HttpServletRequest requ = (HttpServletRequest)request; HttpSession session = requ.getSession(true);
【实现】登录检验过滤器:LoginFilter.java。
package filters; //省略了创建时自动导入的包 public class LoginFilter implements Filter{ public void destroy() {} public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterchain) throws IOException, ServletException{ HttpServletRequest requ = (HttpServletRequest)request; HttpServletResponse resp = (HttpServletResponse)response; HttpSession session = requ.getSession(true); if (session.getAttribute("u_name") = = null) {resp.sendRedirect("login.jsp"); } else {filterchain.doFilter(request, response); } } public void init(FilterConfig arg0) throws ServletException {} }
【注册过滤器】过滤器必须在web.xml注册配置后才能起作用。假设要过滤/admin目录下的所有程序,注册信息如下。
<filter> <filter-name>loginfilter</filter-name> <filter-class>filters.LoginFilter </filter-class> </filter> <filter-mapping> <filter-name>loginfilter</filter-name> <url-pattern>/admin/*</url-pattern> </filter-mapping>
该程序还需要设计注册页面(login.jsp)、登录页面(login.jsp),以及登录处理页面(将请求参数uaerName保存到session中的u_name属性中),具体的实现步骤请读者自己完成。
2.2.3 监听器技术与应用案例
监听器(Listener)是一种特殊的Servlet技术。它可以监听Web应用的上下文信息、Servlet请求信息和Servlet会话信息,并自动根据不同情况,在后台调用相应的处理程序。利用监听器来对Web应用进行监听和控制,增强了Web应用的事件处理能力。
监听器编程要用到javax.servlet.jar中的一组监听接口和事件类。根据监听对象的不同,监听器可被划分为3种。
1)ServletContext事件监听器:用于监听应用程序环境对象。
2)HttpSession事件监听器:用于监听用户会话对象。
3)ServletRequest事件监听器:用于监听请求消息对象。
这3种监听器共包含了8个监听接口、6个监听事件类,如表2-16所示。
表2-16 监听器接口与事件类

1.监听ServletContext对象
对ServletContext对象实现监听,可以监听到ServletContext对象中属性的变化(增加、删除和修改操作),也可以监听到ServletContext对象本身的变化(创建与销毁)。常用的监听方法如表2-17所示。
表2-17 监听ServletContext对象的常用方法

2.监听会话
监听HttpSession对象,可监听HttpSession对象中属性的变化(增加、删除和修改操作),也可监听HttpSession对象本身的变化(创建与销毁),以及该对象的状态,还可监听HttpSession对象是否绑定到该监听器对象上。常用的监听方法如表2-18所示。
表2-18 监听HttpSession对象的常用方法

说明:活化(Activate)和钝化(Passivate)是Web容器为了更好地利用系统资源或者进行服务器负载平衡等原因而对特定对象采取的措施。会话对象的钝化指的是暂时将会话对象通过序列化的方法存储到硬盘上,而活化与钝化相反,是把硬盘上存储的会话对象重新加载到Web容器中。
3.监听请求
对ServletRequest对象进行监听,可以监听到ServletRequest对象中属性的变化(增加、删除和修改操作),也可以监听到HttpSession对象本身的变化(创建与销毁)。常用的监听方法如表2-19所示。
表2-19 监听ServletRequest对象的常用方法

4.设计监听器
设计监听器一般需要以下步骤。
1)实现合适的接口:要根据监听对象的不同,实现表2-16中的某个监听接口。
2)实现有关事件的方法:按所选择的监听器接口,实现该接口中的有关方法。
3)获取对Web应用对象的访问:在事件处理方法中,可能会用到9个重要对象(分为3类)。
● Servlet上下文、变化后的Servlet上下文属性的名称、变化后的Servlet上下文属性的值。
● 会话对象、变化后的会话属性的名称、变化后的会话属性的值。
● 请求对象、变化后的请求对象属性的名称、变化后的请求对象属性的值。
4)使用这些对象:需要根据具体应用,选择有关的对象。例如,对于Servlet上下文,可能会读取初始化参数(getInitParameter方法),存储数据供以后使用(setAttribute方法)和读取原先存储的数据(getAttribute方法)。
5)配置监听器:在web.xml中,利用listener元素和listener-class元素完成配置。
5.监听器基本结构
一个监听器程序的基本结构如下。
package …; import …; public class监听器实现类名implements***Listerner{//实现***Listerner中的方法}
6.监听器信息配置
监听器的配置信息同样写在web.xml里,配置相对简单,无需配置地址。
<listener><listener-class>监听器类的包路径</listener-class></listener>
提示:在Eclipse环境下同样没有直接新建Listener的菜单项,通过新建Class完成,在新建Class时指定Class实现的接口;监听器的配置也需要在web.xml中手动完成。
【例2-9】使用监听器统计并显示在线用户数目。
【分析】当一个浏览器第一次访问网站时,服务器会新建一个HttpSession对象,并触发HttpSession创建事件,如果注册了HttpSessionListener事件监听器,则会调用HttpSessionListener事件监听器的sessionCreated方法。相反,当这个浏览器用户注销或访问结束超时的时候,服务器会销毁相应的HttpSession对象,触发HttpSession销毁事件,同时调用所注册HttpSessionListener事件监听器的sessionDestroyed方法。这样,只需要在HttpSessionListener实现类的sessionCreated方法中让计数器加1,在sessionDestroyed方法中让计数器减1,就可实现网站在线人数的统计功能。
【设计关键】选择正确的监听接口并实现相应的抽象方法:由上面的分析可知,要监听HttpSession对象的创建和销毁,因此监听器类要实现的接口为HttpSessionListener。
【实现】
1)设计监听器类:OnlineListener.java
package listener; import javax.servlet.http.*; public class OnlineListener implements HttpSessionListener { private static int onlineCount=0; public void sessionCreated(HttpSessionEvent sessionEvent) { onlineCount++; } public void sessionDestroyed(HttpSessionEvent sessionEvent) { if(onlineCount>0) onlineCount--; } public static int getOnlineCount(){return onlineCount; } }
2)修改web.xml文件,在web.xml文件中添加以下配置代码
<listener> <listener-class>listener.OnlineListener</listener-class></listener>
3)显示在线人数的页面online.jsp
<%@page pageEncoding="UTF-8"%> <%@page import="listener.OnlineListener"%> <html> <head><title>在线人数显示页面</title> </head> <body><h2>当前的在线人数:<%=OnlineListener.getOnlineCount() %></h2> </body> </html>
【运行测试】运行页面程序online.jsp,查看在线人数。