JavaWeb学习笔记(八)--ServletConfig和ServletContext对象介绍

1. ServletConfig对象

在Servlet的配置文件中,可以使用一个或多个<init-param>标签为Servlet配置一些初始化参数。

当Servlet配置初始化参数后,web容器在创建Servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用Servlet的init()方法时,将ServletConfig对象传递个Servlet。进而程序员通过ServletConfig对象就可以得到当前Servlet的初始化参数信息。

本小节使用的API:

// GenericServlet类
ServletConfig getServletConfig() // 获取ServletConfig对象
// ServletConfig类
String getInitParameter(String name); // 根据初始化参数名获取对应的值

Enumeration<String> getInitParameterNames(); // 获取所有的初始化参数名

1.1 在web.xml中配置初始化参数

<servlet>
        <servlet-name>ServletConfigDemo</servlet-name>
        <servlet-class>com.servlet.ServletConfigDemo</servlet-class>
        <init-param>
            <param-name>username</param-name>
            <param-value>schj-bera</param-value>
        </init-param>

        <init-param>
            <param-name>password</param-name>
            <param-value>123456</param-value>
        </init-param>

    </servlet>
    <servlet-mapping>
        <servlet-name>ServletConfigDemo</servlet-name>
        <url-pattern>/ServletConfigDemo</url-pattern>
    </servlet-mapping>

1.2 Servlet中获取ServletConfig,进而获取初始化参数

 1 public class ServletConfigDemo extends HttpServlet {
 2 
 3     // 不用再通过下面这种方式获取,因为HttpServlet的父类GenericServlet已经实现了getServletConfig方法来获取,直接调用即可
 4 //    private ServletConfig config;
 5 //
 6 //    @Override
 7 //    public void init(ServletConfig config) throws ServletException {
 8 //        this.config = config;
 9 //    }
10 
11     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
12 
13     }
14 
15     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
16         ServletConfig config =  this.getServletConfig();
17         // 根据初始化参数名获取对应的值
18         String username = config.getInitParameter("username");
19         String password = config.getInitParameter("password");
20 
21         OutputStream out =  response.getOutputStream();
22         out.write("Use getInitParameter:\n".getBytes());
23         out.write(("username = " + username + "\n").getBytes());
24         out.write(("password = " + password + "\n\n\n").getBytes());
25 
26         out.write("Use getInitParameterNames: \n".getBytes());
27         // 获取所有的初始化参数名
28         Enumeration<String> dates =  config.getInitParameterNames();
29         while (dates.hasMoreElements()) {
30             String name = dates.nextElement();
31             String value = config.getInitParameter(name);
32             out.write((name + " = " + value).getBytes());
33             out.write("\n".getBytes());
34         }
35     }
36 }

2. ServletContext对象

web服务器在启动时,它会为每个web应用程序都创建一个对应的ServletContext对象,它代表当前的web应用。

ServletConfig对象中维护了ServletContext对象的引用,开发人员在编写Servlet时,可以通过ServletConfig.getServletContext方法获取到ServletContext对象。

由于一个web应用中的所有Servlet共享一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。ServletContext对象通常也被称之为context域对象

本小节使用的API:

// GenericServlet类
ServletContext getServletContext() // 获取ServletContext对象
// ServletConfig类
ServletContext getServletContext() // 获取ServletContext对象
// ServletContext类
void setAttribute(String name, Object object)// 将对象绑定到此ServletContext中的给定的属性名称上
Object getAttribute(String name) // 返回给定名称的servlet容器属性,如果该名称没有属性,则返回null
String getInitParameter(String name) // 返回指定名称的初始化参数的值,参数不存在返回null
Enumeration<String> getInitParameterNames() // 返回所有的初始化参数,没有返回一个空的Enumeration
RequestDispatcher getRequestDispatcher(String path) // 返回一个RequestDispatcher对象
InputStream    getResourceAsStream(String path) // 以InputStream方式返回资源文件
String getRealPath(String path) // 返回资源文件的绝对路径

2.1 实现数据共享

 1 /**
 2  * 使用ServletContext对象实现不同Servlet中的数据共享
 3  */
 4 @WebServlet(name = "ServletContextDemo1")
 5 public class ServletContextDemo1 extends HttpServlet {
 6     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 7 
 8     }
 9 
10     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
11         String value = "ServletContextDemo1";
12         /**
13          * 获取ServletContext对象可以使用下面两种方式,推荐使用2
14          * 1. this.getServletConfig().getServletContext()
15          * 2. this.getServletContext()
16          */
17         this.getServletContext().setAttribute("data", value); // 存储数据
18 
19     }
20 }
 1 @WebServlet(name = "ServletContextDemo2")
 2 public class ServletContextDemo2 extends HttpServlet {
 3     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 4 
 5     }
 6 
 7     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 8         String value = (String) this.getServletContext().getAttribute("data"); // 获取数据
 9         System.out.println(value);
10         response.getOutputStream().write(("data=" + value).getBytes());
11     }
12 }

先运行ServletContextDemo1存储数据,再运行ServletContextDemo2获取数据:

2.2 获取Web应用的初始化参数 

应用场景:数据库参数配置

在web.xml中使用<context-param>标签,为整个Web应用配置初始化参数,web服务器启动的时候创建ServletContext对象,会自动把配置的初始化参数封装到ServletContext对象中:

<context-param>
    <param-name>dbUser</param-name>
    <param-value>root</param-value>
</context-param>
<context-param>
    <param-name>dbPassword</param-name>
    <param-value>123456</param-value>
</context-param>
 1 /**
 2  * 使用ServletContext获取Web应用配置的初始化参数
 3  */
 4 @WebServlet(name = "ServletContextDemo3")
 5 public class ServletContextDemo3 extends HttpServlet {
 6     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 7 
 8     }
 9 
10     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
11         ServletContext context = this.getServletContext();
12         String dbUser = context.getInitParameter("dbUser");  // 通过参数名获取对应值
13         String dbPassword = context.getInitParameter("dbPassword");
14 
15         OutputStream out = response.getOutputStream();
16         out.write(("Use function getInitParameter \n").getBytes());
17         out.write(("dbUser="+ dbUser + "\ndbPassword=" + dbPassword + "\n\n\n").getBytes());
18 
19         out.write(("Use function getInitParameterNames \n").getBytes());
20         Enumeration<String> names = context.getInitParameterNames(); // 获取所有的参数名,再根据参数名获取对应的值
21         while (names.hasMoreElements()) {
22             String name = names.nextElement();
23             String value = context.getInitParameter(name);
24             out.write((name + "=" + value + "\n").getBytes());
25         }
26     }
27 }

2.3 实现servlet的转发 

前面已经学过一个重定向,重定向和转发有什么区别:

  • 重定向:你找我,我让你自己去找他             客户机发两次请求
  • 转发:你找我,我帮你去找他                        客户机发一次请求
 1 /**
 2  * 使用ServletContext实现请求的转发
 3  */
 4 @WebServlet(name = "ServletContextDemo4")
 5 public class ServletContextDemo4 extends HttpServlet {
 6     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 7 
 8     }
 9 
10     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
11         RequestDispatcher rd = this.getServletContext().getRequestDispatcher("/ServletContextDemo6");
12         rd.forward(request, response);
13     }
14 }
 1 /**
 2  * 设置响应消息头,实现请求重定向
 3  */
 4 @WebServlet(name = "ServletContextDemo5")
 5 public class ServletContextDemo5 extends HttpServlet {
 6     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 7 
 8     }
 9 
10     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
11         response.setStatus(302);
12         response.setHeader("location", "ServletContextDemo6");
13     }
14 }
 1 @WebServlet(name = "ServletContextDemo6")
 2 public class ServletContextDemo6 extends HttpServlet {
 3     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 4 
 5     }
 6 
 7     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 8         response.getOutputStream().write("ServletContextDemo6".getBytes());
 9     }
10 }

其中ServletContextDemo4实现请求转发,ServletContextDemo5实现请求重定向,两个都转到ServletContextDemo6。

运行结果:

转发只有一次请求

 

 

重定向有两次请求

2.4 读取资源文件

 1 /**
 2  * 使用ServletContext读取资源文件
 3  */
 4 @WebServlet(name = "ServletContextDemo7")
 5 public class ServletContextDemo7 extends HttpServlet {
 6     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 7 
 8     }
 9 
10     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
11 
12         OutputStream out = response.getOutputStream();
13         /**
14          * 资源文件路径以Web应用发布的路径为准,src目录在发布后会拷贝到WEB-INF/classes目录中
15          */
16 
17         // 读取src/db.properties
18         String path1 = "/WEB-INF/classes/db.properties";
19         InputStream in1 = this.getServletContext().getResourceAsStream(path1);
20         String propertiesInfo1 = this.getPropertiesInfo(in1);
21         out.write(propertiesInfo1.getBytes());
22         out.write("\n\n\n".getBytes());
23 
24         // 读取src/com.servlet/db.properties
25         String path2 = "/WEB-INF/classes/com/servlet/db.properties";
26         InputStream in2 = this.getServletContext().getResourceAsStream(path2);
27         String propertiesInfo2 = this.getPropertiesInfo(in2);
28         out.write(propertiesInfo2.getBytes());
29         out.write("\n\n\n".getBytes());
30 
31         // 读取web/db.properties
32         String path3 = "/db.properties";
33         InputStream in3 = this.getServletContext().getResourceAsStream(path3);
34         String propertiesInfo3 = this.getPropertiesInfo(in3);
35         out.write(propertiesInfo3.getBytes());
36         out.write("\n\n\n".getBytes());
37 
38         // 通过ServletContext的getRealPath得到资源的绝对路径后,再通过传统方式读取资源文件
39         String realPath = this.getServletContext().getRealPath(path1);
40         InputStream in = new FileInputStream(realPath);
41         String propertiesInfo4 = this.getPropertiesInfo(in);
42         out.write(propertiesInfo4.getBytes());
43         out.write("\n\n\n".getBytes());
44     }
45 
46     private String getPropertiesInfo(InputStream in) throws IOException {
47         Properties prope = new Properties();
48         prope.load(in);
49         String path = prope.getProperty("path");
50         String dbUser = prope.getProperty("dbUser");
51         String dbPassword = prope.getProperty("dbPassword");
52 
53         return "path=" + path + ", dbUser=" + dbUser + ", dbPassword=" + dbPassword;
54     }
55 
56 }

运行结果:

 3. WEB应用中的普通Java程序读取资源文件

如果读取资源文件的程序不是Servlet,则只能通过类装载器去读:

  1. 通过类装载器,不能加载太大的文件,可能会导致java虚拟机内存溢出
  2. 如果资源文件更新了,服务器没有重启,通过类装载器的方式读取,就不能获取到最新的数据。这时我们可以使用类装载器的方法获取文件路径,再用传统FileInputStream流的方式读取文件,就可以获得更新后的数据。
 1 /**
 2  * Servlet调用其他程序,在其他程序中如何读取资源文件(通过类装载器)
 3  */
 4 @WebServlet(name = "ServletContextDemo8")
 5 public class ServletContextDemo8 extends HttpServlet {
 6     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 7 
 8     }
 9 
10     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
11         UserDao user = new UserDao();
12         user.update();
13     }
14 }
 1 /**
 2  * 如果读取资源文件的程序不是servlet的话;
 3    就只能通过类转载器去读了,文件不能太大;
 4    用传递参数方法不好,耦合性高
 5  */
 6 public class UserDao {
 7 
 8     private static Properties dbconfig = new Properties();
 9     private static String path = "";
10     private static String path1 = "";
11     private static String path2 = "";
12     static {
13         // 类装载器只会加载一次,当db.properties文件修改时,就无法得到更新后的数据
14 //        try {
15 //            InputStream in = UserDao.class.getClassLoader().getResourceAsStream("db.properties");
16 //            dbconfig.load(in);
17 //        } catch (IOException e) {
18 //            throw new ExceptionInInitializerError(e);
19 //        }
20 
21         // 可以通过类加载的方式得到资源文件的路径,再通过传统方式读取文件内容,这样可以获得更新后的数据
22         path  = UserDao.class.getClassLoader().getResource("db.properties").getPath();
23 //        path1  = UserDao.class.getClassLoader().getResource("/com/servlet/db.properties").getPath();  // servlet目录下的资源文件
24 //        path2  = UserDao.class.getClassLoader().getResource("../../db.properties").getPath();   //Web应用根目录下的资源文件
25         try {
26             path =java.net.URLDecoder.decode(path, "UTF-8"); // 文件路径如果有空格,则需要转码,否则系统会找不到文件
27             path1 =java.net.URLDecoder.decode(path1, "UTF-8");
28             path2 =java.net.URLDecoder.decode(path2, "UTF-8");
29         } catch (UnsupportedEncodingException e) {
30             e.printStackTrace();
31         }
32 
33     }
34     public void update() throws IOException {
35         // 读取资源文件数据
36         InputStream in = new FileInputStream(path);
37         dbconfig.load(in);
38         System.out.println("path=" + dbconfig.getProperty("path")
39                 + ", dbUser=" + dbconfig.getProperty("dbUser")
40                 + ", dbPassword=" + dbconfig.getProperty("dbPassword"));
41     }
42 }

运行结果:

修改修改classes下的配置文件,无须重启服务器,即可获取最新结果:

 

posted @ 2019-02-27 12:49  暴躁的毛毛熊  阅读(272)  评论(0编辑  收藏  举报