说明

本篇介绍java web中比较重要的一个技术:servlet。servlet是一种对用户请求动态响应的一个技术,是java web的核心一环。对于一般服务性质的纯后台服务应用而言,或许整个应用是由若干个servlet组成

,而其他方面表现较弱。

servlet

一般的我们的应用都会发布到一个服务应用中,即一个servlet容器中,常见的servlet容器有:Tomcat,JBoss,WebLogic等。我们通过servlet容器处理用户请求,当用户向我们的某个servlet发起请求时,servlet容器会调用并转发请求结果到该servlet,同时会将servlet返回结果回馈给请求方(用户)。其实,servlet本质就是一个接口,我们可以通过注册servlet服务,实现servlet接口,用于监听各种状态先的信息交互。如下,仅仅介绍tomcat中的servlet的相关使用(主要是其他也没用过)。

Tomcat中为servlet的使用提供了一个调用的jar包:sevlet-api.jar ,该jar包位于Tomcat根目录的lib目录下(所有和Tomcat相关的Jar包均放在这里),如下为servlet-api.jar中的包信息:

servlet-api.jar
--javax.servlet //核心
--javax.servlet.annotation
--javax.servlet.descriptor
--javax.servlet.http //基于http的实现

可以看到,这里主要石油javax.servlet和javax.servlet.http两个包组成实现。其中javax.servlet.Servlet接口为api的核心,servlet容器通过调用其定义方法,实现网络中客户端和服务端之前通信的中转传递,Servlet提供了五个方法,其中三个方法是由servlet容器调用。如下,servlet的源码:



package javax.servlet;

import java.io.IOException;

public interface Servlet {
/**
*由sevler容器调用,servlet对象初始化后,servlet容器调用此方法
*
*/
public void init(ServletConfig config) throws ServletException; /**
*提供的一个获取ServletConfig对象的方法,该方法由我们自己实现,返回的对象即是init
*的方法传入的参数。
*
*/
public ServletConfig getServletConfig(); /**
*该方法需要在init方法成功调用后才可正常调用(即客户端请求的时候必须姚该servlet以及
*初始化成功)
*
*/
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException; /**
*返回当前servlet的创建信息包括创建者等(为一个String字串)
*
*/
public String getServletInfo(); /**
*由servlet容器调用,当一个servlet容器被销毁时调用,可以用于清理销毁servlet中的占
*用的一些资源。
*
*/
public void destroy();
}

Servlet接口为最基础的Servlet组件,可供我们最大限度的对servlet进行定制.servlet-api.jar中也为我们提供了它的两个替代实现:一个是javax.servlet.GenericServlet是其实现类,完成它的最基础的一些逻辑实现,但保留其对于网络通信的处理,交由我们自行处理;另一个是javax.servlet.http.HttpServlet,该类是GenericServlet的子类,是对GenericServlet的一种扩展,其对于Servlet的servive方法进行了处理,主要用于Http请求。如下,给出这两个类的实现源码:

  1. GenericServlet

该抽象类并未对servive方法作处理。

public abstract class GenericServlet implements Servlet, ServletConfig,
java.io.Serializable{ private static final String LSTRING_FILE = "javax.servlet.LocalStrings";
private static ResourceBundle lStrings =
ResourceBundle.getBundle(LSTRING_FILE); private transient ServletConfig config; public GenericServlet() { } /**
*销毁方法
*/
public void destroy() {
} /**
*获取servlet初始化传入参数
*
*/
public String getInitParameter(String name) {
ServletConfig sc = getServletConfig();
if (sc == null) {
throw new IllegalStateException(
lStrings.getString("err.servlet_config_not_initialized"));
} return sc.getInitParameter(name);
} /**
*servlet参数参数名获取
*/
public Enumeration<String> getInitParameterNames() {
ServletConfig sc = getServletConfig();
if (sc == null) {
throw new IllegalStateException(
lStrings.getString("err.servlet_config_not_initialized"));
} return sc.getInitParameterNames();
} /**
*实现Servlet方法返回初始化获取的ServletConfig对象
*/
public ServletConfig getServletConfig() {
return config;
} /**
*获取ServletContext对象(Servlet上下文),是在ServletConfig中获取
*/
public ServletContext getServletContext() {
ServletConfig sc = getServletConfig();
if (sc == null) {
throw new IllegalStateException(
lStrings.getString("err.servlet_config_not_initialized"));
} return sc.getServletContext();
} public String getServletInfo() {
return "";
} /**
*实现Servlet初始化方法,并回调init()无参方法,可供实现者监听状态.
*
*
*/
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
} /**
* 子类可通过重写监听Servlet对象初始化状态.
*/
public void init() throws ServletException { } public void log(String msg) {
getServletContext().log(getServletName() + ": "+ msg);
} public void log(String message, Throwable t) {
getServletContext().log(getServletName() + ": " + message, t);
} public abstract void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException; public String getServletName() {
ServletConfig sc = getServletConfig();
if (sc == null) {
throw new IllegalStateException(
lStrings.getString("err.servlet_config_not_initialized"));
} return sc.getServletName();
}
}
  1. HttpServlet

是GenericServlet的子类,对service添加了Http的处理,一般适用于Http通信的Servlet,是较为常用的一种Servlet.

package javax.servlet.http;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.Locale;
import java.util.ResourceBundle; import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; public abstract class HttpServlet extends GenericServlet{
private static final String METHOD_DELETE = "DELETE";
private static final String METHOD_HEAD = "HEAD";
private static final String METHOD_GET = "GET";
private static final String METHOD_OPTIONS = "OPTIONS";
private static final String METHOD_POST = "POST";
private static final String METHOD_PUT = "PUT";
private static final String METHOD_TRACE = "TRACE"; private static final String HEADER_IFMODSINCE = "If-Modified-Since";
private static final String HEADER_LASTMOD = "Last-Modified"; private static final String LSTRING_FILE =
"javax.servlet.http.LocalStrings";
private static ResourceBundle lStrings =
ResourceBundle.getBundle(LSTRING_FILE); public HttpServlet() { } /**
*Http协议Get方式请求回调
*
*/
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException{
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_get_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
}
} protected long getLastModified(HttpServletRequest req) {
return -1;
} /**
*Http协议HHEAD(只请求页面的头部)方式请求回调
*/
protected void doHead(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
NoBodyResponse response = new NoBodyResponse(resp); doGet(req, response);
response.setContentLength();
} /**
*Http协议POST方式请求回调
*/
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_post_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
}
} /**
*Http协议Put方式请求回调
*/
protected void doPut(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_put_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
}
} /**
*Http协议Delete方式请求回调
*/
protected void doDelete(HttpServletRequest req,
HttpServletResponse resp)
throws ServletException, IOException
{
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_delete_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
}
} private Method[] getAllDeclaredMethods(Class<?> c) { if (c.equals(javax.servlet.http.HttpServlet.class)) {
return null;
} Method[] parentMethods = getAllDeclaredMethods(c.getSuperclass());
Method[] thisMethods = c.getDeclaredMethods(); if ((parentMethods != null) && (parentMethods.length > 0)) {
Method[] allMethods =
new Method[parentMethods.length + thisMethods.length];
System.arraycopy(parentMethods, 0, allMethods, 0,
parentMethods.length);
System.arraycopy(thisMethods, 0, allMethods, parentMethods.length,
thisMethods.length); thisMethods = allMethods;
} return thisMethods;
} protected void doOptions(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
Method[] methods = getAllDeclaredMethods(this.getClass()); boolean ALLOW_GET = false;
boolean ALLOW_HEAD = false;
boolean ALLOW_POST = false;
boolean ALLOW_PUT = false;
boolean ALLOW_DELETE = false;
boolean ALLOW_TRACE = true;
boolean ALLOW_OPTIONS = true; for (int i=0; i<methods.length; i++) {
Method m = methods[i]; if (m.getName().equals("doGet")) {
ALLOW_GET = true;
ALLOW_HEAD = true;
}
if (m.getName().equals("doPost"))
ALLOW_POST = true;
if (m.getName().equals("doPut"))
ALLOW_PUT = true;
if (m.getName().equals("doDelete"))
ALLOW_DELETE = true; } String allow = null;
if (ALLOW_GET)
allow=METHOD_GET;
if (ALLOW_HEAD)
if (allow==null) allow=METHOD_HEAD;
else allow += ", " + METHOD_HEAD;
if (ALLOW_POST)
if (allow==null) allow=METHOD_POST;
else allow += ", " + METHOD_POST;
if (ALLOW_PUT)
if (allow==null) allow=METHOD_PUT;
else allow += ", " + METHOD_PUT;
if (ALLOW_DELETE)
if (allow==null) allow=METHOD_DELETE;
else allow += ", " + METHOD_DELETE;
if (ALLOW_TRACE)
if (allow==null) allow=METHOD_TRACE;
else allow += ", " + METHOD_TRACE;
if (ALLOW_OPTIONS)
if (allow==null) allow=METHOD_OPTIONS;
else allow += ", " + METHOD_OPTIONS; resp.setHeader("Allow", allow);
} /**
*处理TRACE请求
*/
protected void doTrace(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{ int responseLength; String CRLF = "\r\n";
StringBuilder buffer = new StringBuilder("TRACE ").append(req.getRequestURI())
.append(" ").append(req.getProtocol()); Enumeration<String> reqHeaderEnum = req.getHeaderNames(); while( reqHeaderEnum.hasMoreElements() ) {
String headerName = reqHeaderEnum.nextElement();
buffer.append(CRLF).append(headerName).append(": ")
.append(req.getHeader(headerName));
} buffer.append(CRLF); responseLength = buffer.length(); resp.setContentType("message/http");
resp.setContentLength(responseLength);
ServletOutputStream out = resp.getOutputStream();
out.print(buffer.toString());
} /**
*http协议处理
*/
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String method = req.getMethod(); if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
if (lastModified == -1) {
// servlet doesn't support if-modified-since, no reason
// to go through further expensive logic
doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
if (ifModifiedSince < lastModified) {
// If the servlet mod time is later, call doGet()
// Round down to the nearest second for a proper compare
// A ifModifiedSince of -1 will always be less
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
}
} } else if (method.equals(METHOD_HEAD)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
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.
// String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
} private void maybeSetLastModified(HttpServletResponse resp,
long lastModified) {
if (resp.containsHeader(HEADER_LASTMOD))
return;
if (lastModified >= 0)
resp.setDateHeader(HEADER_LASTMOD, lastModified);
} /**
*重写父类方法,转化为http协议处理,调用自有http处理
*/
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);
}
} // file private
class NoBodyResponse extends HttpServletResponseWrapper { private static final ResourceBundle lStrings
= ResourceBundle.getBundle("javax.servlet.http.LocalStrings"); private NoBodyOutputStream noBody;
private PrintWriter writer;
private boolean didSetContentLength;
private boolean usingOutputStream; // file private
NoBodyResponse(HttpServletResponse r) {
super(r);
noBody = new NoBodyOutputStream();
} // file private
void setContentLength() {
if (!didSetContentLength) {
if (writer != null) {
writer.flush();
}
setContentLength(noBody.getContentLength());
}
} public void setContentLength(int len) {
super.setContentLength(len);
didSetContentLength = true;
} public ServletOutputStream getOutputStream() throws IOException { if (writer != null) {
throw new IllegalStateException(
lStrings.getString("err.ise.getOutputStream"));
}
usingOutputStream = true; return noBody;
} public PrintWriter getWriter() throws UnsupportedEncodingException { if (usingOutputStream) {
throw new IllegalStateException(
lStrings.getString("err.ise.getWriter"));
} if (writer == null) {
OutputStreamWriter w = new OutputStreamWriter(
noBody, getCharacterEncoding());
writer = new PrintWriter(w);
} return writer;
}
} /*
* Servlet output stream that gobbles up all its data.
*/
// file private
class NoBodyOutputStream extends ServletOutputStream { private static final String LSTRING_FILE =
"javax.servlet.http.LocalStrings";
private static ResourceBundle lStrings =
ResourceBundle.getBundle(LSTRING_FILE); private int contentLength = 0; // file private
NoBodyOutputStream() {} // file private
int getContentLength() {
return contentLength;
} public void write(int b) {
contentLength++;
} public void write(byte buf[], int offset, int len)
throws IOException
{
if (len >= 0) {
contentLength += len;
} else {
// This should have thrown an IllegalArgumentException, but
// changing this would break backwards compatibility
throw new IOException(lStrings.getString("err.io.negativelength"));
}
}
}

如上,Servlet对于用户的请求获取和返回主要是通过方法:

public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;

实现的。这里,servlet容器在调用时传入两个参数:一个ServletRequest对象,用于接收用户请求信息;一个ServletResponse对象,用于返回请求用户信息。而HttpServlet对于对象则更改为HttpServletRequest和HttpServletResponse对象。其实这两个接口是同样在对应的ServletRequest和ServletResponse接口的基础上扩展的。

Enjoytoday,EnjoyCoding

Servlet 使用介绍(1)的更多相关文章

  1. servlet简单介绍

    什么是Servlet? servlet是一种Java编程语言类,用于扩展托管通过请求 - 响应编程模型访问的应用程序的服务器的功能.尽管servlet可以响应任何类型的请求,但它们通常用于扩展Web服 ...

  2. Servlet过滤器介绍之原理分析

    zhangjunhd 的BLOG     写留言去学院学习发消息 加友情链接进家园 加好友 博客统计信息 51CTO博客之星 用户名:zhangjunhd 文章数:110 评论数:858 访问量:19 ...

  3. Introducation of Servlet filter(servlet过滤器介绍 )

    本文章向大家介绍Servlet Filter,主要包括 Servlet Filter使用实例.应用技巧.基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下. 过滤器是一个可以转换 ...

  4. Servlet 使用介绍(2)

    说明 本篇由于介绍Servlet容器回传请求方法service(ServletRequest req, ServletResponse res);传入参数用户请求参数request和请求返回参数res ...

  5. 10.Servlet简单介绍

    1.什么是Servlet * Servlet是javaweb的三大组件之一,它属于动态资源.Servlet的作用是处理请求,服务器会把接收到的请求交给Servlet来处理,在Servlet种通常需要: ...

  6. J2EE的13个规范之(三) Servlet简单介绍

    Servlet是一种server端脚本,它是一个特殊的Java类,继承自HttpServlet.开发中主要用于处理和响应client的请求. Servlet在容器中执行,事实上例的和销毁创建由容器进行 ...

  7. Servlet基本介绍和使用

    基本概念 Servlet又称为Java Servlet是一个基于java技术的web组件,运行在服务器端,用于生成动态的内容.Servlet是平台独立的java类,编写一个Servlet实际上就是按照 ...

  8. Servlet 简单介绍

    来源于菜鸟教程http://www.runoob.com/servlet/servlet-intro.html Servlet 简介 Servlet 是什么? Servlet(Server Apple ...

  9. 一、动态网络编程的概念 二、Tomcat服务器搭建 三、Servlet组件介绍

    一.动态网络编程的概念 动态网页:结合了HTML以外的高级程序编程语言和数据库技术生成的页面. 动态网页编程技术: ASP,PHP,JSP HTTP协议:规范浏览器和服务器之间通信的数据格式. 浏览器 ...

随机推荐

  1. B树概述与简单应用示例(C#)

    引言: 天不生仲尼,万古如长夜.在计算机科学中,也有一个划时代的发明,B树(多路平衡查找树)及其变体(B树,b*树,b+树): 由德国科学家(鲁道夫·拜尔 Rudolf Bayer),美国科学家(爱德 ...

  2. vue/cli 3 引入 使用jQuery

    注意这里配置的是vue-cli3.0引入jquery的方法,不是vue-cli2.0的配置方法 一.安装jquery npm install jquery --save 二.一般安装成功后在packa ...

  3. OWASP ModSecurity Core Rule Set (CRS)的基本使用

    Preface 前述文章开源WAF工具ModSecurity,介绍了ModSecurity作为Nginx的动态加载模块的基本安装和使用. 本篇简单介绍ModSecurity CRS规则集的使用. # ...

  4. jQuery实现回车触发登录按钮的功能

    jQuery实现回车触发登录按钮的功能,代码如下: $('body').keyup(function(e){ if(e.keyCode===13){ $('.login').click() } }) ...

  5. java---时间戳

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss" );// 格式化时间Date date = ne ...

  6. LATEX Mathematical Symbols

    原文地址:https://www.caam.rice.edu/~heinken/latex/symbols.pdf

  7. MySQL的数据库定义语法

    创建数据库 在MySQL中,使用 CREATE DATABASE 或 CREATE SCHEMA 语句创建数据库 语法结构: CREATE {DATABASE|SCHEMA}[IF NOT EXIST ...

  8. 构建Electron的常见问题(Mac)

    背景 起因是产品的需求,需要更换Electron为底层平台,但因为会有不少定制化的功能要实现,必须自己实现此类内容,所以也就导致必须自己编译Electron的源代码. 整个构建过程,看Electron ...

  9. XTTS Creates Alias on Destination when Source and Destination use ASM (Doc ID 2351123.1)

    XTTS Creates Alias on Destination when Source and Destination use ASM (Doc ID 2351123.1) APPLIES TO: ...

  10. [MySQL] 使用force index强制使用索引

    1.在测试一个按照时间的范围查询时,尽管增加了索引,发现使用不到索引,可以使用这个来强制使用索引 测试过程为,创建下面的表,以及创建了联合索引 create table delay_delete_us ...