编程问答
servlet入门篇(genericservlet 类 -凯发ag旗舰厅登录网址下载
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秒后刷新并跳转到我的博客的网站凯发ag旗舰厅登录网址下载首页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);}}
总结
以上是凯发ag旗舰厅登录网址下载为你收集整理的servlet入门篇(genericservlet 类 - httpservlet 类 -servletconfig 接口 - httpservletrequest 接口……)的全部内容,希望文章能够帮你解决所遇到的问题。
如果觉得凯发ag旗舰厅登录网址下载网站内容还不错,欢迎将凯发ag旗舰厅登录网址下载推荐给好友。
- 上一篇:
- 下一篇: 会话管理:session与cookie