Servlet第二篇【Servlet调用图、Servlet细节、ServletConfig、ServletContext】(下)

ServletConfig对象

ServletConfig对象有什么用?

通过此对象可以读取web.xml中配置的初始化参数。

现在问题来了,为什么我们要把参数信息放到web.xml文件中呢?我们可以直接在程序中都可以定义参数信息,搞到web.xml文件中又有什么好处呢

好处就是:能够让你的程序更加灵活【更换需求,更改配置文件web.xml即可,程序代码不用改】

获取web.xml文件配置的参数信息

  • 为Demo1这个Servlet配置一个参数,参数名是name,值是zhongfucheng
 <servlet>
        <servlet-name>Demo1</servlet-name>
        <servlet-class>zhongfucheng.web.Demo1</servlet-class>
        <init-param>
            <param-name>name</param-name>
            <param-value>zhongfucheng</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>Demo1</servlet-name>
        <url-pattern>/Demo1</url-pattern>
    </servlet-mapping>

在Servlet中获取ServletConfig对象,通过ServletConfig对象获取在web.xml文件配置的参数

Servlet第二篇【Servlet调用图、Servlet细节、ServletConfig、ServletContext】(下)

ServletContext对象

什么是ServletContext对象?

当Tomcat启动的时候,就会创建一个ServletContext对象。它代表着当前web站点

ServletContext有什么用?

  1. ServletContext既然代表着当前web站点,那么所有Servlet都共享着一个ServletContext对象,所以Servlet之间可以通过ServletContext实现通讯
  2. ServletConfig获取的是配置的是单个Servlet的参数信息,ServletContext可以获取的是配置整个web站点的参数信息
  3. 利用ServletContext读取web站点的资源文件
  4. 实现Servlet的转发【用ServletContext转发不多,主要用request转发】

Servlet之间实现通讯

ServletContext对象可以被称之为域对象

到这里可能有一个疑问,域对象是什么呢?其实域对象可以简单理解成一个容器【类似于Map集合】

实现Servlet之间通讯就要用到ServletContext的setAttribute(String name,Object obj)方法,第一个参数是关键字,第二个参数是你要存储的对象

  • 这是Demo2的代码
 //获取到ServletContext对象
        ServletContext servletContext = this.getServletContext();

        String value = "zhongfucheng";

        //MyName作为关键字,value作为值存进   域对象【类型于Map集合】
        servletContext.setAttribute("MyName", value);

这是Demo3的代码

//获取ServletContext对象
        ServletContext servletContext = this.getServletContext();

        //通过关键字获取存储在域对象的值
        String value = (String) servletContext.getAttribute("MyName");

        System.out.println(value);

访问Demo3可以获取Demo2存储的信息,从而实现多个Servlet之间通讯

Servlet第二篇【Servlet调用图、Servlet细节、ServletConfig、ServletContext】(下)

获取web站点配置的信息

如果我想要让所有的Servlet都能够获取到连接数据库的信息,不可能在web.xml文件中每个Servlet中都配置一下,这样代码量太大了!并且会显得非常啰嗦冗余。

  • web.xml文件支持对整个站点进行配置参数信息【所有Servlet都可以取到该参数信息】
 <context-param>
        <param-name>name</param-name>
        <param-value>zhongfucheng</param-value>
    </context-param>

Demo4代码

//获取到ServletContext对象
        ServletContext servletContext = this.getServletContext();

        //通过名称获取值
        String value = servletContext.getInitParameter("name");
        System.out.println(value);

Servlet第二篇【Servlet调用图、Servlet细节、ServletConfig、ServletContext】(下)

试一下Demo3是否能拿到,相同的代码

  //获取到ServletContext对象
        ServletContext servletContext = this.getServletContext();

        //通过名称获取值
        String value = servletContext.getInitParameter("name");
        System.out.println(value);

Servlet第二篇【Servlet调用图、Servlet细节、ServletConfig、ServletContext】(下)

读取资源文件

第一种方式:

  • 现在我要通过Servlet111读取1.png图片

Servlet第二篇【Servlet调用图、Servlet细节、ServletConfig、ServletContext】(下)

  • 按我们以前的方式,代码应该是这样的。

FileInputStream fileInputStream = new FileInputStream("1.png");

        System.out.println(fileInputStream);

  • 当我们访问的时候,却出错了!说找不到1.png文件
    Servlet第二篇【Servlet调用图、Servlet细节、ServletConfig、ServletContext】(下)
  • 这是为什么呢?我们以前读取文件的时候,如果程序和文件在同一包名,可以直接通过文件名称获取得到的!,原因很简单,以前我们写的程序都是通过JVM来运行的,而现在,我们是通过Tomcat来运行的
  • 根据web的目录规范,Servlet编译后的class文件是存放在WEB-INF\classes文件夹中的Servlet第二篇【Servlet调用图、Servlet细节、ServletConfig、ServletContext】(下)
  • 看到这里,我们知道了要进入classes目录中读取文件,所以我们将代码改成以下方式
  FileInputStream fileInputStream = new FileInputStream("D:\\zhongfucheng\\web\\WEB-INF\\classes\\zhongfucheng\\web\\1.png");
        System.out.println(fileInputStream);
  • 再去读取时,就发现可以获取到文件了。
  • 但是现在问题又来了,我读取文件的时候都要写上绝对路径,这样太不灵活了。试想一下,如果我将该读取文件的模块移到其他的web站点上,我的代码就又要修改了【因为web站点的名字不一样】。
  • 我们通过ServletContext读取就可以避免修改代码的情况,因为ServletContext对象是根据当前web站点而生成的
  • 代码如下所示:
//获取到ServletContext对象
        ServletContext servletContext = this.getServletContext();

        //调用ServletContext方法获取到读取文件的流
        InputStream inputStream = servletContext.getResourceAsStream("/WEB-INF/classes/zhongfucheng/web/1.png");

第二种方式:

  • 如果我的文件放在web目录下,那么就简单得多了!,直接通过文件名称就能获取Servlet第二篇【Servlet调用图、Servlet细节、ServletConfig、ServletContext】(下)
  • 代码如下所示
//获取到ServletContext对象
        ServletContext servletContext = this.getServletContext();

        //调用ServletContext方法获取到读取文件的流
        InputStream inputStream = servletContext.getResourceAsStream("2.png");

Servlet第二篇【Servlet调用图、Servlet细节、ServletConfig、ServletContext】(下)

第三种方式:

通过类装载器读取资源文件

  • 我的文件放在了src目录下【也叫做类目录】Servlet第二篇【Servlet调用图、Servlet细节、ServletConfig、ServletContext】(下)
  • 代码如下所示
//获取到类装载器
        ClassLoader classLoader = Servlet111.class.getClassLoader();

        //通过类装载器获取到读取文件流
        InputStream inputStream = classLoader.getResourceAsStream("3.png");

Servlet第二篇【Servlet调用图、Servlet细节、ServletConfig、ServletContext】(下)

我的文件放在了src目录下的包下

Servlet第二篇【Servlet调用图、Servlet细节、ServletConfig、ServletContext】(下)

代码如下,添加包名路径即可。

 //获取到类装载器
        ClassLoader classLoader = Servlet111.class.getClassLoader();

        //通过类装载器获取到读取文件流
        InputStream inputStream = classLoader.getResourceAsStream("/zhongfucheng/web/1.png");

原则:如果文件太大,就不能用类装载器的方式去读取,会导致内存溢出

如果文章有错的地方欢迎指正,大家互相交流。


上一篇:python管理mysql,请叫我雷锋


下一篇:在阿里云服务器(Ubuntu系统)下使用WordPress搭建博客网站教程