侧边栏壁纸
博主头像
coydone博主等级

记录学习,分享生活的个人站点

  • 累计撰写 306 篇文章
  • 累计创建 51 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

HttpServlet和ServletContext

coydone
2022-02-05 / 0 评论 / 0 点赞 / 318 阅读 / 9,127 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-04-09,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

HttpServlet

HttpServlet概述

HttpServlet类是GenericServlet的子类,它提供了对HTTP请求的特殊支持,所以通常我们都会通过继承HttpServlet来完成自定义的Servlet。

HttpServlet覆盖了service()方法

HttpServlet类中提供了service(HttpServletRequest,HttpServletResponse)方法,这个方法是HttpServlet自己的方法,不是从Servlet继承来的。在HttpServlet的service(ServletRequest,ServletResponse)方法中会把ServletRequest和ServletResponse强转成HttpServletRequest和HttpServletResponse,然后调用service(HttpServletRequest,HttpServletResponse)方法,这说明子类可以去覆盖service(HttpServletRequest,HttpServletResponse)方法即可,这就不用自己去强转请求和响应对象了。其实子类也不用去覆盖service(HttpServletRequest,HttpServletResponse)方法,因为HttpServlet还要做另一步简化操作。

doGet()/doPost()

在HttpServlet的 service(HttpServletRequest,HttpServletResponse) 方法会去判断当前请求是GET还是POST,如果是GET请求,那么会去调用本类的doGet()方法,如果是POST请求会去调用doPost()方法,这说明我们在子类中去覆盖doGet()或doPost()方法即可。

Servlet细节

  • 不要在Servlet中创建成员变量,创建局部变量即可。

  • 可以创建无状态成员。

  • 可以创建有状态的成员,但状态必须为只读的。

Servlet与线程安全

因为一个类型的Servlet只有一个实例对象,那么就有可能会现同一个Servlet同时处理多个请求,那么Servlet是否为线程安全的呢?答案是:“不是线程安全的”。这说明Servlet的工作效率很高,但也存在线程安全问题。

所以我们不应该在Servlet中随便创建成员变量,因为可能会存在一个线程对这个成员变量进行写操作,另一个线程对这个成员变量进行读操作。

让服务器在启动时就创建Servlet

默认情况下,服务器会在某个Servlet第一次收到请求时创建它。也可以在web.xml中对Servlet进行配置,使服务器启动时就创建Servlet。

<servlet>
    <servlet-name>hello1</servlet-name>
    <servlet-class>com.coydone.servlet.Hello1Servlet</servlet-class>
    <load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>hello1</servlet-name>
    <url-pattern>/hello1</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>hello2</servlet-name>
    <servlet-class>com.coydone.servlet.Hello2Servlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>hello2</servlet-name>
    <url-pattern>/hello2</url-pattern>
</servlet-mapping>
<servlet>
    <servlet-name>hello3</servlet-name>
    <servlet-class>com.coydone.servlet.Hello3Servlet</servlet-class>
    <load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>hello3</servlet-name>
    <url-pattern>/hello3</url-pattern>
</servlet-mapping>

<servlet>元素中配置<load-on-startup>元素可以让服务器在启动时就创建该Servlet,其中<load-on-startup>元素的值必须是大于等于的整数,它的使用是服务器启动时创建Servlet的顺序。上例中,根据<load-on-startup>的值可以得知服务器创建Servlet的顺序为Hello1Servlet、Hello2Servlet、Hello3Servlet。

ServletContext

一个项目只有一个ServletContext对象。我们可以在n个Servlet中来获取这个唯一的对象,使用它可以给多个Servlet传递数据。这个对象在Tomcat启动时就创建,在Tomcat关闭时才会销毁。

ServletContext概述

指实际存在的一个Web应用,所以web程序发布服务器上面,服务器产生一个ServletContext服务器会为每个应用创建一个ServletContext对象:

  • ServletContext对象的创建是在服务器启动时完成的;init()初始化的方法。

  • ServletContext对象的销毁是在服务器关闭时完成的。destroy()。

ServletContext对象的作用是在整个Web应用的动态资源之间共享数据。例如在AServlet中向ServletContext对象中保存一个值,然后在BServlet中就可以获取这个值,这就是共享数据了。

服务器启动的时候,为每个WEB应用创建一个单独的ServletContext对象,我们可以使用这个对象存取数据,用这个对象存取的数据可以在整个WEB应用中获得。可以使用如下方法存取数据:

  • setAttribute(String name,Object object):向ServletContext中存数据。

  • getAttribute(String name):从ServletContext中取数据。

  • removeAttribute(name):从ServletContext中移除数据。

ServletContext 类的四个作用:

  • 获取 web.xml 中配置的上下文参数 context-param。

  • 获取当前的工程路径,格式:/工程路径。

  • 获取工程部署后在服务器硬盘上的绝对路径。

  • 像 Map 一样存取数据。

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 1、获取 web.xml 中配置的上下文参数context-param
    ServletContext context = getServletConfig().getServletContext();
    String username = context.getInitParameter("username");
    System.out.println("context-param 参数 username 的值是:" + username);
    System.out.println("context-param 参数 password 的值是:" + context.getInitParameter("password"));
    // 2、获取当前的工程路径,格式: /工程路径
    System.out.println( "当前工程路径:" + context.getContextPath() );
    // 3、获取工程部署后在服务器硬盘上的绝对路径 
    // / 斜杠被服务器解析地址为:http://ip:port/工程名/ 映射到 IDEA 代码的 web 目录
    System.out.println("工程部署的路径是:" + context.getRealPath("/")); 
    System.out.println("工程下 css 目录的绝对路径是:" + context.getRealPath("/css")); 
    System.out.println("工程下 imgs 目录 1.jpg 的绝对路径是:" + context.getRealPath("/imgs/1.jpg")); 
}

web.xml 中的配置:

<!--context-param 是上下文参数(它属于整个 web 工程)-->
<context-param> 
    <param-name>username</param-name>
    <param-value>context</param-value>
</context-param> 
<!--context-param 是上下文参数(它属于整个 web 工程)-->
<context-param> 
    <param-name>password</param-name>
    <param-value>root</param-value>
</context-param>

ServletContext 像 Map 一样存取数据:ContextServlet1 代码

public class ContextServlet1 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取 ServletContext 对象
        ServletContext context = getServletContext();
        System.out.println(context);
        System.out.println("保存之前: Context1 获取 key1 的值是:"+ context.getAttribute("key1"));
        context.setAttribute("key1", "value1");
        System.out.println("Context1 中获取域数据 key1 的值是:"+ context.getAttribute("key1"));
    }
}

ContextServlet2 代码:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException {
    ServletContext context = getServletContext();
    System.out.println(context);
    System.out.println("Context2 中获取域数据 key1 的值是:"+ context.getAttribute("key1"));
}

获取ServletContext

ServletConfig#getServletContext();
GenericServlet#getServletContext();
HttpSession#getServletContext()
ServletContextEvent#getServletContext()

在Servlet中获取ServletContext对象:

  • 在void init(ServletConfig config)中:ServletContext context = config.getServletContext();,ServletConfig类的getServletContext()方法可以用来获取ServletContext对象。

在GenericeServlet或HttpServlet中获取ServletContext对象:

  • GenericServlet类有getServletContext()方法,所以可以直接使用this.getServletContext()来获取。
public class MyServlet implements Servlet {
    public void init(ServletConfig config) {
        ServletContext context = config.getServletContext();
    }
    ...
}

public class MyServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) {
        ServletContext context = this.getServletContext();
    }
}

域对象的功能

ServletContext是JavaWeb四大域对象之一:PageContext、ServletRequest、HttpSession、ServletContext。

所有域对象都有存取数据的功能,因为域对象内部有一个Map,用来存储数据,ServletContext对象用来操作数据的方法:

  • void setAttribute(String name, Object value):用来存储一个对象,也可以称之为存储一个域属性,例如:servletContext.setAttribute(“xxx”, “XXX”),在ServletContext中保存了一个域属性,域属性名称为xxx,域属性的值为XXX。注意,如果多次调用该方法,并且使用相同的name,那么会覆盖上一次的值,这一特性与Map相同。

  • Object getAttribute(String name):用来获取ServletContext中的数据,当前在获取之前需要先去存储才行,例如:String value = (String)servletContext.getAttribute(“xxx”);,获取名为xxx的域属性。

  • void removeAttribute(String name):用来移除ServletContext中的域属性,如果参数name指定的域属性不存在,那么本方法什么都不做。

  • Enumeration getAttributeNames():获取所有域属性的名称。

获取应用初始化参数

Servlet也可以获取初始化参数,但它是局部的参数。也就是说,一个Servlet只能获取自己的初始化参数,不能获取别人的,即初始化参数只为一个Servlet准备。

可以配置公共的初始化参数,为所有Servlet而用,这需要使用ServletContext才能使用。还可以使用ServletContext来获取在web.xml文件中配置的应用初始化参数。注意,应用初始化参数与Servlet初始化参数不同。

web.xml

<web-app ...>
    ...
    <context-param>
        <param-name>paramName1</param-name>
        <param-value>paramValue1</param-value>      
    </context-param>
    <context-param>
        <param-name>paramName2</param-name>
        <param-value>paramValue2</param-value>      
    </context-param>
</web-app>
ServletContext context = this.getServletContext();
String value1 = context.getInitParameter("paramName1");
String value2 = context.getInitParameter("paramName2");
System.out.println(value1 + ", " + value2);

Enumeration names = context.getInitParameterNames();
while(names.hasMoreElements()) {
    System.out.println(names.nextElement());
}

ServletConfig类

ServletConfig类的作用:

  • 可以获取 Servlet 程序的别名 servlet-name 的值 。

  • 获取初始化参数 init-param。

  • 获取 ServletContext 对象。

web.xml 中的配置:

<!-- servlet 标签给 Tomcat 配置 Servlet 程序 --> 
<servlet> 
    <!--servlet-name 标签 Servlet 程序起一个别名(一般是类名) --> 
    <servlet-name>HelloServlet</servlet-name>
    <!--servlet-class 是 Servlet 程序的全类名--> 
    <servlet-class>com.coydone.servlet.HelloServlet</servlet-class> 
    <!--init-param 是初始化参数--> 
    <init-param> 
        <!--是参数名--> 
        <param-name>username</param-name> 
        <!--是参数值--> 
        <param-value>root</param-value> 
    </init-param> 
    <!--init-param 是初始化参数--> 
    <init-param> 
        <!--是参数名--> 
        <param-name>url</param-name> 
        <!--是参数值--> 
        <param-value>jdbc:mysql://localhost:3306/test</param-value> 
    </init-param> 
</servlet> 
<!--servlet-mapping 标签给 servlet 程序配置访问地址--> 
<servlet-mapping> 
    <!--servlet-name 标签的作用是告诉服务器,我当前配置的地址给哪个 Servlet 程序使用-->        
    <servlet-name>HelloServlet</servlet-name> 
    <!--url-pattern 标签配置访问地址 <br/> / 斜杠在服务器解析的时候,表示地址为:http://ip:port/工程路径 <br/> /hello 表示地址为:http://ip:port/工程路径/hello <br/> --> 
    <url-pattern>/hello</url-pattern> 
</servlet-mapping>

Servlet 中的代码:

@Override 
public void init(ServletConfig servletConfig) throws ServletException { 
    System.out.println("2 init 初始化方法"); 
    // 1、可以获取 Servlet 程序的别名 servlet-name 的值 
    System.out.println("HelloServlet 程序的别名是:" + servletConfig.getServletName()); 
    // 2、获取初始化参数 init-param System.out.println("初始化参数 username 的值是;" + servletConfig.getInitParameter("username"));
    System.out.println("初始化参数 url 的值是;" + servletConfig.getInitParameter("url")); 
    // 3、获取 ServletContext 对象 
    System.out.println(servletConfig.getServletContext());
}
0

评论区