Servlet

一、 什么是 Servlet

Java Servlet 技术是Java体系中用于开发 Web 应用的底层技术。
Servlet 是运行在 Servlet 容器(如 Tomcat)中的Java程序,而 Servlet 容器或 Servlet 引擎相当于一个 Web 服务器,但是可以产生动态内容,而不仅是静态资源。一个 Servlet 是一个 Java 程序,一个 Servlet 应用包含了一个或多个 Servlet,一个 JSP 页面会被翻译并编译成一个 Servlet。
Servlet 应用运行在一个 Servlet 容器中,它无法独立运行。Servlet 容器将来自用户的请求传递给 Servlet 应用,并将 Servlet 应用的响应返回给用户。

二、 Servlet API

Servlet API 有以下4个Java包:

  • javax.servlet:包含定义 Servlet 和 Servlet 容器之间契约的类和接口。主要包含:Servlet 接口,ServletRequest 接口,ServletResponse 接口,ServletContext 接口,ServletConfig 接口,RequestDispatcher 接口,Filter 接口,GenericServlet 类等。
  • javax.servlet.http:包含定义 HTTP Servlet 和 Servlet 容器之间契约的类和接口。
  • javax.servlet.annotation:包含用于 Servlet,filter,listener 的注解。它还为被注解元件定义元数据。
  • javax.servlet.descriptor:包含提供程序化登录 Web 应用程序配置信息的类型。

Servlet 技术的核心是 Servlet,它是所有 Servlet 类必须直接或间接实现的一个接口。
Servlet 接口定义了Servlet 与 Servlet 容器之间的契约。这个契约归结起来就是,Servlet 容器将 Servlet 类载入内存,并在 Servlet 实例上调用具体的方法。在一个应用程序中,每种 Servlet 类型只能有一个实例。

用户请求致使 Servlet 容器调用 Servlet 的 service 方法,并传入一个 ServletRequest 实例和一个 ServletResponse 实例。ServletRequest 中封装了当前的HTTP请求,ServletResponse 表示当前用户的HTTP响应。
对于每一个应用程序,Servlet 容器还会创建一个 ServletContext 实例。这个对象中封装了上下文(应用程序)的环境详情。每个上下文只有一个 ServletContext。每个 Servlet 实例也都有一个封装 Servlet 配置的 ServletConfig。

Servlet 接口中定义了以下5个方法:

public void init (ServletConfig config) throws ServletException;
public ServletConfig getServletConfig();
public void service (ServletRequest req, ServletResponse res) throws ServletException, IOException;
public String getServletInfo();
public void destroy();

3个 Servlet 生命周期方法:

  • init:当请求 Servlet 时,Servlet 容器会第一时间调用这个方法。这个方法在后续请求中不会再被调用。利用这个方法调用初始化代码。调用这个方法时,Servlet 容器会传入一个 ServletConfig。
  • service:每当请求 Servlet 时,Servlet 容器就会调用这个方法。
  • destroy:当要销毁 Servlet 时,Servlet 容器就会调用这个方法。当要卸载应用程序,或者当要关闭 Servlet 容器时,就会发生这种情况。一般会在这个方法中编写清除代码。

2个非生命周期方法:

  • getServletlnfo:这个方法会返回 Servlet 的描述。
  • getServletConfig:这个方法会返回由 Servlet 容器传给 init 方法的 ServletConfig。

三、 Hello Servlet

在 eclipse EE + Tomcat 环境下编写一个简单的 Servlet 实例

搭建环境

1. 下载 Tomcat
下载完成后解压压缩包,参考文件夹下的`RUNNIG.txt`配置环境变量。
其中`"CATALINA_HOME"`是必选项,指向 Tomcat 的根目录。
2. 将 eclipse 与 Tomcat 关联
Window->Preferences->Server->Runtime Enviroments 点击 add 选择下载的 Tomcat 版本,next 后可以选择 Tomcat 的名字,路径和 JRE 版本。Finish 完成创建。
Window->Show View->Other 可以选择 Servers 窗口查看 Tomcat,双击可以进一步配置 Tomcat,选择端口号等等。

创建项目

1. 创建一个 Dynamic Web Project 在这个页面下打勾,eclipse 会为我们自动创建一个 web.xml 文件。

2. 右键 Project,配置 Build Path,点击 add Library,选择 Server Runtime,导入 Tomcat 中的 Servlet 类库。

编写 Servlet 类

编写 Servlet 类有3种方式:

  1. 实现 Servlet 接口
  2. 继承 GenericServlet 类 (implements Servlet, ServletConfig)
  3. 继承 HttpServlet 类 (extends GenericServlet) (常用)

以实现 Servlet 接口为例,创建 HelloServlet 类

 package com.JL916;

 import java.io.IOException;
import java.io.PrintWriter; import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet; @WebServlet(name = "servlet", urlPatterns = {"/hi"})
public class HelloServlet implements Servlet {   @Override
  public void destroy() {}   @Override
  public ServletConfig getServletConfig() { return null; }   @Override
  public String getServletInfo() { return "hello"; }   @Override
  public void init(ServletConfig arg0) throws ServletException {}   @Override
  public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
    arg1.setContentType("text/html");
    PrintWriter writer = arg1.getWriter();
    writer.print("<html><head></head><body>Hello Servlet</body></html>");
  }
}

配置 Servlet

配置 Servlet 有两种方式,一种是使用注解配置,即

@WebServlet(name = "servlet", urlPatterns = {"/hi"}) 

另一种是在 web.xml 文件的 web-app 元素中添加 servlet 元素 和 servlet-mapping 元素,如下所示:

<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.JL916.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/hi</url-pattern>
</servlet-mapping>

注意:url样式必须用一个'/'开头

运行程序

在浏览器中输入 http://localhost:8080(Tomcat 端口号)/项目名称/(url-pattern)

四、 API 简介

ServletRequest

对于每一个HTTP请求,Servlet容器都会创建一个 ServletRequest 实例,并将它传给 Servlet 的 service 方法。ServletRequest 封装了关于这个请求的信息。
主要方法:

public int getContentLength();        // 返回请求主体的字节数
public String getContentType();       // 返回请求主体的MIME类型
public String getParameter(String name); // 返回指定请求参数的值 常用于返回表单的值或查询字符串的值
public String getProtocol();       // 返回请求的协议名称和版本

ServletResponse

ServletResponse 接口表示一个 Servlet 响应。在调用 Servlet 的 service 方法前,Servlet 容器首先创建一个 ServletResponse,并将它作为第2个参数传给 service 方法。

在 ServletResponse 中定义的方法之一是 getWriter 方法,它返回了一个可以向客户端发送文本的 java.io.PrintWriter。默认情况下,PrintWriter 对象使用 ISO-8859-1 编码。
在发送任何HTML标签前,应该先调用 setContentType 方法,设置响应的内容类型,并将"text/html"作为一个参数传入。

ServletConfig

当 Servlet 容器初始化 Servlet 时,Servlet 容器会给 Servlet 的 init 方法传入一个 ServletConfig。
ServletConfig 封装可以通过`@WebServlet`或者部署描述符传给 Servlet 的配置信息。这样,传入的每一条信息就叫一个初始参数。一个初始参数有 key 和 value 两个元件。
为了从 Servlet 内部获取到初始参数的值,要在 Servlet 容器传给 Servlet 的 init 方法的 ServletConfig 中调用 getlnitParameter 方法。

String getInitParameter(String name)
@WebServlet(name = "servlet", urlPatterns = {"/configtest"},
  initParams = {
    @WebInitParam(name = "admin", value = "JL916"),
    @WebInitParam(name = "email", value = "admin@example.com")
  })

ServletContext

ServletContext 表示 Servlet 应用程序。每个 Web 应用程序只有一个上下文。在将一个应用程序同时部署到多个容器的分布式环境中时,每台Java虚拟机只有一个 ServletContext 对象。 通过在 ServletConfig 中调用 getServletContext 方法,可以获得 ServletContext。
有了 ServletContext,就可以共享可以从应用程序中的所有资料处访问到的信息,并且可以动态注册 Web 对象。前者将对象保存在 ServletContext中的一个内部 Map 中。保存在ServletContext 中的对象称作属性。
ServletContext中的下列方法负责处理属性:

public Object getAttribute(String name);
public Enumeration<String> getAttributeNames();
public void setAttribute(String name, Object object);
public void removeAttribute(String name);

GenericServlet

GenericServlet 是一个抽象类,实现了 Servlet,ServletConfig,java.io.Serializable 接口,为 Servlet 接口中的除 service 外的方法提供默认实现。

// 将 config 对象保存起来
public void init(ServletConfig config) throws ServletException {
  this.config = config;
  this.init();
}
// 子类可以覆盖没有参数的 init() 方法,ServletConfig 仍然由 GenericServlet 实例保存
public void init() throws ServletException { }

javax.servlet.http

javax.servlet.http 中的许多类型覆盖了 javax.servlet 中的类型。
主要类型如下;

HttpServlet

HttpServlet 是一个抽象类,继承自 GenericServlet。
HttpServlet 实现了 service 方法,将 ServletRequest 对象和 ServletResponse 对象转换类型,再调用重载的service方法,获取 request 的 method,再分别调用 doXXX 方法,因此无需再覆盖 service 方法,只要覆盖常用的 doGet 方法和 doPost 方法即可。

@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response; if (!(req instanceof HttpServletRequest && res instanceof HttpServletResponse)) {
throw new ServletException("non-HTTP request or response");
} request = (HttpServletRequest) req;
response = (HttpServletResponse) res; service(request, response);
} protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod(); if (method.equals(METHOD_GET)) {
// ...
doGet(req, resp);
} else if (method.equals(METHOD_HEAD)) {
// ...
doHead(req, resp);
} else if (method.equals(METHOD_POST)) {
doPost(req, resp);
} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);
} else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp);
} else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp);
} else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp);
} else {
// Note that this means NO servlet supports whatever
// method was requested, anywhere on this server. // ...
resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}
HttpServletRequest 和 HttpServletResponse

HttpServletRequest 继承自 ServletRequest,新增部分方法:

public String getMethod();      // 返回生成这个请求的HTTP方法名称
public String getQueryString();   // 返回请求URL中的查询字符串
public HttpSession getSession(); // 返回与这个请求相关的会话对象 如果没有 将创建一个
public Cookie[] getCookies(); // 返回Cookie对象数组

HttpServletResponse 继承自 ServletResponse,新增部分方法:

public void addCookie(Cookie cookie);                // 添加一个Cookie
public void sendRedirect(String location) throws IOException; // 发送一条响应码 将浏览器跳转到指定位置

五、 部署描述文件(web.xml)

使用部署描述符,如果需要修改配置值,如Servlet路径,则不需要重新编译Servlet类。
此外,可以将初始参数传给一个Servlet,并且不需要重新编译Servlet类,就可以对它们进行编辑。
部署描述符还允许覆盖在 Servlet 标注中定义的值。Servlet 上的 @WebServlet 注解如果同时也在部署描述符中进行声明,那么它将不起作用。

参考资料:《Spring MVC 学习指南》 Paul Deck 著

Java Web 学习(1) —— Servlet的更多相关文章

  1. JAVA Web学习篇--Servlet

    Servlet由来 做过BS项目的人都知道,浏览器可以依据HTML静态标记语言来显示各式各样的网页.可是假设我们须要在网页上完毕一些业务逻辑:比方登陆验证.或者说网页显示的内容在server的数据库中 ...

  2. java web学习笔记 servlet

    关于java web web.xml中一般配置的都是与servlet先关的可以配置servlet filter listener context-param用来配置web应用的启动参数,可用通过Ser ...

  3. java web学习笔记-Servlet篇

    Servlet基础 1.Servlet概述 JSP的前身就是Servlet.Servlet就是在服务器端运行的一段小程序.一个Servlet就是一个Java类,并且可以通过“请求-响应”编程模型来访问 ...

  4. Java Web学习笔记-Servlet不是线程安全的

    由于Servlet只会有一个实例,多个用户同时请求同一个Servlet时,Tomcat会派生出多条线程执行Servlet的代码,因此Servlet有线程不安全的隐患.如果设计不当,系统就会出现问题. ...

  5. [原创]java WEB学习笔记11:HttpServlet(HttpServletRequest HttpServletRsponse) 以及关于 Servlet 小结

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  6. Java Web 学习路线

    实际上,如果时间安排合理的话,大概需要六个月左右,有些基础好,自学能力强的朋友,甚至在四个月左右就开始找工作了.大三的时候,我萌生了放弃本专业的念头,断断续续学 Java Web 累计一年半左右,总算 ...

  7. Java web 学习之旅

    java web学习之旅 来公司十天了,感觉已经慢慢地融入了这个环境中,几个学长人都很好,都是在他们帮助下,我才能比较顺利的开始了学习java web的旅途. 来这里学习的第一个阶段是做一个简单的用户 ...

  8. java web 学习笔记 编码问题总结

       java web 学习笔记 编码问题总结 1.非form表单中提交的中文参数---------------------------传递给Servlet服务器时,默认以iso-8859-1解码 ...

  9. Java Web学习笔记之---EL和JSTL

    Java Web学习笔记之---EL和JSTL (一)EL (1)EL作用 Expression  Language(表达式语言),目的是代替JSP页面中复杂的代码 (2)EL表达式 ${变量名} ( ...

随机推荐

  1. Linux系统在开机的时候自动启动SVN

    Linux系统在开机的时候自动启动SVN 1.创建执行脚本svn.sh(/root路径下,随便哪个路径),其内容很简单,如下: #!/bin/bash     svnserve -d --listen ...

  2. Winform组合ComboBox和TreeView实现ComboTree

    最近做Winform项目需要用到类似ComboBox的TreeView控件. 虽然各种第三方控件很多,但是存在各种版本不兼容问题.所以自己写了个简单的ComboTreeView控件. 下图是实现效果: ...

  3. 四、springBoot 优雅的创建定时任务

    前言 好几天没写了,工作有点忙,最近工作刚好做一个定时任务统计的,所以就将springboot 如何创建定时任务整理了一下. 总的来说,springboot创建定时任务是非常简单的,不用像spring ...

  4. 怎样用手机把视频变成GIF表情包?原来那么简单,网友:看完涨知识了

    现如今表情包几乎成了,我们手机聊天的必需品了.不过相比于普通表情包,大家更喜欢用GIF表情包,因为动图表情包不仅更加搞笑,而且能更形象的表达我们的情绪.比较有想法的朋友甚至想自己制作GIF表情包,但是 ...

  5. flask+layui+echarts实现前端动态图展示数据

    效果图: 该效果主要实现一个table展示数据,并在下方生成一个折线图. 实现方式: 1.首先需要对表格进行一个数据加载,这里用到了layui的table.render,具体用法可以参考 https: ...

  6. zookeeper 都有哪些使用场景?

    面试题 zookeeper 都有哪些使用场景? 面试官心理分析 现在聊的 topic 是分布式系统,面试官跟你聊完了 dubbo 相关的一些问题之后,已经确认你对分布式服务框架/RPC框架基本都有一些 ...

  7. j2ee开发之struts2框架学习笔记

    Struts2框架技术重点笔记 1.Struts2 是在webwork基础上发展而来. 2.Struts2 不依赖struts API和 servlet API 3.Struts2提供了拦截器,表现层 ...

  8. Windows Terminal 安装及美化

    windows terminal 是今年微软Build大会上推出的一款的全新终端,用来代替cmder之类的第三方终端.具有亚克力透明.多标签.Unicode支持(中文,Emoji).自带等宽字体等这些 ...

  9. .Net Core自动化部署系列(三):使用GitLab CI/CD 自动部署Api到Docker

    之前写过使用Jenkins实现自动化部署,最近正好没事研究了下GitLab的自动化部署,顺便记录一下. 使用GitLab部署我们需要准备两件事,第一个起码你得有个GitLab,自己搭建或者使用官方的都 ...

  10. 【Sqlserver】查询结果导出excel

    1.右键数据库——>任务——>导出数据,打开SQL Server导入和导出向导: 2.选择当前数据库,填写用户名,密码,下一步: 3.选择目标类型 excel,选择导出模板,下一步: 4. ...