- 浏览: 22621 次
- 性别:
- 来自: 广州
最近访客 更多访客>>
最新评论
-
guoyanxi:
感谢,正准备考
IBM AIX认证资料(含000-103&000-104题库) -
nrxqq:
不是很懂
Swing中的线程探究-1
Servlet技术介绍
Servlet又被称为Java服务器小程序,它是用Java编写的服务器端程序,是由服务器端调用和执行的、按照Servlet自身的规范编写的Java类。有的时候可以把Servlet看作是用Java编写的CGI,但是它们的实际功能比CGI要强得多。
下面是一个简单的Servlet程序
import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 一个简单的 Servlet 程序 * @author zhouych */ public class HelloWorldServlet extends HttpServlet { protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=gb2312"); PrintWriter out = response.getWriter(); try { out.println("<html>"); out.println("<head>"); out.println("<title>Servlet HelloWorldServlet</title>"); out.println("</head>"); out.println("<body>"); out.println("<h1>Servlet HelloWorldServlet at " + request.getContextPath () + "</h1>"); out.println("</body>"); out.println("</html>"); } finally { out.close(); } } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } @Override public String getServletInfo() { return "Short description"; } }
编写完Servlet程序后,还需要去配置web.xml属性文件,如下(节选)
<web-app> <servlet> <servlet-name>HelloWorldServlet</servlet-name> <servlet-class>HelloWorldServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloWorldServlet</servlet-name> <url-pattern>/HelloWorldServlet</url-pattern> </servlet-mapping> </web-app>
Servlet的生命周期
Servlet部署在容器中(如Tomcat中),它的生命周期由容器负责管理,具体可以分成5个部分:
1)装载Servlet类。
2)创建一个Servlet的实例(Servlet实际就是一个Java类,在使用前需要被创建其类对象)。
3)调用Servlet的init()方法(Servlet容器会对在web.xml文件中写的初始化参数进行初始化)。
4)调用Servlet的service()方法对收到的请求进行服务响应(service()方法由容器自动调用,程序员不应该去修改该方法,而只需要 修改诸如doGet()和doPost()等方法让service()根据请求自动调用相应方法即可)。
5)调用Servlet的destory()方法来销毁该实例。
Servlet中常用的类及接口
考试中对Servlet的内容比较多,Servlet中常用的类及接也比较多,这里不多介绍,有兴趣的可以查阅其他资料。
Servlet中的监听程序
我们可以创建一些特殊的Servlet类,这些类可以用来监听Servlet的上下文信息、Servlet中HTTP的会话信息和Servlet的请求信息,通过这些监听程序,可以在后台自动执行一些程序。常考的监听类型有:
1)Servlet上下文监听:在Web应用中可以部署一些监听程序,这些程序能够监听ServletContext的信息,比如ServletContext的查和删除,ServletContext属性的增加、删除和修改等。下面给出一个简单的例子程序
import java.io.FileOutputStream; import java.io.PrintWriter; import java.util.Date; import javax.servlet.ServletContext; import javax.servlet.ServletContextAttributeEvent; import javax.servlet.ServletContextAttributeListener; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; /** * 一个用来监听 ServletContext 及其属性的程序 * @author zhouych */ public class MyServletContextListener implements ServletContextListener, ServletContextAttributeListener { private ServletContext context = null; @Override public void contextInitialized(ServletContextEvent sce) { this.context = sce.getServletContext(); print("ServletContext被创建"); } @Override public void contextDestroyed(ServletContextEvent sce) { print("ServletContext被销毁"); this.context = null; } @Override public void attributeAdded(ServletContextAttributeEvent scab) { print("增加了一个属性: attributeAdded(" + scab.getName() + ", " + scab.getValue() + ")"); } @Override public void attributeRemoved(ServletContextAttributeEvent scab) { print("删除了一个属性: attributeRemoved(" + scab.getName() + ", " + scab.getValue() + ")"); } @Override public void attributeReplaced(ServletContextAttributeEvent scab) { print("修改了一个属性: attributeReplaced(" + scab.getName() + ", " + scab.getValue() + ")"); } private void print(String message) { PrintWriter pw = null; try { pw = new PrintWriter(new FileOutputStream("E:/log.txt", true)); pw.println(new Date().toString() + "::Form ContextListener; " + message); pw.close(); } catch (Exception e) { pw.close(); e.printStackTrace(); } } }
之后,需要在web.xml属性文件中添加内容如下(节选)
<web-app> <listener> <listener-class>listener.MyServletContextListener</listener-class> </listener> <web-app>
可以在JSP页面中添加如下代码来测试
<% out.println("add attribute"); getServletContext().setAttribute("user", "zhouych"); out.println("replace attribute"); getServletContext().setAttribute("user", "cheng"); out.println("remove attribute"); getServletContext().removeAttribute("user"); %>
2) Servlet会话监听:在Web应用中还可以监听HTTP会话活动情况、HTTP会话属性的设置情况和HTTP会话的active、passivate情况等。可以通过HttpSessionListener接口监听HTTP会话的创建、销毁的信息;通过HttpSessionBindingListener接口监听HTTP会话中对象的绑定信息;通过HttpSessionAttributeListener接口监听HTTP会话中属性的设置请求。下面给出一个简单的例子
import java.util.Hashtable; import java.util.Iterator; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; /** * 一个用来监听 HTTP 会话的程序 * @author zhouych */ public class MySessionListener implements HttpSessionListener { // 保存所有的登录信息 static Hashtable table = new Hashtable(); @Override public void sessionCreated(HttpSessionEvent se) { HttpSession session = se.getSession(); table.put(session.getId(), session); System.out.println("创建session: " + session.getId()); } @Override public void sessionDestroyed(HttpSessionEvent se) { HttpSession session = se.getSession(); System.out.println("销毁session: " + session.getId()); table.remove(session.getId()); } static public Iterator getSet() { return table.values().iterator(); } static public HttpSession getSession(String id) { return (HttpSession) table.get(id); } }
考试的时候经常会考查HttpSessionAttributeListener和HttpSessionBindingListener这两个接口的区别。这两个接口虽然都能用来监听会话过程属性的改变,但是两者又有不同。HttpSessionAttributeListener需要在部署描述符中定义,由Servlet容器创建一个实现类的实例,一般用来跟踪应用程序上所有的会话状态;而HttpSessionBindingListener则不需要在部署描述符中定义,仅当对象被添加进会话或从会话中删除时,Servlet容器会调用实现此监听接口的对象上的方法,一般用来处理一定类型对象被添加进会话或从会话中被删除的状况。
3)Servlet的请求监听:在Web应用中可以监听客户端的请求,比如可以从请求中获取客户端的地址并进行处理,一般使用ServletRequestListener接口和ServletRequestAttributeListener接口来处理,下面给出一个例子
import java.io.FileOutputStream; import java.io.PrintWriter; import javax.servlet.ServletRequest; import javax.servlet.ServletRequestAttributeEvent; import javax.servlet.ServletRequestAttributeListener; import javax.servlet.ServletRequestEvent; import javax.servlet.ServletRequestListener; /** * 一个用来建监听客户端的请求的程序 * @author zhouych */ public class MyRequestListener implements ServletRequestListener, ServletRequestAttributeListener{ @Override public void requestDestroyed(ServletRequestEvent sre) { print("销毁request"); } @Override public void requestInitialized(ServletRequestEvent sre) { print("创建request"); ServletRequest req = sre.getServletRequest(); if (req.getRemoteAddr().startsWith("127")) { req.setAttribute("isLogin", new Boolean(true)); } else { req.setAttribute("isLogin", new Boolean(false)); } } @Override public void attributeAdded(ServletRequestAttributeEvent srae) { print("attributeAdded(" + srae.getName() + ", " + srae.getValue() + ")"); } @Override public void attributeRemoved(ServletRequestAttributeEvent srae) { print("attributeRemoved(" + srae.getName() + ", " + srae.getValue() + ")"); } @Override public void attributeReplaced(ServletRequestAttributeEvent srae) { print("attributeReplaced(" + srae.getName() + ", " + srae.getValue() + ")"); } private void print(String message) { PrintWriter pw = null; try { pw = new PrintWriter(new FileOutputStream("E:/log.txt", true)); pw.println(message); pw.close(); } catch (Exception e) { pw.close(); e.printStackTrace(); } } }
Servlet中的过滤程序
在Web应用中过滤器能截取从客户端进来的请求,并做出处理的答复。在这里,过滤器可以验证客户是否来自可信的网络,可以对客户提交的数据进行重新编码、可以从系统里获得配置的信息、可以过滤掉某些词汇、可以记录系统日志、可以验证客户端的浏览器是否支持当前应用等等。程序员可以为一个Web应用部署多个过滤器,这些过滤器组成一个过滤链,每个过滤器只负责一个任务。下面给出一个例子
import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; /** * 一个对用户进行访问认证的过滤器程序,如果认证通过,那么允许 * 访问指定的资源,否则把请求转向其他地方(如转向认证页面) * @author zhouych */ public class SignonFilter implements Filter { public static final String LOGIN_PAGE = "login.jsp"; protected FilterConfig filterConfig; @Override public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest filterReq = (HttpServletRequest) request; HttpServletResponse filterRes = (HttpServletResponse) response; HttpSession session = filterReq.getSession(); String isLogin = ""; try { isLogin = (String) session.getAttribute("isLogin"); if (isLogin.equals("true")) { System.out.println("验证通过"); chain.doFilter(request, response); } else { filterRes.sendRedirect(LOGIN_PAGE); System.out.println("拦截了一个未认证的请求"); } } catch (Exception e) { } } @Override public void destroy() { this.filterConfig = null; } }
然后在web.xml中配置过滤器,如下(节选)
<web-app> <filter> <filter-name>auth</filter-name> <filter-class>filter.SignonFilter</filter-class> </filter> <filter-mapping> <filter-name>auth</filter-name> <url-pattern>/admin/*</url-pattern> </filter-mapping> </web-app>
Servlet中的线程安全问题
Servlet体系结构建立在Java多线程机制上,它的生命周期由Servlet容器负责。当客户端第一次请求某一个Servlet时,Servlet容器会根据部署描述符文件来实例化这个Servlet类。当有新的客户端再次请求该Servlet时,Servlet容器默认不会再实例化该Servlet类,默认以多线程模式来运行该实例。
这个时候问题来了,当有多个线程同时访问一个Servlet时,可能会发生多个线程同时访问同一资源的情况,这个时候就会发生一系列的安全性问题。
解决的方法也比较简单,主要有以下几种:
1)让Servlet类实现SingleThreadModel接口,这个接口会告诉容器如何处理对同一个Servlet的调用。一旦Servlet继承了该接口,则其里面的service()方法将不会有两个线程同时执行,保证了线程安全。
2)对共享数据进行同步化处理,比如可以使用synchronized关键字来同步共享数据。
3)在JSP页面中使用page指令的isThreadSafe来将该页面声明为线程安全。
4)避免使用实例变量。
需要提醒的是如果一个Servlet实现了SingleThreadModel接口,那么Servlet容器会为每个新的请求创建一个单独的Servlet实例,这将会引起系统的大量开销。同样如果使用同步代码,会导致同一时刻只能有一个线程在执行,而其他用户则被迫处于阻塞状态,同时为了保证主存内容和线程的工作内存中的数据一致,需要频繁地使用缓存,这同样会大大地影响系统的性能。所以最好的方法是避免使用实例变量,如果实在无法避免使用,那么应该使用同步代码来保护要使用的实例变量,但是注意一定要尽量使同步代码最小化。
Servlet的线程安全问题只有在大量的并发访问的时候才会显现出来,很难被发现,所以在编写Servlet程序的时候需要特意注意。
发表评论
-
SCWCD之路——结束语
2010-01-12 19:46 1237写到这里,整个专题终于告一段落了。总的来说,S ... -
SCWCD之路——附加内容
2010-01-12 19:32 904介绍 ... -
SCWCD之路——表达式语言
2010-01-12 18:55 1018介绍 EL(Expressio ... -
SCWCD之路——标准标签库开发
2010-01-11 20:58 905介绍 JSTL(JSP ... -
SCWCD之路——自定义标签库开发
2010-01-11 16:45 925介绍 ... -
SCWCD之路——J2EE设计模式
2010-01-11 15:15 1390概述 J2EE目前的设计模式有 ... -
SCWCD之路——Web应用的安全性
2010-01-10 16:14 1392概述 Servlet技术规范规 ... -
SCWCD之路——Web应用的结构和部署
2010-01-10 14:33 1238概述 在Web应用中,有着其一 ... -
SCWCD之路——JSP技术
2010-01-09 12:05 1287JSP介绍 ... -
SCWCD之路——前言
2010-01-07 20:43 1010SCWCD(Sun Certified Web ...
相关推荐
标题“SCWCD之路——前言”暗示了这是一个关于SCWCD(Sun Certified Web Component Developer)认证的学习历程或指南的开篇部分。SCWCD是Java EE(现在称为Jakarta EE)开发人员的一个专业认证,它专注于Web组件的...
标题“SCWCD之路——结束语”表明这是一个关于SCWCD认证学习的总结或结语。SCWCD,全称Sun Certified Web Component Developer,是Oracle(原Sun Microsystems)推出的一个Java Web开发领域的专业认证,主要考察...
本篇文章将探讨“SCWCD之路——Web应用的安全性”,并结合提供的文件`catalina.jar`和`tomcat-juli.jar`,深入讲解相关的安全知识点。 首先,让我们理解`catalina.jar`和`tomcat-juli.jar`。这两个文件都是Apache ...
"SCWCD之路——标准标签库开发"是一个关于Java Web开发中的重要主题,特别是与Servlet、JSP和自定义标签库相关的知识。SCWCD(Sun Certified Web Component Developer)是Oracle公司提供的一个Java Web开发认证,它...
这个认证主要针对那些希望在Java平台上从事Web应用程序开发的专业人士,特别是涉及到Servlet和JSP(JavaServer Pages)技术的开发者。 Servlet技术是Java Web开发的核心部分,它是一种用于扩展服务器功能的Java API...
在探讨Servlet技术及其在SCWCD(Sun Certified Web Component Developer)认证中的重要性时,我们首先需要理解Servlet的基本模型以及其在处理HTTP请求时的关键方法。本篇文章将深入解析《Servlet学习指南:SCWCD认证...
Servlets可以处理HTTP请求并生成动态内容作为响应,这使得它们成为构建动态网站和Web应用程序的核心技术之一。它们通过继承`javax.servlet.http.HttpServlet`类或实现`javax.servlet.Servlet`接口来创建。 #### ...
这个认证主要针对那些希望在Java EE平台上从事Web组件开发的专业人士,包括Servlet、JSP(JavaServer Pages)以及相关的技术。SCWCD证书证明了持有者具备创建动态Web应用程序的能力。 一、Servlet技术 Servlet是...
SCWCD,全称Sun Certified Web Component Developer,是Oracle(原Sun Microsystems)推出的Java EE(企业版)认证考试之一,主要考察开发者在构建Web应用程序方面的能力,包括Servlet、JSP、JSTL、EL表达式语言等...
【标题】"scwcd.rar_scwcd"指的是SCWCD相关的学习资源,SCWCD是Sun Certified Web Component Developer的缩写,这是Oracle(原Sun Microsystems)提供的一个Java Web开发的专业认证,主要针对Servlet和JSP技术。...
这个认证主要针对Servlet、JSP(JavaServer Pages)以及EL(Expression Language)等技术。在准备SCWCD认证考试的过程中,实际题目和答案的练习是非常关键的环节。 这份名为“SUN SCWCD认证考试真实题目一(有答案)...
《Head First Servlet & JSP》是一本非常受欢迎的IT教程,专为准备SCWCD(Sun Certified Web Component Developer)认证的读者设计。本书以其独特的学习风格,深入浅出地介绍了Servlet和JSP(JavaServer Pages)这两...
学习Servlet并准备SCWCD考试,有助于深入理解Java Web开发技术。 综上,Servlet速成教程将带你全面了解Servlet的基础知识,包括其工作原理、API使用、生命周期管理以及在实际项目中的应用。通过深入学习,你可以...
这本书以其独特的教学方式,深入浅出地讲解了SCWCD考试所涵盖的核心技术,包括JavaServer Pages (JSP) 和Servlets。 SCWCD是Java Web开发领域的专业认证,主要考察开发者对Web组件设计和实现的理解能力。通过这个...
SCWCD考试涵盖了Servlet、JSP(JavaServer Pages)以及相关的Web技术。本篇复习笔记将深入探讨Servlet技术模型及其相关知识点。 Servlet技术是Java EE平台的核心组成部分,用于处理HTTP请求。Servlet是一个Java类,...
SCWCD,全称Sun Certified Web Component Developer,是Oracle(原Sun Microsystems)为Java开发者提供的一项专业认证,主要测试考生在构建动态Web应用程序方面的能力,包括Servlet、JSP(JavaServer Pages)、...
在准备310-083 SCWCD考试时,考生需要深入理解Servlet API、JSP规范以及相关最佳实践。实践项目和模拟测试题是提高技能和熟悉考试格式的有效途径。同时,熟悉使用开发工具,如Eclipse、IntelliJ IDEA或NetBeans,...
SCWCD,全称Sun Certified Web Component Developer,是Oracle(原Sun Microsystems)为Java开发者提供的一项专业认证,主要测试考生在构建动态Web应用程序方面的能力,包括Servlet、JSP(JavaServer Pages)、EL...