Servlet 详解
一、概念
1. Servlet
Servlet是server applet的缩写,译为:运行在服务器端的小程序
servlet就是一个接口,定义了java类被浏览器访问到[tomcat识别]的规则
我们可以自定义一个类,实现servlet接口,重写方法,实现逻辑
Servlet比较特殊,不需要new,自动就可以运行。也有创建、垃圾回收和销毁过程。
Servlet是JavaWeb的三大组件之一(Servlet、Filter、Listener),它属于动态资源。
Servlet的作用是处理请求,服务器会把接收到的请求交给Servlet来处理,在Servlet中通常需要:
接收请求数据
处理请求
完成响应
例如客户端发出登录请求,或者输出注册请求,这些请求都应该由Servlet来完成处理
Servlet需要我们自己来编写,每个Servlet必须实现javax.servlet.Servlet接口。Servlet对象驻留在服务器内存中。
2. servlet与servlet容器
Java Servlet(Java服务器小程序)是一个基于Java技术的Web组件,运行在服务器端,它由Servlet容器所管理,用于生成动态的内容。 Servlet是平台独立的Java类,编写一个Servlet,实际上就是按照Servlet规范编写一个Java类。Servlet被编译为平台独立 的字节码,可以被动态地加载到支持Java技术的Web服务器中运行。
Servlet容器(如 Tomcat)也叫做Servlet引擎,是Web服务器或应用程序服务器的一部分,用于在发送的请求和响应之上提供网络服务,解码基于 MIME的请求,格式化基于MIME的响应。Servlet没有main方法,不能独立运行,它必须被部署到Servlet容器中,由容器来实例化和调用 Servlet的方法(如doGet()和doPost()),Servlet容器在Servlet的生命周期内包容和管理Servlet。在JSP技术 推出后,管理和运行Servlet/JSP的容器也称为Web容器。
(注:常用的MIME类型:text/html,application/pdf,video/quicktime,application /java,image/jpeg,application/jar,application/octet-stream,application/x- zip)
有了servlet之后,用户通过单击某个链接或者直接在浏览器的地址栏中输入URL来访问Servlet,Web服务器接收到该请求后,并不是将 请求直接交给Servlet,而是交给Servlet容器。Servlet容器实例化Servlet,调用Servlet的一个特定方法对请求进行处理, 并产生一个响应。这个响应由Servlet容器返回给Web服务器,Web服务器包装这个响应,以HTTP响应的形式发送给Web浏览器。
二、简单示例
1、创建 java 工程
File >> New Project >> Java Enterprise,工程命名为 ServletTest
2、在项目根目录创建目录: web/WEB-INF
在 WEB-INF 下创建目录 classes 和 lib
点击file菜单,选择project Structure (ctrl+alt+shift+s), 把当前项目的 Paths 输出路径(Output path)改成 WEB-INF 下的 classes
3、在 src 中创建 Package : com.crs811
在包中创建类文件:HelloServlet.java,内容如下:
package com.crs811; import java.io.IOException; import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class HelloServlet implements Servlet { @Override public void init(ServletConfig config) throws ServletException { } @Override public ServletConfig getServletConfig() { return null; } @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { //IDEA控制台输出: Hello World!!! System.out.println("Hello World!!!"); PrintWriter out = servletResponse.getWriter(); out.println("<h1>hello world</h1>"); } @Override public String getServletInfo() { return null; } @Override public void destroy() { } }
4、在 WEB-INF 中新建 web.xml 文件,web.xml文件是用来初始化配置信息:比如Welcome页面、servlet、servlet-mapping、filter、listener、启动加载级别等。内容如下:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>com.crs811.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> </web-app>
5、配置 artifacts
Run >> Edit Configurations >> Deployment , 右方加号,如果没有 artifacts ,则需要添加,步骤如下
(1) 点击file菜单,选择project Structure (ctrl+alt+shift+s)
(2) 选择Modules, 找到需要部署的项目(ServletTest),右键,点击add, 找到web,点击web
(3) 选择Artifacts,然后点击+号,选择Web Application:exploded,然后选择from Modules, 选择对应的项目,点击ok即可, 添加好后,想要部署的项目就可以deployment中添加了
6、测试:
点击“运行”按钮运行项目,或在浏览器输入:http://localhost:8080/ServletTest_war_exploded/hello
则浏览器和控制台会输出 servlet 的内容:
浏览器:
控制台:
三、生命周期
首先加载servlet的class,实例化servlet,然后初始化servlet调用init()的方法,接着调用服务的service的方法,最后容器关闭时候调用destroy 销毁方法。
1.被创建:执行init方法,只执行一次
Servlet什么时候被创建?
--默认情况下,第一次被访问时,Servlet被创建,然后执行init方法;
--可以配置执行Servlet的创建时机;
2.提供服务:每个客户端请求都会执行service方法,执行多次,处理doGet和doPost方法
3.被销毁:当Servlet服务器正常关闭时,执行destroy方法,只执行一次
Servlet 调用过程详解,请点击下图看大图:
四、servlet 输出网页
在项目的包 com.crs811 中新建 WebpageServlet.java,内容如下:
package com.crs811; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/webpage") public class WebpageServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置response查询的码表 //response.setCharacterEncoding("UTF-8"); //通过一个头 Content-Type 告知客户端使用何种码表 //response.setHeader("Content-Type", "text/html;charset=UTF-8"); response.setContentType("text/html;charset=UTF-8"); PrintWriter out=response.getWriter(); out.println("<html>"); out.println("<body>"); out.println("<h1>要输入的内容.........</h1><p><font color='red'>我是红色文字</font></p>"); out.println("</body>"); out.println("</html>"); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
浏览器端输入:http://localhost:8080/ServletTest_war_exploded/webpage
可以看到,这种输出HTML页面的方式很麻烦,HTML代码和java代码混杂在一起,不便于维护
因此才使用 jsp 来将 HTML 页面和java 事务逻辑分离,因此形成了 javaweb 的 MVC结构
涉及的知识点
1、HttpServlet
广义上,Servlet 即实现了 Servlet 接口 的类,当我们创建一个自定义类,实现 Servlet 接口 的时候,会发现有 5 个方法需要重写,有init【初始化】,destroy【销毁】,service【服务】,ServletConfig【Servlet配置】,getServletInfo【Serlvet信息】。
这样做的话每次都需要实现 5 个方法,太麻烦了!
因此改进的方法是继承 HttpServlet 类,该类已经默认实现了 Servlet 接口中的所有方法,在编写 Servlet 的时候,只需要重写需要的方法就好了,并且该类还在原有 Servlet 接口上添加了一些与 HTTP 协议处理相关的方法,比 Servlet 接口的功能更强大。
Servlet 处理请求的方法一共有三种:
实现 service() 方法
重写 doGet() 和 doPost() 方法,并在 doGet() 中添加一句this.doPost(req, resp);(因为无论是get或post请求提交的数据,处理方式都基本相同,下同)
重写 doGet() 和 doPost() 方法,并在 doPost() 中添加一句this.doGet()(req, resp)
2、注解
注解是 Servlet 3.0 提出的新特性,支持注解配置,这大大简化了我们的工作。
在之前的开发工作中,我们总是去 web.xml 文件中配置servlet,至少会出现8行:
而当一个项目中存在很多 Servlet ,那么配置文件就会变得非常臃肿,不便于后期的维护
在 Servlet 3.0 推出之后,我们可以使用注解来配置 Servlet,上面 8 行的配置可以简化为一行简单的注解:@WebServlet(name="WebpageServlet", urlPatterns="/webpage")
使用urlPatterns 或 value 定义访问的 URL,只有这个属性是必要的,name 是可以缺省的值,所以可以简写成:
@WebServlet("/foreServlet")