Servlet详解

本文详细解析Servlet的工作原理,包括Servlet的生命周期、Tomcat如何处理HTTP请求与响应,以及创建Servlet的具体步骤。探讨了为什么通常继承HttpServlet而非实现Servlet接口,解释了service、doGet和doPost方法的使用场景。
摘要由CSDN通过智能技术生成

1.什么是Servlet?

JavaServlet是运行在WEB服务器上或应用服务器上的程序,它是作为来自WEB浏览器或者其他HTTP请求客户端和请求和HTTP服务器上的数据库或者应用程序的中间层(处理http请求与响应)

 2.启动web服务器时Servlet做了什么事情(tomcat为例)

tomcat是一个web应用服务器,是一个Servlet/Jsp容器,tomcat作为Servlet的容器,负责把收到来自于web的请求传送给Servlet,并负责把Servlet的响应传送给客户端,而Servlet是运行在支持JAVA语言的服务器上的组件

tomcat将http请求文本接收并解析,然后封装成HttpServletRequest类型request对象,所有http请求头数据可通过request对象调用对应的方法的获取到

tomcat同时会将响应信息封装成HttpServletResponse类型response对象,通过response属性就可以控制输出到浏览器内容,然后将response交给tomcat,tomcat会将其变成响应文本格式发送给浏览器

3.详解创建Servlet创建原理

3.1servlet的生命周期

3.2为什么创建servlet是继承HttpServlet,而不是实现Servlet接口

3.3在servlet的生命周期中是执行service方法,为什么我们只需要写dopost和doget方法

3.1servlet的生命周期是什么?

当web.xml的load-on-startup大于等于0时,服务器启动时就会初始化一个Servlet对象,也就是执行init(ServletConfig,conf)方法

当web.xml的load-on-startup不设置或者小于0,在第一次请求时会初始化一个Servlet对象

初始化的Servlet对象会去处理所有来自客户端的请求,在service(ServletRequest req, ServletResponse res)里执行

最后服务器关闭时才会销毁这个对象,执行destroy()方法

3.2在创建Servlet时候是去继承HttpServlet类,而不是实现Servlet接口

3.3在初始化对象去处理请求的时候调用的是service方法,为什么我们只需要写dopost和doget方法

public class TestControl extends HttpServlet

public abstract class HttpServlet extends GenericServlet

public abstract class GenericServlet
    implements Servlet, ServletConfig, java.io.Serializable

由类关系我们可知,HttpServlet继承了GenericServlet,GenericServlet实现了Servlet接口

Servlet接口中主要定义了三个方法:init(ServletCobnfig, conf) service(ServletRequest req, ServletResponse res) destroy ()方法

getServletConfig()主要是获取ServletConfig对象,ServletConfig对象可以获取到servlet一些信息

因此Servlet接口的作用是三个生命周期运行方法,获取ServletConfig方法,通过ServletConfig可以获取到ServletContext,通过继承GenericServlet我们就可以使用Servlet的方法,能拿到ServletConfig,也可以拿到ServletContext,那样太麻烦了,所以我们可以看到GenericServlet也直接实现了ServletConfig接口,这样我们也就直接就可以拿到ServletContext信息

在GenericServlet中有两个init方法

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

public void init() throws ServletException {

    }

一个成员变量

    private transient ServletConfig config;


getServletConfig()

public ServletConfig getServletConfig(){return config}

在init(ServletConfig config)方法中,为了方便在其他地方亦可以使用ServletConfig对象,而不仅仅局限在init(ServletConfig,config)方法中,所以创建了一个私有成员变量config,在init(ServletConfig config)方法中就将其赋值给config,然后通过getServletConfig()方法就能够获取ServletConfig对象了,但是在init(ServletConfig config)中还调用了一个

init()方法,并且这个init()方法是空的,什么读也没有,这是为什么呢?

当我们需要在init方法中做一点别的事情,我们想到的方法就是继承GenericServlet中init(ServletConfig config)方法,这样依赖,

就破坏了原本在GnereicServlet类中的init(ServletConfig config)写的代码,也就是在GenericServlet类中成员变量config就一直

是null,无法得到赋值,因为被重写了,就不会在执行GenericServlet中init(ServletConfig config)方法中代码。要想赋值就必须在重写init(ServletConfig config)方法中调用父类的init(ServletConfig config)方法,也就是super.init(ServletConfig config),这样依赖,就很不方便。所以在GenericServlet类中增加了一个init()方法,以后需要在init方法中需要初始化别的数据,只需要重写init()方法,而不需要去覆盖(ServletConfig config)这个方法。

public abstract void service(ServletRequest req, ServletResponse res)
    throws ServletException, IOException;

在GenericServlet类中并没有实现service方法,而想到的是他的子类实现了,那就是HttpServlet

   public void service(ServletRequest req, ServletResponse res)
        throws ServletException, IOException
    {
        HttpServletRequest  request;
        HttpServletResponse response;
        
        if (!(req instanceof HttpServletRequest &&
                res instanceof HttpServletResponse)) {
            throw new ServletException("non-HTTP request or response");
        }

        request = (HttpServletRequest) req;
        response = (HttpServletResponse) res;

        service(request, response);
    }

从HttpServlet代码我们可以知道将传过来的ServletRequest强制转换成了HttpServletRequest类型,ServletResponse强制转换成了HttpServletRespnse类型

该方法主要是去执行判断是那种请求方法一般是get或者post,然后调用到相应请求方式函数中,这样我们就知道了写Servlet时为什么只需要重写dopost或者doget方法

四、几大重点对象讲解:

ServletConfig对象(通过getServletConfig获取):

getServletName():获取Servlet名称,在web.xml中的Servlet-name

getInitParameter():获取Servlet对象初始化参数的值,获取的是在web.xml中Servlet节点下init参数的值

getInitParameterNames():获取Servlet中所有初始化参数的名字,返回的是枚举类型

ServletContext对象:获取方式getServletContext(),或者getServletConfig.getServletContext()我们只需要使用第一种就行

功能:tomcat为每个web项目都创建一个ServletContext实例,tomcat在启动时创建,服务器关闭时销毁,在一个web项目中共享数据,管理web项目资源,为整个web配置公共信息等,通俗来说,就是一个web项目,就存在一个ServletContext实例,每个Servlet都可以访问他。

1、web项目中共享数据,getAttribute(String name)\setAttribute(String name, Object obj),removeAttribute(String name)

setAttribute(String name, Object obj)在web项目中范围内存放内容以便让在web项目中所有的Servlet都能访问

2.整个web项目初始化参数(全局参数),每个Servlet都能获取到该初始化值

getInitParameter(String name) 通过指定名称获取初始化值

getInitParameterNames()获取枚举类型

web.xml配置整个web项目的初始化

3、获取web项目资源

3.1获取web项目下指定的资源路径:getServletContext().getRealPath("/WEB-INF/web.xml")

3.2获取web项目下指定资源的内容,返回的是字节输入流。InputStream getResourceAsStream(java.lang.String.path)

 等等。。

request对象:将请求文本封装成的对象,所以通过request能获得请求文本的所有内容,请求头、请求体、请求行

1、请求行内容获取

实际访问路径 http://localhost:8080/day08/Demo05Servlet?username=jack&password=1234

统一资源标记符:String uri = request.getReuqestURI() (/day8/Demo05Servlet)

统一资源定位符:StringBuffer url = request.getRequestURL()( http://localhost:8080/day08/Demo05Servlet)

协议和版本: String protocol = request.getProtocol()(HTTP/1.1)

协议:String scheme = request.getScheme()(http)

主机(域名) : String serverName = request.getServerName()(localhost)

端口: int port = request.getServerPort()(8088)

发布到tomcat下的项目名称:String contextPath = request.getContextPath()

Servlet路径: String servletPath = request.getServletPath()(/Demo05Servlet)

所有请求参数:String queryString = request.getQueryString()(username=jack&password=1234)

远程主机ip地址: String remoteAddr = request.getRemoteAddr()

2.请求头获取

String getHeader(java.lang.String name)获取指定头内容String

long getDateHeader(java.lang.String name) 获得指定头内容Date

int getInitHeader(java.lang.String name)获得指定头内容int

Enumeration getHeaders(java.lang.String name)获取指定名称所有内容

3请求体获取(GET/POST)

String request.getParameter(String)获得指定名称,一个请求参数值

String[] request.getParameterValues(String)获得指定名称,例如checkbox,select等

Map<String, String[]> request.getParameterMap()获得所有的请求参数

4.请求转发

request.getRequestDispatcher(String path).forward(request,response);  //path:转发后跳转的页面,这里不管用不用“/”开头,都是以web项目根开始,因为这是请求转发,请求转发只局限在=与在同一个web项目下使用,所以这里一直都是从web项目根下开始的

web项目根:

开发:G:\Workspaces\test01\WebRoot\...

运行时:D:\java\tomcat\apache-tomcat-7.0.53\webapps\test01\

web站点根:

运行时:D:\java\tomcat\apache-tomcat-7.0.53\webapps\

从这里可以看出,web项目根就是从该web项目名开始,所以我们请求转发时,只需要接着项目名后面需要访问路径写就行了

特点:浏览器中的url不会改变,也就是浏览器不知道服务器做了什么,是服务器帮我们跳转页面,并且转发后的页面,能够继续使用原先的request,因为是原先的request,所以request域中的属性都可以继续获取到

response对象:

常用的一个方法就是:response.setHeader(java.lang.String name, java.lang.String value)设置指定的头,一般常用

例如:设置每隔3秒就自动刷新一次

response.setHeader('Refresh',3)

重定向(页面跳转)

方式一:response.setStatus(302); //状态码302就代表重定向response.setHeader('location','http://www.baidu.com')

方式二:使用封装好的,通过response.sendRedirect('http://www.baidu.com')

特点:服务器告诉浏览器要跳转的页面,是浏览器主动去跳转的页面,浏览器知道,也浏览器的地址栏中url会改变,是浏览器重新发起一个请求道另外页面页面,所以request是重新发起的根请求转发不一样

注意:response.sendRedirect(path)

response.sendRedirect('/test01/MyServlet01');使用了‘/’开头表名从web站点根开始

response.sendRedirect('MyServlet'); 没有使用'/'开头,说明是从web项目根开始,所以无需写test01

参考文章地址:https://www.cnblogs.com/whgk/p/6399262.html

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值