servlet入门篇(genericservlet 类 -尊龙游戏旗舰厅官网
1.servlet 简介
servlet 对请求的处理和响应过程可分为以下几个步骤:
(1)客户端发送请求至服务器端;
(2)服务器将请求信息发送至 servlet ;
(3)servlet 生成响应内容并将其传给服务器。响应内容动态生成,通常取决于客户端的请求;
(4)服务器将响应返回给客户端。
servlet 执行以下主要任务:
- 读取客户端(浏览器)发送的显式的数据。这包括网页上的 html 表单,或者也可以是来自 applet 或自定义的 http 客户端程序的表单。
- 读取客户端(浏览器)发送的隐式的 http 请求数据。这包括 cookies、媒体类型和浏览器能理解的压缩格式等等。
- 处理数据并生成结果。这个过程可能需要访问数据库,执行 rmi 或 corba 调用,调用 web 服务,或者直接计算得出对应的响应。
- 发送显式的数据(即文档)到客户端(浏览器)。该文档的格式可以是多种多样的,包括文本文件(html 或 xml)、二进制文件(gif 图像)、excel 等。
- 发送隐式的 http 响应到客户端(浏览器)。这包括告诉浏览器或其他客户端被返回的文档类型(例如 html),设置 cookies 和缓存参数,以及其他类似的任务。
2.servlet基础
2.1 servlet体系结构
public abstract class httpservlet extends genericservlet public abstract class genericservlet implements servlet, servletconfig, serializable2.2 servlet 接口
servlet 接口 定义了 servlet 与 servlet 容器之间的契约,servlet 容器将 servlet 类载入内存,并在 servlet 实例上调用具体的方法。用户请求致使 servlet 容器调用 servlet 的service 方法,并传入一个 servletrequest 实例和一个 servletresponse 实例。
// // source code recreated from a .class file by intellij idea // (powered by fernflower decompiler) //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(); }2.3 生命周期
servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 servlet 遵循的过程:
-
servlet 通过调用 init () 方法进行初始化。
-
servlet 调用 service() 方法来处理客户端的请求。
-
servlet 通过调用 destroy() 方法终止(结束)。
-
最后,servlet 是由 jvm 的垃圾回收器进行垃圾回收的。
一个简单的生命周期案例:
package webstudy;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; import java.io.printwriter;@webservlet(name = "/life") public class lifeservlet extends httpservlet {public lifeservlet() {system.out.println(this.getclass().getname()"构造方法执行");}@overridepublic void init() throws servletexception {// 初始化代码...system.out.println(this.getclass().getname()"init方法执行");}@overrideprotected void dopost(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception {}@overrideprotected void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception {system.out.println(this.getclass().getname()"doget方法执行");response.setcontenttype("text/html");printwriter pw = response.getwriter();pw.println("");pw.flush();pw.close();}@overridepublic void destroy() {// 终止化代码...system.out.println(this.getclass().getname()"destory方法执行");} }3. servlet api 编程常用接口和类
-
genericservlet 类
-
httpservlet 类
-
servletconfig 接口
-
httpservletrequest 接口
-
httpservletresponse 接口
-
servletconfig 接口
3.4.1 genericservlet 类
genericservlet 类是一个抽象类,实现了 servlet 和 servletconfig 接口,其作用是:
(1)将 init 方法中的 servletconfig 赋给一个类中成员(servletconfig config),以便可以通过调用 getservletconfig 获取。
(2)为 servlet 接口中的所有方法提供默认的实现。
(3)可以通过覆盖没有参数的 init 方法来编写初始化代码,servletconfig 则仍然由 genericservlet 实例保存。
(4)开发者可以在不用获得 servletconfig 对象情况下直接调用 servletconfig 的方法,例如源代码中的 getservletcontext() 方法。
一个简单示例:获取初始化参数name:value
package book.ch2;import javax.servlet.*; import javax.servlet.annotation.webinitparam; import javax.servlet.annotation.webservlet; import java.io.ioexception; import java.io.printwriter;@webservlet(name = "mygenericservlet", urlpatterns = { "/generic" }, initparams = {@webinitparam(name = "driverclassname", value = "org.postgresql.driver")})public class mygenericservlet extends genericservlet {private static final long serialversionuid = 1l;public mygenericservlet() {super();}@overridepublic void service(servletrequest request, servletresponse response) throws servletexception, ioexception {servletconfig servletconfig = getservletconfig();string driverclassname = servletconfig.getinitparameter("driverclassname");string url = servletconfig.getinitparameter("url");response.setcontenttype("text/html");printwriter writer = response.getwriter(); writer.print("driverclassname:" driverclassname); } }
3.4.2 httpservlet 类
httpservlet 覆盖了 genericservlet 中的 service 方法,并添加了一个新 service 方法。
新 service 方法接受的参数是 httpservletrequest 和 httpservletresponse ,而不是 servletrequest 和 servletresponse。
原始的 service 方法将 servlet 容器的 request 和 response 对象分别转换成 httpservletrequest 和 httpservletresponse,并调用新的 service 方法。
httpservlet 中的 service 方法会检验用来发送请求的 http 方法(通过调用 request.getmethod)并调用以下方法之一:doget、dopost、dohead、doput、dotrace、dooptions 和 dodelete。这 7 种方法中,doget 和 dopost 是最常用的。所以,不再需要覆盖 service 方法了,只须覆盖 doget 或者 dopost 即可。
// // 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 msg = lstrings.getstring("http.method_get_not_supported");this.sendmethodnotallowed(req, resp, 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 msg = lstrings.getstring("http.method_post_not_supported");this.sendmethodnotallowed(req, resp, msg);}protected void doput(httpservletrequest req, httpservletresponse resp) throws servletexception, ioexception {string msg = lstrings.getstring("http.method_put_not_supported");this.sendmethodnotallowed(req, resp, msg);}protected void dodelete(httpservletrequest req, httpservletresponse resp) throws servletexception, ioexception {string msg = lstrings.getstring("http.method_delete_not_supported");this.sendmethodnotallowed(req, resp, msg);}private void sendmethodnotallowed(httpservletrequest req, httpservletresponse resp, string msg) throws ioexception {string protocol = req.getprotocol();if (protocol.length() != 0 && !protocol.endswith("0.9") && !protocol.endswith("1.0")) {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(lstrings.getstring("http.non_http"));}this.service(request, response);} }3.4.3 servletconfig 接口
tomcat 初始化一个 servlet 时,会将该 servlet 的配置信息封装到一个 servletconfig 对象中,通过调用 init(servletconfig config) 方法将 servletconfig 对象传递给 servlet。
// // source code recreated from a .class file by intellij idea // (powered by fernflower decompiler) //package javax.servlet;import java.util.enumeration;public interface servletconfig {string getservletname();servletcontext getservletcontext();string getinitparameter(string var1);enumeration一个简单的示例:获取配置信息
package book.ch2;import javax.servlet.servletconfig; import javax.servlet.servletexception; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import java.io.ioexception; import java.io.printwriter;public class servletconfigdemoservlet extends httpservlet { private servletconfig servletconfig;@overridepublic void init(servletconfig config) throws servletexception {this.servletconfig = config;system.out.println("-----------" servletconfig "-----------");}@overridepublic servletconfig getservletconfig() {return servletconfig;}@overrideprotected void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception {// 使用servletconfig对象获取初始化参数servletconfig servletconfig = getservletconfig();system.out.println("-----------" servletconfig "-----------");string poet = servletconfig.getinitparameter("poet");string poem = servletconfig.getinitparameter("poem");// 设置响应到客户端的文本类型为htmlresponse.setcontenttype("text/html;charset=utf-8");// 获取输出流printwriter out = response.getwriter();out.print("获取servletconfigdenoservlet的初始化参数:");out.println("
poet参数的值:" poet);out.println("
poem参数的值:" poem "
"); out.append("served at:").append(request.getcontextpath());}}web.xml配置
<servlet><servlet-name>myservletconfigservlet-name><servlet-class>book.ch2.servletconfigdemoservletservlet-class><init-param><param-name>poetparam-name><param-value>纳兰容若param-value>init-param><init-param><param-name>poemparam-name><param-value>我是人间惆怅客param-value>init-param>servlet><servlet-mapping><servlet-name>myservletconfigservlet-name><url-pattern>/myservletconfigurl-pattern>servlet-mapping>输出结果:
3.4.4 httpservletrequest 接口
httpservletrequest 接口继承自 servletrequest 接口,专门用来封装 http 请求消息。
由于 http 请求消息分为请求行、请求消息头和请求消息体3部分,故而在 httpservletrequest 接口中定义了获取请求行、请求消息头和请求消息体的相关方法,以及存取请求域属性的方法。
package book.ch2;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; import java.io.printwriter;@webservlet("/requestlineservlet") public class requestlineservlet extends httpservlet {private static final long serialversionuid = 1l;public requestlineservlet() {super(); }/******************* 获取请求行信息 *******************/@overrideprotected void doget(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {// 设置响应到客户端mime类型和字符编码方式response.setcontenttype("text/html;charset=utf-8");// 获取请求使用的http方法string method = request.getmethod();// 获取请求行中的资源名部分string uri = request.getrequesturi();// 获取使用的协议及版本号string protocol = request.getprotocol();// 获取请求url后面的查询字符串string querystring = request.getquerystring();// 获取servlet所映射的路径string servletpath = request.getservletpath();// 获取请求资源所属于的web应用的路径string contextpath = request.getcontextpath();// 获取输出流printwriter out = response.getwriter();out.println("请求使用的http方法:" method "
");out.println("请求行中的资源名部分:" uri "
");out.println("请求使用的协议及版本号:" protocol "
");out.println("请求url后面的查询字符串:" querystring "
");out.println("servlet所映射的路径:" servletpath "
");out.println("请求资源所属于的web应用的路径:" contextpath "
"); out.append("served at:").append(request.getcontextpath());out.close();}@overrideprotected void dopost(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception { doget(request, response);}}3.4.4.1 获取请求头信息
请求头信息
");// 获取请求消息中所有头字段enumeration headernames = request.getheadernames();// 使用循环遍历所有请求头,并通过getheader()方法获取一个指定名称的头字段while (headernames.hasmoreelements()) {string headername = (string) headernames.nextelement();out.print(headername " : " request.getheader(headername) "
");}}@overrideprotected void dopost(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {doget(request, response);}}
3.4.4.2 获取请求参数
获取请求参数:
<html> <head> <meta charset="utf-8"> <title>个人信息title> head> <body> <h2>个人信息h2> <hr> <form action="/requestparaservlet" method="get"><p>用户名:<input type="text" name="username">p><p>昵 称:<input type="text" name="nickname">p><p>爱好:<input type="checkbox" name="hobby" value="swim">游泳<input type="checkbox" name="hobby" value="go">围棋<input type="checkbox" name="hobby" value="music">音乐p><p><input type="submit" value="提交">p>form> body> html> package book.ch2;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; import java.io.printwriter;@webservlet("/requestparaservlet") public class requestparaservlet extends httpservlet {private static final long serialversionuid = 1l;public requestparaservlet() {super();}/******************* 获取请求参数 *******************/@overrideprotected void doget(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {// 设置响应到客户端mime类型和字符编码方式response.setcontenttype("text/html;charset=utf-8");// 设置request对象的解码方式request.setcharacterencoding("utf-8");string username = request.getparameter("username");string nickname = request.getparameter("nickname");// 获取输出流printwriter out = response.getwriter();out.println("用户名:" username "
");out.println("昵 称:" nickname "
");out.println("爱好:");// 获取参数名为“hobby”的值string[] hobbys = request.getparametervalues("hobby");for (int i = 0; i < hobbys.length; i) {if (i < hobbys.length - 1)out.println(hobbys[i] ",");elseout.println(hobbys[i] "");}out.println("
");out.close(); }@overrideprotected void dopost(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {doget(request, response);}}3.4.4.3 设置-获取-删除请求域属性
获取请求域属性:
package book.ch2;import com.mialab.servlet_demo.entity.book;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; import java.io.printwriter; import java.util.date; import java.util.enumeration;@webservlet("/requestscopeattrservlet") public class requestscopeattrservlet extends httpservlet {private static final long serialversionuid = 1l;public requestscopeattrservlet() {super();}@override/******************* 获取请求域属性 *******************/protected void doget(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {// 设置响应的文本类型为html,字符编码为utf-8response.setcontenttype("text/html;charset=utf-8");// 在request范围内设置名为book的book对象属性request.setattribute("book", new book(9801, "《android应用开发实践教程》"));// 在request范围内设置名为singer的string对象属性request.setattribute("singer", "jessie j,第32届全英音乐奖入围最佳女艺人,《歌手2018》总冠军");// 在request范围内设置名为newdate的date对象属性request.setattribute("newdate", new date());// 从request范围内获取名为book的属性book book = (book) request.getattribute("book");// 从request范围内获取名为singer的属性string singer = (string) request.getattribute("singer");// 从request范围内获取名为newdate的属性date date = (date) request.getattribute("newdate");// 获取输出流printwriter out = response.getwriter();out.println("request.getattribute(\"book\")的值:" book "
");out.println("request.getattribute(\"singer\")的值:" singer "
");out.println("request.getattribute(\"newdate\")的值:" date "
");enumeration<string> names = request.getattributenames();out.println("request请求域中的属性有:");while (names.hasmoreelements()) {out.println(names.nextelement() " ");}out.println("
");request.removeattribute("book");out.println("执行request.removeattribute(\"book\")后request请求域中的属性有:");names = request.getattributenames();while (names.hasmoreelements()) {out.println(names.nextelement() " ");}out.close();}@overrideprotected void dopost(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {doget(request, response);}}
httpservletrequest源代码:
// // source code recreated from a .class file by intellij idea // (powered by fernflower decompiler) //package javax.servlet.http;import java.io.ioexception; import java.security.principal; import java.util.collection; import java.util.collections; import java.util.enumeration; import java.util.map; import javax.servlet.servletexception; import javax.servlet.servletrequest;public interface httpservletrequest extends servletrequest {string basic_auth = "basic";string form_auth = "form";string client_cert_auth = "client_cert";string digest_auth = "digest";string getauthtype();cookie[] getcookies();long getdateheader(string var1);string getheader(string var1);enumeration<string> getheaders(string var1);enumeration<string> getheadernames();int getintheader(string var1);default httpservletmapping gethttpservletmapping() {return new httpservletmapping() {public string getmatchvalue() {return "";}public string getpattern() {return "";}public string getservletname() {return "";}public mappingmatch getmappingmatch() {return null;}};}string getmethod();string getpathinfo();string getpathtranslated();default pushbuilder newpushbuilder() {return null;}string getcontextpath();string getquerystring();string getremoteuser();boolean isuserinrole(string var1);principal getuserprincipal();string getrequestedsessionid();string getrequesturi();stringbuffer getrequesturl();string getservletpath();httpsession getsession(boolean var1);httpsession getsession();string changesessionid();boolean isrequestedsessionidvalid();boolean isrequestedsessionidfromcookie();boolean isrequestedsessionidfromurl();/** @deprecated */@deprecatedboolean isrequestedsessionidfromurl();boolean authenticate(httpservletresponse var1) throws ioexception, servletexception;void login(string var1, string var2) throws servletexception;void logout() throws servletexception;collection<part> getparts() throws ioexception, servletexception;part getpart(string var1) throws ioexception, servletexception;<t extends httpupgradehandler> t upgrade(class<t> var1) throws ioexception, servletexception;default map<string, string> gettrailerfields() {return collections.emptymap();}default boolean istrailerfieldsready() {return false;} }3.4.5 httpservletresponse 接口
httpservletresponse 接口继承自 servletresponse 接口,专门用来封装 http 响应消息。由于 http 响应消息分为状态行、响应消息头、消息体三部分,于是在 httpservletresponse 接口中也相应定义了向客户端发送响应状态码、响应消息头、响应消息体的方法。
httpservletresponse 接口提供的设置状态码并生成响应状态行的方法有以下。
(1)setstatus(int status) 方法:用于设置 http 响应消息的状态码,并生成响应状态行。正常情况下,web 服务器会默认产生一个状态码为 200 的状态行。
(2)senderror(int sc) 方法和 senderror(int sc, string msg) 方法:第 1 个方法只是发送错误信息的状态码;而第 2 个方法除了发送状态码外,还可以增加一条用于提示说明的文本信息,该文本信息将出现在发送给客户端的正文内容中。
3.4.5.1 响应消息头
package book.ch2;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("/responseheadservlet") public class responseheadservlet extends httpservlet {private static final long serialversionuid = 1l;public responseheadservlet() {super();}@overrideprotected void doget(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {// 5秒后刷新并跳转到我的博客的网站尊龙游戏旗舰厅尊龙游戏旗舰厅官网首页response.setheader("refresh", "5;url=http://www.bithachi.cn");// 每隔2秒定时刷新当前页面// response.setheader("refresh", "2");response.getwriter().println(new java.util.date());// 输出当前时间}@overrideprotected void dopost(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {doget(request, response);}}
3.4.5.2 响应消息体
package book.ch2;import javax.servlet.servletcontext; import javax.servlet.servletexception; import javax.servlet.servletoutputstream; import javax.servlet.annotation.webservlet; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import java.io.ioexception; import java.io.inputstream;@webservlet("/responsepicservlet") public class responsepicservlet extends httpservlet {private static final long serialversionuid = 1l;public responsepicservlet() {super();}@overrideprotected void doget(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {// 设置响应消息头content-typeresponse.setcontenttype("image/jpeg");// 获取servletcontext对象servletcontext context = super.getservletcontext();// 获取读取服务器端文件的输入流inputstream is = context.getresourceasstream("/images/ch2/abc.jpeg");// 获取servletoutputstream输出流servletoutputstream os = response.getoutputstream();int i = 0;while ((i = is.read()) != -1) {os.write(i);// 向输出流中写入二进制数据}is.close();os.close();}@overrideprotected void dopost(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {doget(request, response);} }
httpservletresponse源代码:
3.4.6 servletcontext 接口
servlet 容器在启动一个 web 应用时,会为该应用创建一个唯一的 servletcontext 对象供该应用中的所有 servlet 对象共享。servlet 对象可以通过 servletcontext 对象来访问容器中的各种资源。
获得 servletcontext 对象可以通过以下两种方式:
servletcontext 接口中定义了获取 web 应用范围的初始化参数的方法,有以下。
(1)方法声明:public string getinitparameter(string name) ;
作用:返回 web 应用范围内指定的初始化参数值。在 web.xml 中使用 元素表示应用范围内的初始化参数。
(2)方法声明:public enumeration getinitparameternames();
作用:返回一个包含所有初始化参数名称的 enumeration 对象。
3.4.6.1 获取web应用的初始化参数
web.xml
<context-param><param-name>usernameparam-name><param-value>admin888param-value>context-param><context-param><param-name>passwordparam-name><param-value>123param-value>context-param><context-param><param-name>driverclassnameparam-name><param-value>org.postgresql.driverparam-value>context-param><context-param><param-name>urlparam-name><param-value>jdbc:postgresql://127.0.0.1:5432/postgresparam-value>context-param> package book.ch2;import javax.servlet.servletcontext; 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; import java.io.printwriter; import java.util.enumeration;@webservlet("/getwebinitparamservlet") public class getwebinitparamservlet extends httpservlet {private static final long serialversionuid = 1l;public getwebinitparamservlet() {super();}@overrideprotected void doget(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {// 设置响应到客户端的文本类型为htmlresponse.setcontenttype("text/html;charset=utf-8");// 得到servletcontext对象servletcontext context = this.getservletcontext();// 得到包含所有初始化参数名的enumeration对象enumeration<string> paramnames = context.getinitparameternames();// 获取输出流printwriter out = response.getwriter();// 遍历所有的初始化参数名,得到相应的参数值,打印到控制台out.print("当前web应用的所有初始化参数:
"); // 遍历所有的初始化参数名,得到相应的参数值并打印while (paramnames.hasmoreelements()) {string name = paramnames.nextelement();string value = context.getinitparameter(name);out.println(name ":" value);out.println("");}out.close();}@overrideprotected void dopost(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {doget(request, response);}}
3.4.6.2 实现多个servlet对象共享数据
先访问putcontextdataservlet.java设置共享数据,再访问getcontextdataservlet.java获取共享数据
package com.mialab.servlet_demo;import javax.servlet.servletcontext; 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("/putcontextdataservlet") public class putcontextdataservlet extends httpservlet {private static final long serialversionuid = 1l;public putcontextdataservlet() {super();}@overrideprotected void doget(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {servletcontext context = this.getservletcontext();// 通过setattribute()方法设置属性值context.setattribute("contextdata", "here is contexdata");}@overrideprotected void dopost(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {// todo auto-generated method stubdoget(request, response);}} package book.ch2;import javax.servlet.servletcontext; 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; import java.io.printwriter;@webservlet("/getcontextdataservlet") public class getcontextdataservlet extends httpservlet {private static final long serialversionuid = 1l;public getcontextdataservlet() {super();}@overrideprotected void doget(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {printwriter out = response.getwriter();servletcontext context = this.getservletcontext();// 通过getattribute()方法获取属性值string data = (string) context.getattribute("contextdata");out.println(data);system.out.println(data);}@overrideprotected void dopost(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {doget(request, response);}}3.4.6.3 读取web应用下的资源文件
package book.ch2;import javax.servlet.servletcontext; 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.fileinputstream; import java.io.ioexception; import java.io.printwriter; import java.util.properties;@webservlet("/getresourceservlet") public class getresourceservlet extends httpservlet {private static final long serialversionuid = 1l;public getresourceservlet() {super();}@overrideprotected void doget(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {printwriter out = response.getwriter();servletcontext context = this.getservletcontext();// 获取文件绝对路径string path = context.getrealpath("/web-inf/classes/data.properties");fileinputstream in = new fileinputstream(path);properties pros = new properties();pros.load(in);out.println("username = " pros.getproperty("username") "");out.println("password = " pros.getproperty("password") "
");out.println("driverclassname = " pros.getproperty("driverclassname") "
");out.println("url = " pros.getproperty("url") "
");}@overrideprotected void dopost(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {doget(request, response);} }
servletcontext.java源代码:
// // source code recreated from a .class file by intellij idea // (powered by fernflower decompiler) //package javax.servlet;import java.io.inputstream; import java.net.malformedurlexception; import java.net.url; import java.util.enumeration; import java.util.eventlistener; import java.util.map; import java.util.set; import javax.servlet.servletregistration.dynamic; import javax.servlet.descriptor.jspconfigdescriptor;public interface servletcontext {string tempdir = "javax.servlet.context.tempdir";string ordered_libs = "javax.servlet.context.orderedlibs";string getcontextpath();servletcontext getcontext(string var1);int getmajorversion();int getminorversion();int geteffectivemajorversion();int geteffectiveminorversion();string getmimetype(string var1);set<string> getresourcepaths(string var1);url getresource(string var1) throws malformedurlexception;inputstream getresourceasstream(string var1);requestdispatcher getrequestdispatcher(string var1);requestdispatcher getnameddispatcher(string var1);/** @deprecated */@deprecatedservlet getservlet(string var1) throws servletexception;/** @deprecated */@deprecatedenumeration<servlet> getservlets();/** @deprecated */@deprecatedenumeration<string> getservletnames();void log(string var1);/** @deprecated */@deprecatedvoid log(exception var1, string var2);void log(string var1, throwable var2);string getrealpath(string var1);string getserverinfo();string getinitparameter(string var1);enumeration<string> getinitparameternames();boolean setinitparameter(string var1, string var2);object getattribute(string var1);enumeration<string> getattributenames();void setattribute(string var1, object var2);void removeattribute(string var1);string getservletcontextname();dynamic addservlet(string var1, string var2);dynamic addservlet(string var1, servlet var2);dynamic addservlet(string var1, class<? extends servlet> var2);dynamic addjspfile(string var1, string var2);<t extends servlet> t createservlet(class<t> var1) throws servletexception;servletregistration getservletregistration(string var1);map<string, ? extends servletregistration> getservletregistrations();javax.servlet.filterregistration.dynamic addfilter(string var1, string var2);javax.servlet.filterregistration.dynamic addfilter(string var1, filter var2);javax.servlet.filterregistration.dynamic addfilter(string var1, class<? extends filter> var2);<t extends filter> t createfilter(class<t> var1) throws servletexception;filterregistration getfilterregistration(string var1);map<string, ? extends filterregistration> getfilterregistrations();sessioncookieconfig getsessioncookieconfig();void setsessiontrackingmodes(set<sessiontrackingmode> var1);set<sessiontrackingmode> getdefaultsessiontrackingmodes();set<sessiontrackingmode> geteffectivesessiontrackingmodes();void addlistener(string var1);<t extends eventlistener> void addlistener(t var1);void addlistener(class<? extends eventlistener> var1);<t extends eventlistener> t createlistener(class<t> var1) throws servletexception;jspconfigdescriptor getjspconfigdescriptor();classloader getclassloader();void declareroles(string... var1);string getvirtualservername();int getsessiontimeout();void setsessiontimeout(int var1);string getrequestcharacterencoding();void setrequestcharacterencoding(string var1);string getresponsecharacterencoding();void setresponsecharacterencoding(string var1); }4. servlet处理表单数据
表单数据是指通过表单让用户填写内容,然后提交到服务器上;这些数据被称之为表单数据。
servlet 处理表单数据可以使用以下的方法:
用户名:" username "
");out.println("密码:" password "
");out.println("性别:" sex "
");out.println("家乡:" home "
");out.println("爱好:");// 获取参数名为“hobby”的值string[] hobbys = request.getparametervalues("hobby");for (int i = 0; i < hobbys.length; i) {if (i < hobbys.length - 1) {out.println(hobbys[i] ",");} else {out.println(hobbys[i] "");}}out.println("
");out.println("自我介绍:" info "
");out.close();}@overrideprotected void dopost(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {doget(request, response);}}5.servlet 重定向和请求转发
请求转发只是把请求转发给服务器上(通常是同一个 web 应用中)的另一个组件( servlet 或 jsp等);
重定向则只是告诉客户(浏览器)去访问另一个 url(可能是同一个 web 站点甚至其他站点)。
请求转发发生在服务器端,由服务器(比如 servlet)控制;
重定向发生在客户端,由客户(通常是浏览器)控制。
请求转发使用 requestdispatcher 对象的 forward() 或 include()方法。
重定向则使用 httpservletresponse 对象的 sendredirect() 方法。
5.1 重定向
重定向后则无法在服务器端获取第一次请求对象上保存的信息。比如还是在 servlet 中将用户名保存到当前 request 对象中,并重定向到一个新的 url,然后在新 url 指向的地址中(假设是某个 servlet)就无法获取原先保存在第一个请求中的信息。很明显,用户名是保存在第一次请求的对象中,但并没有保存在本次(第二次)请求的对象中。
重定向后,浏览器地址栏 url 变为新的 url(因为浏览器确实给新的 url 发送了一个新的请求)。
访问redirectservlet,重定向到anotherservlet
package book.ch2;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("/redirectservlet") public class redirectservlet extends httpservlet {private static final long serialversionuid = 1l;public redirectservlet() {super();}@overrideprotected void doget(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {// 设置响应到客户端的文本类型为htmlresponse.setcontenttype("text/html;charset=utf-8");// 输出当前时间response.getwriter().println(new java.util.date());// 进行重定向response.sendredirect(request.getcontextpath() "/anotherservlet");}@overrideprotected void dopost(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {doget(request, response);}} package book.ch2;import javax.servlet.servletexception; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import java.io.ioexception; import java.io.printwriter;@webservlet("/anotherservlet") public class anotherservlet extends httpservlet {private static final long serialversionuid = 1l;public anotherservlet() {super();}@overrideprotected void doget(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {// 设置响应到客户端的文本类型为htmlresponse.setcontenttype("text/html;charset=utf-8");// 获取输出流printwriter out = response.getwriter();// 输出响应结果out.println("重定向页面
");out.close();}@overrideprotected void dopost(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {doget(request, response);}}http://localhost:8080/redirectservlet —> http://localhost:8080/anotherservlet
5.2 请求转发
请求转发后可以在服务器端获取本次请求对象上保存的信息(比如在 servlet 中将用户名保存到当前 request 对象中,转发给另一组件(如 jsp )后,另一组件可以通过 request 对象取得用户名信息)。
请求转发后,浏览器地址栏 url 不会发生改变。
requestdispatcher对象是通过调用 httpservletrequest 对象的getrequestdispatcher()方法得到的,所以 forward() 或 include() 本质来说是属于请求对象的方法,所以请求转发始终发生在一个请求当中。
forword() 和 include() 的区别:
forward():表示在服务器端从一个 servlet 中将请求转发到另一个资源(servlet、jsp 或 html 等),本意是让第一个组件对请求做些预处理(或者什么都不做),而让另一组件处理并返回响应。
include():表示在响应中包含另一个资源(servlet、jsp 或 html 等)的响应内容,最终被包含的页面产生的任何响应都将并入原来的 response 对象,然后一起输出到客户端。
请求forwardservlet,转发到otherservlet
package book.ch2;import javax.servlet.requestdispatcher; import javax.servlet.servletexception; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import java.io.ioexception;@webservlet("/forwardservlet") public class forwardservlet extends httpservlet {private static final long serialversionuid = 1l;public forwardservlet() {super();}/******************* 转发请求 *******************/@overrideprotected void doget(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {// 将key为bookname,value为《android应用开发实践教程》的属性对象存储到request对象中request.setattribute("bookname", "《android应用开发实践教程》"); requestdispatcher dispatcher = request.getrequestdispatcher("/otherservlet");dispatcher.forward(request, response);}@overrideprotected void dopost(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {doget(request, response);} } package book.ch2;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; import java.io.printwriter;@webservlet("/otherservlet") public class otherservlet extends httpservlet {private static final long serialversionuid = 1l;public otherservlet() {super();}@overrideprotected void doget(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {// 设置响应到客户端的文本类型为htmlresponse.setcontenttype("text/html;charset=utf-8");// 从request对象中获取bookname属性值string bookname = (string) request.getattribute("bookname");// 获取输出流printwriter out = response.getwriter();// 输出响应结果out.println("请求转发的结果页面
");out.println("读取的request对象的bookname属性值为:" bookname);}@overrideprotected void dopost(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {doget(request, response);}}6. servlet数据库访问
jdbc(java database connectivity,java 数据库连接)是一种用于执行 sql 语句的 java api ,可以为多种关系数据库提供统一访问,它由一组用 java 语言编写的类和接口组成。 jdbc 提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够更为便利地编写数据库应用程序。
一个示例:
文件结构:
book.sql
set foreign_key_checks=0;-- ---------------------------- -- table structure for book -- ---------------------------- drop table if exists `book`; create table `book` (`bookid` int(4) not null,`bookname` varchar(50) not null,primary key (`bookid`) ) engine=innodb default charset=utf8;-- ---------------------------- -- records of book -- ---------------------------- insert into `book` values ('9801', 'android应用开发实践教程'); insert into `book` values ('9802', 'web应用开发'); insert into `book` values ('9803', 'ios程序设计');测试数据:
package webstudy;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; import java.io.printwriter; import java.sql.*;@webservlet("/jdbctest") public class jdbcservlet extends httpservlet {string jdbc_driver = "com.mysql.jdbc.driver";string db_url = "jdbc:mysql://localhost:3306/message?usessl=true";string user = "root";string password = "123456";connection con1 = null;statement stmt = null;resultset rs1;@overridepublic void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception {response.setcontenttype("text/html;charset=utf-8");printwriter out = response.getwriter();try {class.forname(jdbc_driver);con1 = drivermanager.getconnection(db_url, user, password);stmt = con1.createstatement();string sql;sql = "select bookid,bookname from book";rs1 = stmt.executequery(sql);while (rs1.next()) {int id = rs1.getint("bookid");string bookname1 = rs1.getstring("bookname");out.println("bookid:" id);out.println(",bookname:" bookname1);out.println("");}rs1.close();stmt.close();con1.close();} catch (sqlexception e) {// todo auto-generated catch blocke.printstacktrace();} catch (exception e) {// todo auto-generated catch blocke.printstacktrace();}//out.close();}}
7. servlet 异常处理
当一个 servlet 抛出一个异常时,web 容器在使用了 exception-type元素的 web.xml中搜索与抛出异常类型相匹配的配置。可以在web.xml中使用error-page元素来指定对特定异常 或 http 状态码作出相应的 servlet 调用。
假设有一个 errorhandler的 servlet 在任何已定义的异常或错误出现时被调用,以下将是在 web.xml 中创建的项。
<servlet><servlet-name>errorhandlerservlet-name><servlet-class>book.ch2.errorhandlerservletservlet-class>servlet> <servlet-mapping><servlet-name>errorhandlerservlet-name><url-pattern>/errorhandlerurl-pattern>servlet-mapping> <error-page><error-code>404error-code><location>/errorhandlerlocation>error-page><error-page><error-code>403error-code><location>/errorhandlerlocation>error-page><error-page><exception-type>javax.servlet.servletexceptionexception-type><location>/errorhandlerlocation>error-page><error-page><exception-type>java.io.ioexceptionexception-type><location>/errorhandlerlocation>error-page>关于上面的web.xml中异常处理几点说明:
errorhandler 与其他的 servelt 的定义方式一样,且在 web.xml 中进行配置。
如果有错误状态代码出现,不管为 404(not found 未找到)或 403(forbidden 禁止),则会调用 errorhandler。
如果 web 应用程序抛出 servletexception 或 ioexception,web 容器则会调用 errorhandler。
可以定义不同的错误处理程序来处理不同类型的错误或异常。
如果要对所有的异常有一个通用的错误处理程序,那么应该定义下面的 error-page,而不是为每个异常定义单独的 error-page 元素:
<error-page><exception-type>java.lang.throwableexception-type><location>/errorhandlerlocation>error-page>一个示例:
<servlet><servlet-name>errorhandlerservlet-name><servlet-class>book.ch2.errorhandlerservletservlet-class>servlet><servlet-mapping><servlet-name>errorhandlerservlet-name><url-pattern>/errorhandlerurl-pattern>servlet-mapping> <error-page><error-code>404error-code><location>/errorhandlerlocation>error-page><error-page><exception-type>java.lang.throwableexception-type><location>/errorhandlerlocation>error-page> package book.ch2;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; import java.io.printwriter; @webservlet("/errorhandlerservlet") public class errorhandlerservlet extends httpservlet {private static final long serialversionuid = 1l;public errorhandlerservlet() {super();}@overrideprotected void doget(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {throwable throwable = (throwable) request.getattribute("javax.servlet.error.exception");integer statuscode = (integer) request.getattribute("javax.servlet.error.status_code");string servletname = (string) request.getattribute("javax.servlet.error.servlet_name");if (servletname == null) {servletname = "unknown";}string requesturi = (string) request.getattribute("javax.servlet.error.request_uri");if (requesturi == null) {requesturi = "unknown";}// 设置响应内容类型response.setcontenttype("text/html;charset=utf-8");printwriter out = response.getwriter();string title = "servlet处理 error/exception";string doctype = "\n";out.println(doctype "\n" "servlet异常/错误处理
");if (throwable == null && statuscode == null) {out.println("错误信息丢失
");out.println("请返回 。");} else if (statuscode != null) {out.println("错误代码 : " statuscode "");out.println("servlet name : " servletname "
");out.println("异常类型 : " throwable.getclass().getname() "
");out.println("请求 uri: " requesturi "
");out.println("异常信息: " throwable.getmessage());} else { // out.println("
错误信息
"); // out.println("servlet name : " servletname ""); // out.println("异常类型 : " throwable.getclass().getname() "
"); // out.println("请求 uri: " requesturi "
"); // out.println("异常信息: " throwable.getmessage());}out.println("");out.println("");}@overrideprotected void dopost(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {doget(request, response);}} package book.ch2;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("/exceptionservlet") public class exceptionservlet extends httpservlet {private static final long serialversionuid = 1l;public exceptionservlet() {super();}@overrideprotected void doget(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {int x = 126/0;//int[] array = {2,4,6};//system.out.println(array[3]);//throw new arrayindexoutofboundsexception();}@overrideprotected void dopost(httpservletrequest request, httpservletresponse response)throws servletexception, ioexception {doget(request, response);}}
总结
以上是尊龙游戏旗舰厅官网为你收集整理的servlet入门篇(genericservlet 类 - httpservlet 类 -servletconfig 接口 - httpservletrequest 接口……)的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇:
- 下一篇: 会话管理:session与cookie