Java Web 学习与总结(一)Servlet基础
配置环境:https://www.cnblogs.com/qq965921539/p/9821374.html
简介:
Servlet是Sun公司提供的一种实现动态网页的解决方案,在制定J2EE时引入它作为实现了基于Java语言的动态技术,目前流行的Web框架基本都基于Servlet技术,只有掌握了Servlet,才能真正掌握Java Web编程的核心和精髓。
Servlet是运行在Servlet容器中的Java类,它能处理Web客户的HTTP请求,并产生HTTP响应。
Servlet对请求的处理和响应过程可进一步细分为以下几个步骤:
1.接收HTTP请求
2.取得请求信息,包括请求头和请求参数数据
3.调用其它Java类方法,完成具体的业务功能
4.实现到其他Web组件的跳转(包括重定向或请求转发)
5.生成HTTP响应(包括HTML或非HTML响应)
优点:
Servlet有以下几个优点:
1.高效,在Servlet中,每个请求由一个轻量级的java线程处理;
2.方便,提供了大量实用工具例程,这个在后面会慢慢叙述;
3.功能强大,继承了Java的优点,能够直接和Web服务器交互,还能够在各个程序之间共享数据;
4.可移植性好,Servlet由Java语言编写,并且其API具有完善的标准,支持Servlet规范的容器都可以运行Servlet程序,如Tomcat和Resin等。
Servlet体系结构:
Servlet是使用Servlet API及相关类和方法的Java程序,Servlet API包含两个软件包:
javax.servlet包:包含支持所有协议的通用的Web组件接口和类,如ServletRequest接口,ServletResponse接口
javax.servlet.http包:包含支持HTTP协议的接口和类,如HttpServletRequest接口,HttpServletResponse接口
Servet API的主要接口和类之间的关系为:
Servlet接口:
所有的Servlet都必须直接或间接地实现javax.servlet.Servlet接口。Servlet接口规定了必须由Servlet类实现并且由Servlet引擎识别和管理的方法集。Servlet接口的基本目标是提供与Servlet生命周期相关的方法,如init(),service()和destory()等,下述示例为Servlet接口的源代码:
package javax.servlet; import java.io.IOException; public interface Servlet {
void init(ServletConfig var1) throws ServletException; ServletConfig getServletConfig(); void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException; String getServletInfo(); void destroy();
}
1.init(),初始化servlet对象,Servlet实例化后,容器调用该方法进行初始化工作。ServletAPI规定该方法只能被调用一次,如果此方法没有正常结束就会抛出一个ServletException异常,一旦抛出该异常,Servlet将不再执行。
2.service(ServletRequest var1, ServletResponse var2),接受客户端请求对象,执行业务操作,利用响应对象响应客户端请求。
3.destroy(),当容器监测到一个servlet从服务中被移除时,容器调用该方法,释放资源,调用该方法前必须给service()足够时间来结束执行。
4.getServletConfig(),ServletConfig是容器向servlet传递参数的载体,此方法可以让Servlet在任何时候获得ServletConfig对象。
5.getServletInfo(),返回一个String对象获取servlet相关信息。
GenericServlet类:
GenericServlet类是一个抽象类,是Servlet接口的直接实现,除service()方法之外还提供了其他有关Servlet生命周期的方法。这意味着只需通过简单地扩展GenericServlet和实现servlet方法就可以编写一个基本的Servlet。
package javax.servlet; import java.io.IOException;
import java.io.Serializable;
import java.util.Enumeration; public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
private static final long serialVersionUID = 1L;
private transient ServletConfig config; public GenericServlet() {
} public void destroy() {
} public String getInitParameter(String name) {
return this.getServletConfig().getInitParameter(name);
} public Enumeration<String> getInitParameterNames() {
return this.getServletConfig().getInitParameterNames();
} public ServletConfig getServletConfig() {
return this.config;
} public ServletContext getServletContext() {
return this.getServletConfig().getServletContext();
} public String getServletInfo() {
return "";
} public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
} public void init() throws ServletException {
} public void log(String msg) {
this.getServletContext().log(this.getServletName() + ": " + msg);
} public void log(String message, Throwable t) {
this.getServletContext().log(this.getServletName() + ": " + message, t);
} public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException; public String getServletName() {
return this.config.getServletName();
}
}
init(ServletConfig config:该方法来源于Servlet接口,覆写该方法,必须调用super.init(config)
init():该方法重载Servlet.init(ServletConfig config)方法而无需调用super.init(config)。而ServletConfig对象依然可以通过调用getServletConfig()方法获得。
destory()方法作用与Servlet接口中的方法相同,略。
getInitParameter():返回一个包含初始化变量的值的字符串,如果变量不存在则返回null,该方法从servlet的ServletConfig变量获得命名变量的值。
getInitParameterNames():该方法返回一个包含所有初始化变量的枚举函数。如果没有初始化变量,则返回一个空枚举函数。
getServletConfig():返回一个servlet的ServletConfig对象getServletContext()方法与ServletConfig.getServletContext()相同,略。
getServletInfo():该方法来源于Servlet接口,覆写该方法以产生有意义的信息。(如:版本号、版权、作者等)
log(java.lang.String msg):public void log(java.lang.String msg)该方法把指定的信息写入一个日志文件,见ServletContext.log(String)。
log(java.lang.String message,java.lang.Throwable t):public void log(java.lang.String message,java.lang.Throwable t) 该方法把解释性的内容和抛出的例外信息写入一个日志文件。
service():这是一个抽象的方法,当为执行网络请求继承GenericServlet类时必须实现它,该方法必须由servlet容器调用以允许servlet 对请求作出响应。见Servlet.service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)。
getServletName():见ServletConfig.getServletName()。
HttpServlet类:
这个是重点啦(拍桌子)!HttpServlet类扩展了GenericServlet类并且对Servlet接口提供了与HTTP相关的实现,是在Web开发中定义Servlet最常使用的类。HttpServlet类中的主要方法的源代码如下所示:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
// package javax.servlet.http; import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.ResourceBundle;
import javax.servlet.DispatcherType;
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 long serialVersionUID = 1L;
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 final ResourceBundle lStrings = ResourceBundle.getBundle("javax.servlet.http.LocalStrings"); public HttpServlet() {
} 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(405, msg);
} else {
resp.sendError(400, msg);
} } protected long getLastModified(HttpServletRequest req) {
return -1L;
} protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
if (DispatcherType.INCLUDE.equals(req.getDispatcherType())) {
this.doGet(req, resp);
} else {
NoBodyResponse response = new NoBodyResponse(resp);
this.doGet(req, response);
response.setContentLength();
} } 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(405, msg);
} else {
resp.sendError(400, msg);
} } 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(405, msg);
} else {
resp.sendError(400, msg);
} } 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(405, msg);
} else {
resp.sendError(400, msg);
} } private static Method[] getAllDeclaredMethods(Class<?> c) {
if (c.equals(HttpServlet.class)) {
return null;
} else {
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;
Class clazz = null; try {
clazz = Class.forName("org.apache.catalina.connector.RequestFacade");
Method getAllowTrace = clazz.getMethod("getAllowTrace", (Class[])null);
ALLOW_TRACE = (Boolean)getAllowTrace.invoke(req, (Object[])null);
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | ClassNotFoundException var14) {
;
} 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 = "GET";
} if (ALLOW_HEAD) {
if (allow == null) {
allow = "HEAD";
} else {
allow = allow + ", HEAD";
}
} if (ALLOW_POST) {
if (allow == null) {
allow = "POST";
} else {
allow = allow + ", POST";
}
} if (ALLOW_PUT) {
if (allow == null) {
allow = "PUT";
} else {
allow = allow + ", PUT";
}
} if (ALLOW_DELETE) {
if (allow == null) {
allow = "DELETE";
} else {
allow = allow + ", DELETE";
}
} if (ALLOW_TRACE) {
if (allow == null) {
allow = "TRACE";
} else {
allow = allow + ", TRACE";
}
} if (ALLOW_OPTIONS) {
if (allow == null) {
allow = "OPTIONS";
} else {
allow = allow + ", OPTIONS";
}
} resp.setHeader("Allow", allow);
} protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String CRLF = "\r\n";
StringBuilder buffer = (new StringBuilder("TRACE ")).append(req.getRequestURI()).append(" ").append(req.getProtocol());
Enumeration reqHeaderEnum = req.getHeaderNames(); while(reqHeaderEnum.hasMoreElements()) {
String headerName = (String)reqHeaderEnum.nextElement();
buffer.append(CRLF).append(headerName).append(": ").append(req.getHeader(headerName));
} buffer.append(CRLF);
int responseLength = buffer.length();
resp.setContentType("message/http");
resp.setContentLength(responseLength);
ServletOutputStream out = resp.getOutputStream();
out.print(buffer.toString());
out.close();
} protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
long lastModified;
if (method.equals("GET")) {
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
this.doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader("If-Modified-Since");
} catch (IllegalArgumentException var9) {
ifModifiedSince = -1L;
} if (ifModifiedSince < lastModified / 1000L * 1000L) {
this.maybeSetLastModified(resp, lastModified);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("HEAD")) {
lastModified = this.getLastModified(req);
this.maybeSetLastModified(resp, lastModified);
this.doHead(req, resp);
} else if (method.equals("POST")) {
this.doPost(req, resp);
} else if (method.equals("PUT")) {
this.doPut(req, resp);
} else if (method.equals("DELETE")) {
this.doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
this.doOptions(req, resp);
} else if (method.equals("TRACE")) {
this.doTrace(req, resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{method};
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
} } private void maybeSetLastModified(HttpServletResponse resp, long lastModified) {
if (!resp.containsHeader("Last-Modified")) {
if (lastModified >= 0L) {
resp.setDateHeader("Last-Modified", lastModified);
} }
} public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest)req;
response = (HttpServletResponse)res;
} catch (ClassCastException var6) {
throw new ServletException("non-HTTP request or response");
} this.service(request, response);
}
}
HttpServlet虽然看起来很长,但由于前两个类的结构已趋于完善,主要方法也不多:
service(ServletRequest req, ServletResponse res):HttpServlet在实现Servlet接口时,重写了service()方法,该方法会自动判断用户的请求方式:若为GET请求,则调用doGet()方法,若为POST请求,则调用doPost方法。如果Servlet收到一个HTTP请求而没有重载相应的do方法,它就返回一个说明此方法对本资源不可用的标准HTTP错误
doGet(ServletRequest req, ServletResponse res):被本类的service方法调用,用来处理一个HTTP GET请求
doPost(ServletRequest req, ServletResponse res):被本类的service方法调用,用来处理一个HTTP POST请求
HttpServlet作为HTTP请求的分发器,除了提供对GET和POST请求的处理方法doGet()和doPost()之外,对于其他请求类型如HEAD,OPTIONS,DELETE,PUT,TRACE也提供了相应的处理方法,如doHead(),doOptions等等
HttpServlet指能够处理HTTP请求的Servlet,开发人员在编写Servlet时,通常应继承这个类,而避免去直接实现Servlet接口
下面是一个正常能够处理请求的Servlet基本结构,我们在后面也主要使用这种结构:
package com.Servlet; import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; @WebServlet(name = "SimpleServlet")
public class SimpleServlet extends HttpServlet {
public SimpleServlet(){
super();
} public void init(ServletConfig servletConfig) throws ServletException{
//初始化方法
} public void destroy() {
//销毁方法
} protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//处理POST请求时调用的方法
} protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//处理GET请求时调用的方法
}
}
Servlet生命周期:
Servlet生命周期有七种状态:创捷,初始化,服务可用,服务不可用,处理请求,终止服务,销毁
根据七种状态可以又分为四个阶段:
1.加载和实例化:在服务器运行中,客户机首次向Servlet发出请求时或者再重新装入Servlet时(如服务器重新启动,Servlet被修改)或配置了自动装入选项时(load-on-startup),服务器在启动时会自动装入此Servlet
2.初始化:调用上面方法中的init(ServletConfig config)来对Servlet实例进行初始化,成功时进入服务可用状态,失败时Servlet容器会从运行环境中清除掉该实例,运行出现异常时进入服务不可用状态,维护人员也可以设置不可用状态或从不可用变成可用
3.处理请求:服务器收到客户端请求时会为该请求创建一个“请求”对象和一个相应对象并调用service()方法,service()方法可能被多次调用,多个客户端访问某个Servlet的service方法时,服务器会为每个请求创建一个线程来减少等待时间
4.销毁:当Servlet容器需要终止Servlet时,它会先调用destroy()方法来释放资源,调用该方法前必须让所有service()的线程完成实行,该方法完成后,Servlet容器必须释放该实例以便被垃圾回收
时序图:
Java Web 学习与总结(一)Servlet基础的更多相关文章
- [原创]java WEB学习笔记04:Servlet 简介及第一个Servlet程序(配置注册servlet,生命周期)
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...
- java web学习总结(九) -------------------通过Servlet生成验证码图片
一.BufferedImage类介绍 生成验证码图片主要用到了一个BufferedImage类,如下:
- [原创]java WEB学习笔记47:Servlet 监听器简介, ServletContext(Application 对象), HttpSession (Session 对象), HttpServletRequest (request 对象) 监听器,利用listener理解 三个对象的生命周期
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...
- [原创]java WEB学习笔记05:Servlet中的ServletConfig对象
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...
- java web学习总结(十五) -------------------JSP基础语法
任何语言都有自己的语法,JAVA中有,JSP虽然是在JAVA上的一种应用,但是依然有其自己扩充的语法,而且在JSP中,所有的JAVA语句都可以使用. 一.JSP模版元素 JSP页面中的HTML内容称之 ...
- java web 学习十五(jsp基础语法)
任何语言都有自己的语法,JAVA中有,JSP虽然是在JAVA上的一种应用,但是依然有其自己扩充的语法,而且在JSP中,所有的JAVA语句都可以使用. 一.JSP模版元素 JSP页面中的HTML内容称之 ...
- java web 学习九(通过servlet生成验证码图片)
一.BufferedImage类介绍 生成验证码图片主要用到了一个BufferedImage类,如下:
- [原创]java WEB学习笔记11:HttpServlet(HttpServletRequest HttpServletRsponse) 以及关于 Servlet 小结
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...
- Java Web 学习路线
实际上,如果时间安排合理的话,大概需要六个月左右,有些基础好,自学能力强的朋友,甚至在四个月左右就开始找工作了.大三的时候,我萌生了放弃本专业的念头,断断续续学 Java Web 累计一年半左右,总算 ...
- Java web 学习之旅
java web学习之旅 来公司十天了,感觉已经慢慢地融入了这个环境中,几个学长人都很好,都是在他们帮助下,我才能比较顺利的开始了学习java web的旅途. 来这里学习的第一个阶段是做一个简单的用户 ...
随机推荐
- javascript中所谓的“坑”收录
坑一: // 反例myname = "global"; // 全局变量function func() { alert(myname); // "undefined&quo ...
- LeetCode之链表
2. Add Two Numbers You are given two linked lists representing two non-negative numbers. The digits ...
- The Process of Google Hiring
[The Process of Google Hiring] 1.keynote 1: The Google hiring process is designed to hire the most t ...
- 64 位 win7 使用PLSQL Developer(转)
由于 PLSQL Developer 没有64位版本,所以在64位系统上运行该程链接64位Oracle时就会报错,笔者为这个问题纠结了好几天,后来通过请教Google + 动手实践,终于搞定了这个问题 ...
- 第4章 类与对象 UML简介
- 【bzoj1087】互不侵犯King 状态压缩dp
AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1087 [题解] 用f[i][j][k]表示前i行放了j个棋子且第i行的状态为k的方案数. ...
- 通过curl模拟多线程抓取网页(curl_multi_*)
curl请求多个url,以前都是使用循环来处理.最近发现可以通过curl_multi_*系列函数来模拟多线程.比对一下,发现如果请求的url只有几个,2种方案耗时差不多,但是url比较多,差距就非常明 ...
- ant的hello world很好的官方文档[z]
http://ant.apache.org/manual/tutorial-HelloWorldWithAnt.html
- 理解数据库中的undo日志、redo日志、检查点
数据库存放数据的文件,本文称其为data file. 数据库的内容在内存里是有缓存的,这里命名为db buffer.某次操作,我们取了数据库某表格中的数据,这个数据会在内存中缓存一些时间.对这个数据的 ...
- advance shading--光源的类型
我们这里讨论的光源类型都有一个相同点,就是,我们考量的都是光源上的一个点,对于物体表面上一个点的影响,也就是说立体角趋近为零的情况. 这里光源分为两类,一类是方向光,假设光源在无限远处.另一类是点光源 ...