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接口的源代码:
1 package javax.servlet; 2 3 import java.io.IOException; 4 5 public interface Servlet { 6 void init(ServletConfig var1) throws ServletException; 7 8 ServletConfig getServletConfig(); 9 10 void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException; 11 12 String getServletInfo(); 13 14 void destroy(); 15 }
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。
1 package javax.servlet; 2 3 import java.io.IOException; 4 import java.io.Serializable; 5 import java.util.Enumeration; 6 7 public abstract class GenericServlet implements Servlet, ServletConfig, Serializable { 8 private static final long serialVersionUID = 1L; 9 private transient ServletConfig config; 10 11 public GenericServlet() { 12 } 13 14 public void destroy() { 15 } 16 17 public String getInitParameter(String name) { 18 return this.getServletConfig().getInitParameter(name); 19 } 20 21 public Enumeration<String> getInitParameterNames() { 22 return this.getServletConfig().getInitParameterNames(); 23 } 24 25 public ServletConfig getServletConfig() { 26 return this.config; 27 } 28 29 public ServletContext getServletContext() { 30 return this.getServletConfig().getServletContext(); 31 } 32 33 public String getServletInfo() { 34 return ""; 35 } 36 37 public void init(ServletConfig config) throws ServletException { 38 this.config = config; 39 this.init(); 40 } 41 42 public void init() throws ServletException { 43 } 44 45 public void log(String msg) { 46 this.getServletContext().log(this.getServletName() + ": " + msg); 47 } 48 49 public void log(String message, Throwable t) { 50 this.getServletContext().log(this.getServletName() + ": " + message, t); 51 } 52 53 public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException; 54 55 public String getServletName() { 56 return this.config.getServletName(); 57 } 58 }
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类中的主要方法的源代码如下所示:
1 // 2 // Source code recreated from a .class file by IntelliJ IDEA 3 // (powered by Fernflower decompiler) 4 // 5 6 package javax.servlet.http; 7 8 import java.io.IOException; 9 import java.lang.reflect.InvocationTargetException; 10 import java.lang.reflect.Method; 11 import java.text.MessageFormat; 12 import java.util.Enumeration; 13 import java.util.ResourceBundle; 14 import javax.servlet.DispatcherType; 15 import javax.servlet.GenericServlet; 16 import javax.servlet.ServletException; 17 import javax.servlet.ServletOutputStream; 18 import javax.servlet.ServletRequest; 19 import javax.servlet.ServletResponse; 20 21 public abstract class HttpServlet extends GenericServlet { 22 private static final long serialVersionUID = 1L; 23 private static final String METHOD_DELETE = "DELETE"; 24 private static final String METHOD_HEAD = "HEAD"; 25 private static final String METHOD_GET = "GET"; 26 private static final String METHOD_OPTIONS = "OPTIONS"; 27 private static final String METHOD_POST = "POST"; 28 private static final String METHOD_PUT = "PUT"; 29 private static final String METHOD_TRACE = "TRACE"; 30 private static final String HEADER_IFMODSINCE = "If-Modified-Since"; 31 private static final String HEADER_LASTMOD = "Last-Modified"; 32 private static final String LSTRING_FILE = "javax.servlet.http.LocalStrings"; 33 private static final ResourceBundle lStrings = ResourceBundle.getBundle("javax.servlet.http.LocalStrings"); 34 35 public HttpServlet() { 36 } 37 38 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 39 String protocol = req.getProtocol(); 40 String msg = lStrings.getString("http.method_get_not_supported"); 41 if (protocol.endsWith("1.1")) { 42 resp.sendError(405, msg); 43 } else { 44 resp.sendError(400, msg); 45 } 46 47 } 48 49 protected long getLastModified(HttpServletRequest req) { 50 return -1L; 51 } 52 53 protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 54 if (DispatcherType.INCLUDE.equals(req.getDispatcherType())) { 55 this.doGet(req, resp); 56 } else { 57 NoBodyResponse response = new NoBodyResponse(resp); 58 this.doGet(req, response); 59 response.setContentLength(); 60 } 61 62 } 63 64 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 65 String protocol = req.getProtocol(); 66 String msg = lStrings.getString("http.method_post_not_supported"); 67 if (protocol.endsWith("1.1")) { 68 resp.sendError(405, msg); 69 } else { 70 resp.sendError(400, msg); 71 } 72 73 } 74 75 protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 76 String protocol = req.getProtocol(); 77 String msg = lStrings.getString("http.method_put_not_supported"); 78 if (protocol.endsWith("1.1")) { 79 resp.sendError(405, msg); 80 } else { 81 resp.sendError(400, msg); 82 } 83 84 } 85 86 protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 87 String protocol = req.getProtocol(); 88 String msg = lStrings.getString("http.method_delete_not_supported"); 89 if (protocol.endsWith("1.1")) { 90 resp.sendError(405, msg); 91 } else { 92 resp.sendError(400, msg); 93 } 94 95 } 96 97 private static Method[] getAllDeclaredMethods(Class<?> c) { 98 if (c.equals(HttpServlet.class)) { 99 return null; 100 } else { 101 Method[] parentMethods = getAllDeclaredMethods(c.getSuperclass()); 102 Method[] thisMethods = c.getDeclaredMethods(); 103 if (parentMethods != null && parentMethods.length > 0) { 104 Method[] allMethods = new Method[parentMethods.length + thisMethods.length]; 105 System.arraycopy(parentMethods, 0, allMethods, 0, parentMethods.length); 106 System.arraycopy(thisMethods, 0, allMethods, parentMethods.length, thisMethods.length); 107 thisMethods = allMethods; 108 } 109 110 return thisMethods; 111 } 112 } 113 114 protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 115 Method[] methods = getAllDeclaredMethods(this.getClass()); 116 boolean ALLOW_GET = false; 117 boolean ALLOW_HEAD = false; 118 boolean ALLOW_POST = false; 119 boolean ALLOW_PUT = false; 120 boolean ALLOW_DELETE = false; 121 boolean ALLOW_TRACE = true; 122 boolean ALLOW_OPTIONS = true; 123 Class clazz = null; 124 125 try { 126 clazz = Class.forName("org.apache.catalina.connector.RequestFacade"); 127 Method getAllowTrace = clazz.getMethod("getAllowTrace", (Class[])null); 128 ALLOW_TRACE = (Boolean)getAllowTrace.invoke(req, (Object[])null); 129 } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | ClassNotFoundException var14) { 130 ; 131 } 132 133 for(int i = 0; i < methods.length; ++i) { 134 Method m = methods[i]; 135 if (m.getName().equals("doGet")) { 136 ALLOW_GET = true; 137 ALLOW_HEAD = true; 138 } 139 140 if (m.getName().equals("doPost")) { 141 ALLOW_POST = true; 142 } 143 144 if (m.getName().equals("doPut")) { 145 ALLOW_PUT = true; 146 } 147 148 if (m.getName().equals("doDelete")) { 149 ALLOW_DELETE = true; 150 } 151 } 152 153 String allow = null; 154 if (ALLOW_GET) { 155 allow = "GET"; 156 } 157 158 if (ALLOW_HEAD) { 159 if (allow == null) { 160 allow = "HEAD"; 161 } else { 162 allow = allow + ", HEAD"; 163 } 164 } 165 166 if (ALLOW_POST) { 167 if (allow == null) { 168 allow = "POST"; 169 } else { 170 allow = allow + ", POST"; 171 } 172 } 173 174 if (ALLOW_PUT) { 175 if (allow == null) { 176 allow = "PUT"; 177 } else { 178 allow = allow + ", PUT"; 179 } 180 } 181 182 if (ALLOW_DELETE) { 183 if (allow == null) { 184 allow = "DELETE"; 185 } else { 186 allow = allow + ", DELETE"; 187 } 188 } 189 190 if (ALLOW_TRACE) { 191 if (allow == null) { 192 allow = "TRACE"; 193 } else { 194 allow = allow + ", TRACE"; 195 } 196 } 197 198 if (ALLOW_OPTIONS) { 199 if (allow == null) { 200 allow = "OPTIONS"; 201 } else { 202 allow = allow + ", OPTIONS"; 203 } 204 } 205 206 resp.setHeader("Allow", allow); 207 } 208 209 protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 210 String CRLF = "\r\n"; 211 StringBuilder buffer = (new StringBuilder("TRACE ")).append(req.getRequestURI()).append(" ").append(req.getProtocol()); 212 Enumeration reqHeaderEnum = req.getHeaderNames(); 213 214 while(reqHeaderEnum.hasMoreElements()) { 215 String headerName = (String)reqHeaderEnum.nextElement(); 216 buffer.append(CRLF).append(headerName).append(": ").append(req.getHeader(headerName)); 217 } 218 219 buffer.append(CRLF); 220 int responseLength = buffer.length(); 221 resp.setContentType("message/http"); 222 resp.setContentLength(responseLength); 223 ServletOutputStream out = resp.getOutputStream(); 224 out.print(buffer.toString()); 225 out.close(); 226 } 227 228 protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 229 String method = req.getMethod(); 230 long lastModified; 231 if (method.equals("GET")) { 232 lastModified = this.getLastModified(req); 233 if (lastModified == -1L) { 234 this.doGet(req, resp); 235 } else { 236 long ifModifiedSince; 237 try { 238 ifModifiedSince = req.getDateHeader("If-Modified-Since"); 239 } catch (IllegalArgumentException var9) { 240 ifModifiedSince = -1L; 241 } 242 243 if (ifModifiedSince < lastModified / 1000L * 1000L) { 244 this.maybeSetLastModified(resp, lastModified); 245 this.doGet(req, resp); 246 } else { 247 resp.setStatus(304); 248 } 249 } 250 } else if (method.equals("HEAD")) { 251 lastModified = this.getLastModified(req); 252 this.maybeSetLastModified(resp, lastModified); 253 this.doHead(req, resp); 254 } else if (method.equals("POST")) { 255 this.doPost(req, resp); 256 } else if (method.equals("PUT")) { 257 this.doPut(req, resp); 258 } else if (method.equals("DELETE")) { 259 this.doDelete(req, resp); 260 } else if (method.equals("OPTIONS")) { 261 this.doOptions(req, resp); 262 } else if (method.equals("TRACE")) { 263 this.doTrace(req, resp); 264 } else { 265 String errMsg = lStrings.getString("http.method_not_implemented"); 266 Object[] errArgs = new Object[]{method}; 267 errMsg = MessageFormat.format(errMsg, errArgs); 268 resp.sendError(501, errMsg); 269 } 270 271 } 272 273 private void maybeSetLastModified(HttpServletResponse resp, long lastModified) { 274 if (!resp.containsHeader("Last-Modified")) { 275 if (lastModified >= 0L) { 276 resp.setDateHeader("Last-Modified", lastModified); 277 } 278 279 } 280 } 281 282 public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { 283 HttpServletRequest request; 284 HttpServletResponse response; 285 try { 286 request = (HttpServletRequest)req; 287 response = (HttpServletResponse)res; 288 } catch (ClassCastException var6) { 289 throw new ServletException("non-HTTP request or response"); 290 } 291 292 this.service(request, response); 293 } 294 }
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基本结构,我们在后面也主要使用这种结构:
1 package com.Servlet; 2 3 import javax.servlet.ServletConfig; 4 import javax.servlet.ServletException; 5 import javax.servlet.annotation.WebServlet; 6 import javax.servlet.http.HttpServlet; 7 import javax.servlet.http.HttpServletRequest; 8 import javax.servlet.http.HttpServletResponse; 9 import java.io.IOException; 10 11 @WebServlet(name = "SimpleServlet") 12 public class SimpleServlet extends HttpServlet { 13 public SimpleServlet(){ 14 super(); 15 } 16 17 public void init(ServletConfig servletConfig) throws ServletException{ 18 //初始化方法 19 } 20 21 public void destroy() { 22 //销毁方法 23 } 24 25 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 26 //处理POST请求时调用的方法 27 } 28 29 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 30 //处理GET请求时调用的方法 31 } 32 }
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容器必须释放该实例以便被垃圾回收
时序图:
转载于:https://www.cnblogs.com/qq965921539/p/10161340.html
Java Web 学习与总结(一)Servlet基础相关推荐
- Java Web学习笔记10:Servlet基础
文章目录 一.Servlet概述 1.什么是Servlet 2.Servlet架构 3.Servlet任务 4.Servlet生命周期
- Java web学习(一)Servlet简介
Servlet 是什么? Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间 ...
- Java Web学习笔记 3 深入Servlet技术
第3章 深入Servlet技术 请求-响应模式就是典型的Web应用程序访问过程,Java Web应用程序中,处理请求并发送响应的过程是由一种叫做Servlet的程序来完成的. 请求request,响应 ...
- Java Web学习笔记13:AJAX基础
文章目录 一.AJAX概述 1.XMLHttpRequest对象的属性 2.XMLHttpRequest对象的方法
- java web学习笔记(持续更新)
java web学习笔记 一.Java Web简介 二.认识Servlet 1.什么是Servlet? 2.请求路径 3.tomcat 4.Servlet的使用 三.Servlet简单应用 1.创建S ...
- Java Web 学习路线
Java Web 学习路线 实际上,如果时间安排合理的话,大概需要六个月左右,有些基础好,自学能力强的朋友,甚至在四个月左右就开始找工作了. 大三的时候,我萌生了放弃本专业的念头,断断续续学 Java ...
- Java Web 学习路线(2018)
实际上,如果时间安排合理的话,大概需要六个月左右,有些基础好,自学能力强的朋友,甚至在四个月左右就开始找工作了. 大三的时候,我萌生了放弃本专业的念头,断断续续学 Java Web 累计一年半左右,总 ...
- java web学习项目20套源码完整版
java web学习项目20套源码完整版 自己收集的各行各业的都有,这一套源码吃遍所有作业项目! 1.BBS论坛系统(jsp+sql) 2.ERP管理系统(jsp+servlet) 3.OA办公自动化 ...
- 2019年Java Web学习笔记目录
Java Web学习笔记目录 1.Java Web学习笔记01:动态网站初体验 2.Java Web学习笔记02:在Intellij里创建Web项目 3.Java Web学习笔记03:JSP元素 4. ...
最新文章
- ASP.NET WebAPi之断点续传下载(中)
- bootstraptable获取所有数据_一键获取oracle用户下所有表的表名与其数据量
- 10.Mysql数据库导入导出和授权
- Perl用LWP实现GET/POST数据发送
- 微信开放平台公众号第三方平台开发 教程一 平台介绍
- 字典哈希表的实现原理
- Ackerman阿克曼函数的递归与非递归(栈)实现
- 三星android p内测,两年前老机重生!三星开启Galaxy C9 Pro升级安卓8.0内测
- 判断粗大误差的matlab程序,粗大误差处理程序
- unity3D游戏素材素材哪家强?Top3都在这!
- 读书百客:《月夜》鉴赏
- 平价的蓝牙耳机哪家质量好?学生党公认的五款高品质蓝牙耳机
- iOS开发模拟网络状态差进行调试
- 数据结构·堆·完全二叉树
- 身份证属地查询,国内身份证号码查询验证(酒店管理系统自动化)
- 360 || 2021校园招聘的一道笔试题思路分享
- HM代码-码控(1)-乱七八糟的初始化
- 情感支撑对话论文最近进展 Emotion Support Conversation
- jquery自由落体运动(弹簧运动)
- 联想ideapad700-15isk(小新线下版)黑苹果完美驱动附详细安装过程
热门文章
- 计算机专业论文关于天气预报的,关于天气预报论文范文写作 天气预报相关论文写作资料...
- apache arm 交叉编译_MacOS 下交叉编译的折腾笔记
- server2016做文件服务器,『配置』服务器搭建 Office Online Server2016 实现文档预览 番外 错误篇...
- 网页版的svn怎样同步代码_学会使用Hdlbits网页版Verilog代码仿真验证平台
- android surfaceview 大小_Android 使用Camera2 API采集视频数据
- 靶场练习第二十天~vulnhub靶场之Funbox: Scriptkiddie
- Duilib编辑框Edit输入完自动跳到下一个编辑框
- 用Kotlin开发您的第一个应用程序| Android与Kotlin
- 汇编语言-017(SCASW 、STRUCT 、STRUCT_ALLPOINTS 、STRUCT_ALIGN 、SYSTEMTIME、UNION 、 STRUCTTEST )
- 汇编语言-006(数组操作 、字符串应用、PUSHFD_POPFD 、PUSHAD_POPAD 、 子程序 函数、 USES 、 INC_DEC )