一、Servlet简介:html
●Servlet是一个符合特定规范的 JAVA 程序 , 是一个基于JAVA技术的Web组件。java |
●Servlet容许在服务器端,由Servlet容器所管理,用于处理客户端请求并作出响应。程序员 |
●Servlet容器:Servlet容器也称为 Servlet引擎,是 WEB 服务器或应用程序服务器的一部分,用于在发送的请求和响应之上提供网络服务。web ●管理和运行 Servlet/JSP的容器也称Web容器;算法 ●Servlet容器、JSP 容器和 Web容器是同义的;数据库 |
●Servlet主要用于生成动态的内容,他能够接受和处理请,求并动态生成 HTML 内容对客户端进行响应; 浏览器
|
二、Servlet与 JSP 的关系:服务器
●在使用JSP技术开发 WEB 程序时,咱们所要作的是在 JSP 中写入 JAVA 代码,当服务器运行JSP时,将JSP转换成JAVA类并编译执行,动态获取数据生成 HTML 代码 , 最终显示在客户浏览器上。cookie |
|||
|
|||
●Servlet继承javax.servlet.http.HttpServlet类: eg: 分析:JSP 在运行时会被 Web容器译为一个Servlet,动态响应内容是经过运行这个Servlet类产生的,Servlet是 JAVA Web动态交互术的关键组件,也是 JSP 的技术基础,容器在运行 JSP 时,须要先将其内容翻译成 Servlet的语法,再按照Servlet的方式运行; |
|||
●Servlet体系结构: |
三、Servlet API:
●Servlet API包含在两个包内, javax. Servlet包中的类和接口是通用的不依赖协议的 Servlet API,包括 Servlet、ServletRequest、ServletResponse、ServletConfig、ServletContext接口及抽象类GenericServlet , javax.servlet.http包中的类和接口是用于支持 HTTP协议的Servlet API; |
||||||||||||
●Servlet接口:定义了全部Servlet须要实现的方法;
|
||||||||||||
●GenericServlet抽象类:提供了Servlet接口和ServletConfig接口,给出了方法的默认实现(service( )方法除外);定义了通用的、不依赖于协议的Servlet。
★一般只须要重写不带参的init()方法,若是重写init(ServletConfig config)方法,则应包含super.init(config)代码; ★若是要编写一个通用的Servlet,只要继承自GenericServlet类,实现service()方法便可; |
||||||||||||
●HttpServlet抽象类:大多数的网络应用是经过 HTTP协议访问服务器资源的,所以咱们编写的 Servlet大多也是应用于处理 HTTP协议的请求和响应。 ★抽象类HttpServlet 继承自GenericServlet类,具备与GenericServlet相似的方法,并提供了与 HTTP相关的实现,支持对HTTP的POST、GET 等请求方式进行差别化处理;开发中,若是须要编写 Servlet,主要就是继承 HttpServlet 抽象;
★HttpServlet的service (HttpServletRequest req, HttpServletResponse res )方法至关于一个分发器,能够根据请求方法的类型,调用相应的doXxx()方法。因此在编写Servlet时只须要根据应用的须要,重写doGet()或者doPost()方法便可; |
||||||||||||
●ServletConfig接口:Servlet容器使用ServletConfig在Servlet初始化过程当中获取配置信息,一个Servlet只有一个ServletConfig对象;
|
||||||||||||
●ServletContext 接口: ★一个 ServtetContext接口的实例表示一个 Web 应用的上下文,Sewlet 使用 Servletontext 接口定义的方法与它的 Servlet 容器进行通讯。JSP 内置对象application就是 ServletContext的实例。 ★Servlet 容器厂商负责提供 ServletContext 接口的实现,容器在应用程序加载时建立ServletContext对象,ServletContext 对象被 Sefvlet 容器中的全部Sefvlet共享。
|
■请求、响应相关接口:ServletRequest 和 HttpServletRequest 接口: |
||||||||||||||||||||
★ServletRequest 接口:当客户请求时,由 Servlet 容器建立 ServletRequest 对象用于封装客户的请求信息,这个对象将容器做为 service ( ) 方法的参数之一传递给 Servlet , Servlet 可以利用 ServletRequest 对象获取客户端请求数据。
|
||||||||||||||||||||
★HttpServletRequest接口:HttpServletReqiest 位于 javax.servlet.http包中,继承自ServletRequest 接口,经过该接口一样能够获取请求中的参数。HttpServletRequest 接口除了继承了ServletRequest 接口中的方法,还增长了一些用于读取请求信息的方法;
|
||||||||||||||||||||
■ServletResponse 和 HttpServletResponse 接口: |
||||||||||||||||||||
★ServletResponse接口:Servlet 容器在接收客户请求时,除了建立 ServletRequest 对象用于封装客户的请求信息外,还建了一个 ServletResponse 对象,用于封裝响应数据,而且同时将这两个对象一并做为参数传递给Servlet。Servlet利用ServletRequest 对象获取客户端的请求数据,通过处理后由 ServletResponse 对象发送响应数据;
★HttpServletResponse:与 HttpServletRequest 接口相似,HttpServletResponse 接口也继承自 ServletResponse 接口,用于客户端的请求执行响应。它除了具备ServletResponse接口的经常使用方法外、还增长了新的方法;
|
四、Servlet的应用:
●建立Servlet ★继承HttpServlet ★重写doPost()或doGet()方法 ● 部署Servlet ★编译Servlet到/WEB-INF/classes目录 ★编辑部署描述文件web.xml <servlet> <servlet-name> Servlet的名字</servlet-name> <servlet-class> Servlet 类的彻底限定名</servlet-class> </servlet> <servlet-mapping> <servlet-name>给出 Servlet 的名字,必须与在< servlet >元素中声明的Servlet 名字相同</servlet-name> <url-pattern>指定 Servlet 的 URL</url-pattern> </servlet-mapping> ●启动Tomcat,访问Servlet |
●建立Servlet: eg:建立一个用于获取用户名并向页面输出的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; public class HttpServletTest extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 在Tomcat中配置URIEncoding解决GET方式的中文乱码,代码中再也不作处理 String uName = request.getParameter("username"); if (uName == null) { uName = "游客"; } // 设置响应内容的类型并指定字符集,以避免浏览器展现中文内容时出现乱码 response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); out.println("<html>"); out.println(" <head><title>Servlet</title></head>"); out.println(" <body>"); out.println("你好,欢迎" + uName + "来到Servlet世界"); out.println(" </body>"); out.println("</html>"); out.flush(); out.close(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 对POST方式提交的数据统一设置字符集,解决中文乱码问题 request.setCharacterEncoding("UTF-8"); doGet(request, response); } } 分析:在上面的示例中,须要强调如下三点: ★开发 Servlet 时,首先要导入 Servlet 所需的包; ★自定义的 Servlet 类继承自 HttpServlet 类; ★实现 doGet ()或者 doPost()方法; ▲My Eclipse下Servlet中方法的实现:选中source——Override/Implement Methods…——选择须要实现的方法——OK; 如图: 技巧:HTTP请求经过使用 GET 或 POST 方法提交,相应地在 Servlet 中也提供了 doGet()和 doPost()两种分别处理请求的方法,但实际的处理过程不少时候却几手是相同的,所应一般的处理方法是:分别编写 doGet )和 doPost ()方法对应不一样的提交方式,同时经过相互调用避免重复编码。例如,把处理代码都写在 doGet()方法中, 而后在 doPost()方法调用 doGet ()方法。这样就能保证既能对不一样提交方式进行差别化处理,又能够避免代码冗余; |
●部署 Servlet:首先应编辑 Web 应用的部署描述文件 web.xml,添加对示例 3 中 Servlet 类的配置,该文件在程序运行Servlet时起着一个 ‘总调度" 的角色 , 它会告诉容器如何建立和访问 Servlet。在 web. xml 文件中配置 Servlet 须要使用两个 XML 元素 < servlet >和<servlet-mapping>。 其中<servlet>元素把Servlet 全类名 ( 包名+类名) 映射到一个内部名称,而< servlet –mapping>元素则将某个 URL 映射到Servlet 的内部名称; eg:web. xml 文件的关键代码以下: <servlet> <servlet-name>HttpServletTest</servlet-name> <servlet-class>cn.store.servlet.HttpServletTest</servlet-class> </servlet> <servlet-mapping> <servlet-name>HttpServletTest</servlet-name> <url-pattern>/HttpServletTest</url-pattern> </servlet-mapping> 分析:在示例中,web.xml 文件中使用了< servlet >和<servlet-mapping>两个 XML 元素把用户访问的URL 映射到 Servlet, ◆详细介绍这两个元素及其子元素: 1)、在 web.xml文件中, < servlet >元素可包含多个子元素,其中<servlet-name>指定 Servlet的名字 , 这个名字在同一个 Web 应用中必须惟一,<servlet-class>指定 Servlet 类的彻底限定名; 2)、<servlet-mapping>元素在 Servlet 和 URL 之间定义映射,它包含两个子元素<servlet-name>和<url-pattern>: ★<servlet-name>给出 Servlet 的名字,必须与在< servlet >元素中声明的Servlet 名字相同, ★<url-pattern>元素指定 Servlet 的 URL , 须要特别注意的是,该路径是相对于 Web 应用程序的路径,在配置Servlet 与 URL的映射后,当 Servlet 容器接收到一个请求时,对请求的路径和Servlet映射的路径进行匹配,进而调用具体Servlet类的相关方法。 ◆下面介绍在web.xml 中经常使用<url-pattern>设置方法: ▲<url-pattern>/xxx</url-pattern>精确匹配 , 如<url-pattern>/ helloServlet </url-pattern>; ▲<url-pattern>/xxx/*</url-pattern>,路径匹配,若是没有精确匹配,对/xxx/路径的全部请求将由该 Servlet 进行处理,如<url-pattern>/ helloServlet/* </url-pattern>,; ▲<url-pattern>*.xxx</url-pattern>若是没有精确匹配和路径匹配,则全部针对. xxx扩展名的请求将由该 Servlet 处理; ◆扩展:有时需指定在容器启动时 Servlet 的加载次序,能够在<servlet>元素中增长<load-on-startu>元素。该元素的值必须是整数,若是为负数或没有指定这个元素,容器将在客户端首次访问 Servlct 时进行加载;若是为正数或0;客器将在启动时根据值的顺序加载 Servlet,且值越小加载优先级越高; |
●访问 Servlet: eg:部署完 Servlat 后,下面介绍如何访问 Servlet, 建立 index . jsP 页面代码以下: <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>ServletTest</title> </head> <body> <form action="HttpServletTest" method="post"> 姓名:<input type="text" name="username" /> <input type="submit" value="提交"/> </form> </body> </html> 分析:在上面的代码中,表单提交的路径 (action 属性 ) 指向 web.xml 文件中<url-pattern>元素所指定的URL, 便可访问对应的 Servlet。 ★部署项目并启动 Tomcat 后,打开浏览器,在地址栏中 输入 ’ http//localhost8080/store/index. jsp" 输入用户姓名为 "小菜包',页面会显示:你好,欢迎小菜包来到 Servlet世界; ★若是根据 web . xml 中设置的 URL 输入 “ http//localhost : 8080/store/HttpServletTest直接访Servlet , 根据“访问Servlet”的下面的代码,在运行时若是没有传递 username 参数就会默认输出 '游客" ,页面会显示:你好,欢迎游客来到 Servlet世界; ◆提示:若是但愿 Web 应用起始访问的是 Scrvlet, 则能够在 web.xml 文件中进行配置, eg:<welcome-file-list> <welcome-file>HttpServletTest</welcome-file> </welcome-file-list> 这时在浏览器中输入 "http://localhost:8080/store’ :运行效果一样是(页面会显示):你好,欢迎游客来到 Servlet世界; |
技巧:为了方便管理,一般将建立的 Servlet 单独放在一个包中,如 cn.store.servlet。 ★经过 IDE工具能够快速建立和部署 Servlet: 右击专门存放 Servlet 的包——New——Servlet——Name: XxxServletName (为建立的 Servlet 命名)——Next ( 此步骤的窗口信息用于部署 web.xml , 配置 Servlet 能够选择各项的默认值,也能够根据须要修改Servlet名称和 Servlet的映射路径,即修改’Servlet/JSP Name:' 和’ Servlet/JSP Mapping URL:',对于 “Display Natne:”和 “Description “后面的解释内容, 能够删除)——Finish; ★用工具建立的Servlet只是一个Servlet模扳,能够根据业务需求编写; |
五、使用 Servlet 实现控制器:
●Servlet与 JSP 的区别: ★JSP文件在用户第一次请求时会被编译成Servlet, 而后由这个Servlet处理用户的请求,因此 JSP 也能够当作是运行时的Servlet; ★JSP 和 Servlet 的区别: ◆JSP页面在 HTML 元素中嵌入Java脚本代码和 JSP 标记,比使用传统Servlet技术开发表示层更加容易。JSP的部署也更加简单,JSP容器 (Servlet容器)会对扩展名是.jsp的URL统一配置,将其转换为 Servlelt为客户端服务,无需为每个 JSP 文件配置 URL 映射; ◆JSP 页面 HTM元素与 java脚本混合的语法 , 对于请求处理过程当中编写流程控制代码,数据访问代码等倒是不利的,难以模块化开发及重用,此时更适合采用传统 Java 类的形式进行开发。所以使用 Servlet 在服务器上解释和执行浏览器的请求,充当客户端和其余层之间的中间层角色更加合适; ◆经过上面的分祈,Servlet 和 JSP 各有所长,JSP 能够方便地开发表示层组件. 而Servlet适合编写流程控制代码. 在开发 Wab 应用时,能够针对二者的特点结合使用,合理分工; |
●实现Servlet控制器: ★使用 JSP 来作控制页, 主要功能是流程控制和业务逻辑处理,如今能够将这部分代码提取出来由Servlet来完成,应用的架构以下图: ★Servlet充当控制器的角色,它接受请求、负责实例化 JavaBean 对象对业务逻辑进行处理,并为JSP页面准备封装的JavaBean对象,接着将请求分发给适当的JSP页面来产生响应; |
◆技巧:request.getContextPath()能够获取当前web 应用的上下文路径. 对于经由浏览器请求的URL , 使用应用上下文路径进行约束,能够避免使用相对路径时可能发生的路径解析错误; eg: ‘location.href=“’contextPath+“ /util/topics?opr=list’” 对于转发方法使用的 URL, 能够直接以 “/” 开始以表示当前应用的根路径; |
六、Servlet的生命周期:
●Servlet的生命周期是经过 Servlet接口中的 init()、servicef()和 destroy()方法来表示的;即 Servlet从建立到销毀的过程,包括如何加载和实例化、初始化、处理请求以及如何被销毁; ◆加载和实例化:Servlet不能独立运行,它必须被部署至Servlet 容器中,由容器实例化和调用 Servlet 的方法,Servlet容器在 Servlet的生命周期内管理 Servlet,当Servlet容器启动或者当客户端发送一个请求时, Servlet容器会查找内存中是否存在Servlet的实例, 若是不存在,就建立一个 Servlet实例,若是存在该Servlet的实例,就直接从内存中取出该实例响应请求; ◆初始化:在Servlet容器完成 Servlet 实例化后,Servlet容器将调用 Servlet的 init()方法进行初始化,初始化的目的是让Servlet对象在处理客户端请求前完成一些准备或资源预加载工做,如设置数据库链接参数,创建 JDBC 链接,或者是创建对其余资源的引用。 ★注:对于每个Servlet实例 init()方法只能被调用一次; ◆服务:Servlet被初始化后 , 就处于能响应请求的就绪状态,当Servlet容器接收客户端请求时,调用Servlet的 service()方法处理客户端请求,HttpServlet 的service()方法会根据 GET 或 POST 请求转调doGet()或 doPost()方法,Servlet实例经过 ServletRequest 对象得到客户端的请求,经过调用ServletResponse 对象的方法设置响应信息; ◆销毁:Servlet 的实例是由 Servlet 容器建立的,因此实例的销毁也是由容器来完成的,Servlet容器判断一个 Servlet容器是否应当被释放时(容器关闭或须要回收资源),容器就会调用 Servlet 的 destroy()方法,该方法指明哪些资源能够被系统回收,而不是由 destroy()方法直接回收 Servlet 实例; |
●Servlet 生命周期演示: eg: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; public class HelloServlet extends HttpServlet { //构造方法 public HelloServlet() { super(); } //初始化方法 public void init() throws ServletException { System.out.println("初始化时,init()方法被调用!"); } //doGet()方法 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("处理请求时,doGet()方法被调用。"); } //doPost()方法 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("处理请求时,doPost()方法被调用。"); } //用于释放资源 public void destroy() { super.destroy(); System.out.println("释放系统资源时,destroy()方法被调用!"); } } 分析:运行本段代码,打开浏览器,根据 web.xml 中设置的URL映射访问HelloServlet。由于HelloServlet只在控制台进行输出, 运行效果:信息:Server startup in 2449 ms 初始化时,init()方法被调用! 处理请求时,doGet()方法被调用。 从新提交一次请求,控制台显示的信息以下: 信息:Server startup in 2449 ms 初始化时,init()方法被调用! 处理请求时,doGet()方法被调用。 当再一次提交请求时, Servlet 的init()方法没有被执行,这说明 init ()方法只有在加载当前的Servlet时候被执行,而且只被执行一次。 当中止Tomcat服务,destroy()方法被执行,显示信息:释放系统资源时,destroy()方法被调用! |
七、 初始化参数及访问应用上下文:
●得到 Servlet 初始化参数: ★配置 Servlet时,能够对该 Servlet 设置初始化参数,经过初始化参数能够更灵活地控制 Servlet的运行时行为; ▲设置初始化参数须要修改 web .xml文件,在<servlet>元素中增长<init-param>元素, eg: <web-app version="3.0" <servlet> <servlet-name>HelloServlet</servlet-name <servlet-class>demo.servlet.HelloServlet</servlet-class> <init-param> <param-name>initParam</param-name> <param-value>Hello Servlet</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/HelloServlet</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>HelloServlet</welcome-file> </welcome-file-list> </web-app> 说明:定义Servlet 的初始化参数时使用<init-param>元素,<init-param>元素是<servlet>元素子元素,使用<init-param>元素必须包括<param-name>元素和 <param-value>元素;<param-name>元素定义初始化参数的名字;<param-value>元素指定初始化参数的值; |
◆初始化参数在 servlet 的初始化环节被加载,并可经过 ServletConfig 实例的 getlnitParameter (String name)方法进行访问; eg: public class HelloServlet extends HttpServlet { //构造方法 public HelloServlet() { super(); } //初始化方法 public void init() throws ServletException { System.out.println("初始化时,init()方法被调用!"); } //doGet()方法 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("处理请求时,doGet()方法被调用。"); String initParam = getInitParameter("initParam"); System.out.println(initParam); } //doPost()方法 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("处理请求时,doPost()方法被调用。"); } //用于释放资源 public void destroy() { super.destroy(); System.out.println("释放系统资源时,destroy()方法被调用!"); } } 分析:经过 GenericServlet 中定义的 getlnitParameter(String nmne) 方法获取初始化数,该方法其实是经过调用 ServletConfig 的getlnitParametcr(String name)方法来获取始化参数值,比 getServletConfig.getlnitParamater(String name)的完整写法更加简洁方便; 部署web项目并访问HelloServlet。运行进行结果如图: |
◆得到上下文参数: 为某个Servlet定义的初始化参数只能被Servlet访问,若是该参数须要被更多的Web应用组件访问,可使用上下文参数定义,要定义上下义参数一样须要对web. xml 文件进行修改; eg: <web-app version="3.0" <context-param> <param-name>contextParam</param-name> <param-value>ContextParamValue</param-value> </context-param> <!--省略其余配置--> </web-app> 说明:使用<context-param>元素声明 Web应用全局范围参数,<context-param>元素包括<param-name>元素和<param-value>元素; <param-name>素指定参数的名字 , <param-value>元素指定参数的值; |
八、 总结:
|