目录:
1.Servlet入门
2.我的第一个Servlet
3.继承HttpServlet类的方法来实现Servlet
4.使用IDE直接创建Servlet程序
5.Servlet的继承体系
6.ServletConfig类
7.ServletCotext类
8.Http协议
9. GenericServlet抽象类
10.HttpServletRequest
11.HttpServletResponse
12.请求重定向

1.Servlet入门

如何实现Servlet:Servlet技术的核心是Servlet,它是所有Servlet类必须直接或者间接实现的一个接口。在编写实现Servlet的Servlet类时,直接实现它。在扩展实现这个这个接口的类时,间接实现它。


Servlet接口定义了Servlet与servlet容器之间的契约。这个契约是:Servlet容器将Servlet类载入内存,并产生Servlet实例和调用它具体的方法。但是要注意的是,在一个应用程序中,每种Servlet类型只能有一个实例。

用户请求致使Servlet容器调用Servlet的Service()方法,并传入一个ServletRequest对象和一个ServletResponse对象。ServletRequest对象和ServletResponse对象都是由Servlet容器(例如TomCat)封装好的,并不需要程序员去实现,程序员可以直接使用这两个对象。

ServletRequest中封装了当前的Http请求,因此,开发人员不必解析和操作原始的Http数据。ServletResponse表示当前用户的Http响应,程序员只需直接操作ServletResponse对象就能把响应轻松的发回给用户。

对于每一个应用程序,Servlet容器还会创建一个ServletContext对象。这个对象中封装了上下文(应用程序)的环境详情。每个应用程序只有一个ServletContext。每个Servlet对象也都有一个封装Servlet配置的ServletConfig对象。

2.我的第一个Servlet

servlet工作流程:


3.继承HttpServlet类的方法来实现Servlet

HttpServlet要比GenericServlet强大,其实也是有道理的。HttpServlet是由GenericServlet抽象类扩展而来的,HttpServlet抽象类的声明如下所示:

public abstract class HttpServlet extends GenericServlet implements Serializable

HttpServlet之所以运用广泛的另一个原因是现在大部分的应用程序都要与HTTP结合起来使用。这意味着我们可以利用HTTP的特性完成更多更强大的任务。Javax。servlet.http包是Servlet API中的第二个包,其中包含了用于编写Servlet应用程序的类和接口。Javax.servlet.http中的许多类型都覆盖了Javax.servlet中的类型。

HttpServlet抽象类是继承于GenericServlet抽象类而来的。使用HttpServlet抽象类时,还需要借助分别代表Servlet请求和Servlet响应的HttpServletRequest和HttpServletResponse对象。

HttpServletRequest接口扩展于javax.servlet.ServletRequest接口,HttpServletResponse接口扩展于javax.servlet.servletResponse接口。

public interface HttpServletRequest extends ServletRequest
public interface HttpServletResponse extends ServletResponse

HttpServlet抽象类覆盖了GenericServlet抽象类中的Service( )方法,并且添加了一个自己独有的Service(HttpServletRequest request,HttpServletResponse方法。

让我们来具体的看一看HttpServlet抽象类是如何实现自己的service方法吧:

首先来看GenericServlet抽象类中是如何定义service方法的:

public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

我们看到是一个抽象方法,也就是HttpServlet要自己去实现这个service方法,我们在看看HttpServlet是怎么覆盖这个service方法的:

public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {HttpServletRequest request;HttpServletResponse response;try {request = (HttpServletRequest)req;response = (HttpServletResponse)res;} catch (ClassCastException var6) {throw new ServletException("non-HTTP request or response");}this.service(request, response);
}

我们发现,HttpServlet中的service方法把接收到的ServletRequsest类型的对象转换成了HttpServletRequest类型的对象,把ServletResponse类型的对象转换成了HttpServletResponse类型的对象。之所以能够这样强制的转换,是因为在调用Servlet的Service方法时,Servlet容器总会传入一个HttpServletRequest对象和HttpServletResponse对象,预备使用HTTP。因此,转换类型当然不会出错了。

转换之后,service方法把两个转换后的对象传入了另一个service方法,那么我们再来看看这个方法是如何实现的:

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 = req.getDateHeader("If-Modified-Since");if (ifModifiedSince < lastModified) {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);}}

我们发现,这个service方法的参数是HttpServletRequest对象和HttpServletResponse对象,刚好接收了上一个service方法传过来的两个对象。

接下来我们再看看service方法是如何工作的,我们会发现在service方法中还是没有任何的服务逻辑,但是却在解析HttpServletRequest中的方法参数,并调用以下方法之一:doGet,doPost,doHead,doPut,doTrace,doOptions和doDelete。这7种方法中,每一种方法都表示一个Http方法。doGet和doPost是最常用的。所以,如果我们需要实现具体的服务逻辑,不再需要覆盖service方法了,只需要覆盖doGet或者doPost就好了。

总之,HttpServlet有两个特性是GenericServlet所不具备的:

1.不用覆盖service方法,而是覆盖doGet或者doPost方法。在少数情况,还会覆盖其他的5个方法。
2.使用的是HttpServletRequest和HttpServletResponse对象。


a.html文件按照第一个Servlet进行配置就行了

4.使用IDE直接创建Servlet程序

5.Servlet的继承体系

6.ServletConfig类


实现Servlet程序,当我们是以继承了HttpServlet类,我们可以使用getServletConfig()方法来获取当前的Servlet对应的ServleConfigt对象,但是当我们直接实现了Servlet接口,就不能使用这个方法来获取ServleConfigt对象,因为这个方法会返回null

当我们使用继承HttpConfig实现Servlet程序,在重写init()方法的时候我们需要在重写的第一行加上一句super.init(config),因为HttpConfig类是继承了GenericServlet类,而GenericServlet类,而GenericServlet的init()方法又保存了Servlet的ServletConfig的对象(GenericServlet实现了Servlet接口)所以如果不使用super.init(config)就无法保存ServletConfig对象

7.ServletCotext类

ServletContext对象表示Servlet应用程序。每个Web应用程序都只有一个ServletContext对象。在将一个应用程序同时部署到多个容器的分布式环境中,每台Java虚拟机上的Web应用都会有一个ServletContext对象。

通过在ServletConfig中调用getServletContext方法,也可以获得ServletContext对象。

那么为什么要存在一个ServletContext对象呢?存在肯定是有它的道理,因为有了ServletContext对象,就可以共享从应用程序中的所有资料处访问到的信息,并且可以动态注册Web对象。前者将对象保存在ServletContext中的一个内部Map中。保存在ServletContext中的对象被称作属性。

ServletContext中的下列方法负责处理属性:

Object getAttribute(String var1);Enumeration<String> getAttributeNames();void setAttribute(String var1, Object var2);void removeAttribute(String var1);

ServletContext对象只能获取<context-param>标签里边的内容不能获取<init-param>标签里边的内容,<init-param>只能由ServletConfig对象获取

我们通过ServletConfig对象获取ServletContext对象,同时我们还可以通过getServletContext()直接获取

ServletContext对象是在web工程启动时创建,web工程停止时销毁我们setAttribute()getAttribute()都是建立在服务器销毁销毁前,而且保存的数据可以在不同的Servlet服务器端进行获取,有点全局变量的意思

以上四个选项:
update resources ---- 更新静态的资源,比如html,js,css等 运行模式和调试模式都是立即生效;
update classes and resources ---- 更新java,jsp和静态资源( 1. java修改后,会被编译成.class,然后覆盖到target/kao文件夹下,IDE调试模式的情况下,立即生效。IDE运行模式下,不立即生效,需要redeployed才可生效。jsp修改后,再次被访问的时候,会自动更新,重新编译成java.class保存在tomcat的work目录下。由于是访问时才检测是否修改,是否需要重新编译,所以 IDE 运行模式 和IDEA调试模式下,都是立即生效。刷新下页面就可);
redeployed ----- 重新部署,发布到tomcat里,不重启tomcat,而是把原来的删掉,然后重新发布(此时的web工程未停止);
restart server ----- 重启tomcat。最彻底!(此时的web工程停止)

8.Http协议

谷歌浏览器查看http协议:

9.GenericServlet抽象类

前面我们编写Servlet一直是通过实现Servlet接口来编写的,但是,使用这种方法,则必须要实现Servlet接口中定义的所有的方法,即使有一些方法中没有任何东西也要去实现,并且还需要自己手动的维护ServletConfig这个对象的引用。因此,这样去实现Servlet是比较麻烦的。

void init(ServletConfig var1) throws ServletException;

幸好,GenericServlet抽象类的出现很好的解决了这个问题。本着尽可能使代码简洁的原则,GenericServlet实现了Servlet和ServletConfig接口,下面是GenericServlet抽象类的具体代码:

public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {private static final String LSTRING_FILE = "javax.servlet.LocalStrings";private static ResourceBundle lStrings = ResourceBundle.getBundle("javax.servlet.LocalStrings");private transient ServletConfig config;public GenericServlet() {}public void destroy() {}public String getInitParameter(String name) {ServletConfig sc = this.getServletConfig();if (sc == null) {throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));} else {return sc.getInitParameter(name);}}public Enumeration<String> getInitParameterNames() {ServletConfig sc = this.getServletConfig();if (sc == null) {throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));} else {return sc.getInitParameterNames();}}public ServletConfig getServletConfig() {return this.config;}public ServletContext getServletContext() {ServletConfig sc = this.getServletConfig();if (sc == null) {throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));} else {return sc.getServletContext();}}public String getServletInfo() {return "";}public void init(ServletConfig config) throws ServletException {this.config = config;this.init();}public void init() throws ServletException {}public void log(String msg) {this.getServletContext().log(this.getServletName() + ": " + msg);}public void log(String message, Throwable t) {this.getServletContext().log(this.getServletName() + ": " + message, t);}public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;public String getServletName() {ServletConfig sc = this.getServletConfig();if (sc == null) {throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));} else {return sc.getServletName();}}
}

其中,GenericServlet抽象类相比于直接实现Servlet接口,有以下几个好处:

1.为Servlet接口中的所有方法提供了默认的实现,则程序员需要什么就直接改什么,不再需要把所有的方法都自己实现了。
2.提供方法,包围ServletConfig对象中的方法。
3.将init( )方法中的ServletConfig参数赋给了一个内部的ServletConfig引用从而来保存ServletConfig对象,不需要程序员自己去维护ServletConfig了。

public void init(ServletConfig config) throws ServletException {this.config = config;this.init();
}

但是,我们发现在GenericServlet抽象类中还存在着另一个没有任何参数的Init()方法:

public void init() throws ServletException {}

设计者的初衷到底是为了什么呢?在第一个带参数的init()方法中就已经把ServletConfig对象传入并且通过引用保存好了,完成了Servlet的初始化过程,那么为什么后面还要加上一个不带任何参数的init()方法呢?这不是多此一举吗?

当然不是多此一举了,存在必然有存在它的道理。我们知道,抽象类是无法直接产生实例的,需要另一个类去继承这个抽象类,那么就会发生方法覆盖的问题,如果在类中覆盖了GenericServlet抽象类的init()方法,那么程序员就必须手动的去维护ServletConfig对象了,还得调用super.init(servletConfig)方法去调用父类GenericServlet的初始化方法来保存ServletConfig对象,这样会给程序员带来很大的麻烦。GenericServlet提供的第二个不带参数的init( )方法,就是为了解决上述问题的。

这个不带参数的init()方法,是在ServletConfig对象被赋给ServletConfig引用后,由第一个带参数的init(ServletConfig servletconfig)方法调用的,那么这意味着,当程序员如果需要覆盖这个GenericServlet的初始化方法,则只需要覆盖那个不带参数的init( )方法就好了,此时,servletConfig对象仍然有GenericServlet保存着。

说了这么多,通过扩展GenericServlet抽象类,就不需要覆盖没有计划改变的方法。因此,代码将会变得更加的简洁,程序员的工作也会减少很多。

10.HttpServletRequest

因为Request代表请求,所以我们可以通过该对象分别获得HTTP请求的请求行,请求头和请求体。

在前面我们讲过,在service中使用的编码解码方式默认为:ISO-8859-1编码,但此编码并不支持中文,因此会出现乱码问题,所以我们需要手动修改编码方式为UTF-8编码,才能解决中文乱码问题,下面是发生乱码的具体细节:

解决post提交方式的乱码:request.setCharacterEncoding("UTF-8");解决get提交的方式的乱码:parameter = newString(parameter.getbytes("iso8859-1"),"utf-8");

上图在获取请求参数之前调用的意思是,在设置请求体字符编码之前不调用HttpServletRequest的get之类方法,避免发生乱码

上图的?username=wzg168只是一种格式一般都是代表请求参数一般写法是...=...

base标签的作用:


上面两张图可以实现c.html和index.html之间的跳转,但是当我们使用请求转发进行跳转的时候(服务
器默认打开index.html页面),再点击回到a.html的时候就会发现跳转不回去,以上代码执行顺序,服务器先默认打开index.html页面——》点击请求转发a/b/c.html——》c.html然后再点击c.html的的跳回首页就会发生错误,错误原因如下(含base标签作用):

我们只需要改进c.html就行,如下:

11.HttpServletResponse

响应的数据通过两个流传递给客户端, javax.servlet.ServletResponse接口表示一个Servlet响应,在调用Servlet的Service( )方法前,Servlet容器会先创建一个ServletResponse对象,并把它作为第二个参数传给Service( )方法。ServletResponse隐藏了向浏览器发送响应的复杂过程。

PrintWriter getWriter()
获得字符流,通过字符流的write(String s)方法可以将字符串设置到response 缓冲区中,随后Tomcat会将response缓冲区中的内容组装成Http响应返回给浏览器端。

ServletOutputStream getOutputStream()
获得字节流,通过该字节流的write(byte[] bytes)可以向response缓冲区中写入字节,再由Tomcat服务器将字节内容组成Http响应返回给浏览器。

其中的getWriter方法,它返回了一个可以向客户端发送文本的的Java.io.PrintWriter对象。默认情况下,PrintWriter对象使用ISO-8859-1编码(该编码在输入中文时会发生乱码)。

在向客户端发送响应时,大多数都是使用该对象向客户端发送HTML。

还有一个方法也可以用来向浏览器发送数据,它就是getOutputStream,从名字就可以看出这是一个二进制流对象,因此这个方法是用来发送二进制数据的。

在发送任何HTML之前,应该先调用setContentType()方法,设置响应的内容类型,并将“text/html”作为一个参数传入,这是在告诉浏览器响应的内容类型为HTML,需要以HTML的方法解释响应内容而不是普通的文本,或者也可以加上“charset=UTF-8”改变响应的编码方式以防止发生中文乱码现象。

当我们write的数据是中文就可能出现乱码,那么以下是解决中文乱码的问题的方法

方法1:

方法2:

response工作流程

12.请求重定向

请求重定向第一种方法:

上图的setHeader方法的name参数代表新的地址,value代表新的访问地址,可以是工程外的资源比如百度等等

请求重定向第二种方法:

Javaweb基础——Servlet相关推荐

  1. javaweb基础 - Servlet

    引用:Java Web(一) Servlet详解!! Servlet:处理请求和发送响应的过程是由一种叫做Servlet的程序来完成的,通过servlet可以实现动态web开发. <!-- *号 ...

  2. Javaweb基础-servlet应用1

    servlet的两种配置访问方式 Servlet使用Web.xml配置 <?xml version="1.0" encoding="UTF-8"?> ...

  3. index加载显示servlet数据_[WEB篇]-JavaWeb基础与应用-02-Servlet开发

    JavaWeb基础与应用 2.Servlet开发 Servlet是sun公司提供的一门用于开发动态web资源的技术. Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源 ...

  4. javaweb利用servlet与struts2实现可点击刷新的基础图片验证码

    javaweb利用servlet实现图片验证码 验证码是登录验证的技术,可以一定程度防止恶意脚本刷网站,造成服务器压力. 具体实现思想很简单: 首先利用servlet产生一个随机的验证码, 保存在se ...

  5. 超详细的Java面试题总结(四 )之JavaWeb基础知识总结

    系列文章请查看: 超详细的Java面试题总结(一)之Java基础知识篇 超详细的Java面试题总结(二)之Java基础知识篇 超详细的Java面试题总结(三)之Java集合篇常见问题 超详细的Java ...

  6. html与java接口,JavaWeb学习——Servlet相关的接口和类

    JavaWeb学习--Servlet相关的接口和类 摘要:本文主要学习了Servlet相关的接口和类. Servlet的接口和类 三种方式 实现Servlet有三种方式: 实现javax.servle ...

  7. javaweb基础知识点记录2

    javaweb基础知识点记录 1.在service方法中,首先获得请求的方法名,然后根据方法名调用对应的doXXXX方法,比如说请求参数为GET,那么就会去调用doGet方法,请求参数为POST,那么 ...

  8. javaweb基础知识点记录1

    javaweb基础知识点记录 1.当我们通过在浏览器的输入栏中直接输入网址的方式访问网页的时候,浏览器采用的就是GET方法向服务器获取资源. 2.我们可以将Servlet看做是嵌套了HTML代码的ja ...

  9. javaweb(07) Servlet详解

    javaweb(07) Servlet详解 什么是Servlet 简介 从广义上来讲,Servlet规范是Sun公司制定的一套技术标准,包含与web应用相关的一系列接口,是web应用实现方式的宏观解决 ...

最新文章

  1. stm32的时钟系统
  2. mysql数据库搜索字符_在MySQL数据库中快速搜索字符串?
  3. java 全局变量_Javascript中的局部变量、全局变量的详解与var、let的使用区别
  4. 创建性设计模式之2--建造者模式
  5. 写一个判断素数的函数,在主函数输入一个整数,输出是否是素数的消息。
  6. 使用cloudera manager安装Oozie服务【详细步骤】
  7. win10如何修改IP地址
  8. c++ class struct同名_C/C++面向对象编程之封装
  9. JS收集:遍历CHECKBOX
  10. leetcode190-颠倒二进制位
  11. 玩嗨的 2 亿快手“老铁”和幕后的极致视觉算法
  12. c语言结构体调用成员函数,c语言结构体函数调用参数如何设置
  13. 解决mac屏幕不能共享问题
  14. 极通EWEBS远程接入v4.2 XP专版
  15. 遭DeFi反噬,以太坊绝地反击 |链捕手
  16. 如何使用串口调试助手(调试串口)
  17. Fast Global Registration
  18. 无线降噪耳机品牌推荐,值得入手的四款降噪蓝牙耳机
  19. Android 磁场传感器 地磁倾角计算 SensorManager.getInclination方法
  20. FFmpeg 像素格式转换和尺寸转换

热门文章

  1. iPhone X适配小结
  2. 扎扎扎扎扎扎扎扎扎扎扎扎扎扎扎扎扎扎扎扎扎扎心了
  3. protobuf在go中的应用
  4. 连接阿里云和容器技术生态 - 阿里云开源容器项目汇总
  5. Linux c中使用系统时间
  6. 第14条:理解“类对象”的用意
  7. 14招保你ERP选型成功
  8. ASP.net:命名空间“System.Xml”中不存在类型(是缺少程序集引用吗?)
  9. HTML用a标签出现404,404.html
  10. wordpress引入php文件,WordPress主题制作之模板文件的引入方法,wordpress模板