day05
01-servlet入门
1.Servlet简介


service(ServletRequest req, ServletResponse res),客户端的请求和响应都会通过这个方法传递,


package cn.itcast; import java.io.*; import javax.servlet.*; //这里继承GenericServlet成为一个Servlet public class FirstServlet extends GenericServlet{ public void service(ServletRequest req, ServletResponse res) throws ServletException,java.io.IOException { OutputStream out = res.getOutputStream(); out.write("hello servlet!!!".getBytes()); //其实这里可以不用关闭流的,因为servlet是给服务器调用的,当这个servlet结束后服务器会自动关掉这个流 out.close(); } }
写好servelt之后我们在cmd中编译


<?xml version="1.0" encoding="UTF-8"?> <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <!--servlet的名字和路径--> <servlet> <servlet-name>FirstServlet</servlet-name> <servlet-class>cn.itcast.FirstServlet</servlet-class> </servlet> <!--servlet的名字和访问路径--> <servlet-mapping> <servlet-name>FirstServlet</servlet-name> <url-pattern>/servlet/FirstServlet</url-pattern> </servlet-mapping> </web-app>
现在我们就可以在浏览器中输入http://localhost:8080/day05/servlet/FirstServlet访问这个servlet,就会在浏览器中显示hello serlvet!!!
02-servlet调用uml图
1.Servlet的运行过程

03-servlet实现类、eclipse创建servlet
1.servlet的运行过程(祥哥版)








2.在Eclipse中开发Servlet









package cn.itcast.servlet; import java.io.IOException; import java.io.OutputStream; import javax.servlet.GenericServlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class FirstServlet extends GenericServlet { public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { OutputStream out = res.getOutputStream(); out.write("hello servelt".getBytes()); } }
写完一个servlet之后我们还要为这个servelt映射一个访问路径,我们可以在web.xml中去做
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet> <servlet-name>FirstServlet</servlet-name> <servlet-class>cn.itcast.servlet.FirstServelt</servlet-class> </servlet> <servlet-mapping> <servlet-name>FirstServlet</servlet-name> <url-pattern>/servlet/FirstServlet</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
做好这些之后,我们还需要给MyEclipse配置一个服务器
Windows-Preferences然后我们搜索Tomcat,在这里我们只指定Tomcat6.0的目录


然后我们还可以为tomcat指定jdk,一般我们不指定,我们用MyEclipse默认的jdk

然后我们还要设置运行方式Launch,这里我们设置运行方式为debug方式,不然在以后的开发中无法调试

设置好服务器之后我们将程序发布到服务器中,由于之前我们手动创建了一个day05,所以这里重复了,我们需要将手动创建那个备份,我们选择第一个

然后开启服务器我们发现报错了

这个是由于我们开始手动创建的那个day05,也就是备份的那个java程序是用jdk 7.0编译的
然而我们这里MyEclipse中我们配置的tomcat服务器运行环境是jdk6.0的,高版本编译的程序,不能用低版本的虚拟机运行,所以就会报java.lang.UnsupportedClassVersionError
我们只需要将备份的那个day05删除就可以运行或者将MyEclipse中的服务器运行环境改成jdk7.0
我们这里选择删除备份,之后运行正常

删除之后我们在浏览器中访问这个servlet
http://localhost:8080/day05/servlet/FirstServlet

3.Servlet接口实现类



package cn.itcast.servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class SecondServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getOutputStream().write("hello servlet".getBytes()); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //无论是通过get还是post请求,我这里一律转给dogGet方法处理 doGet(request,response); } }
在MyEclipse中当我们创建一个Servlet,MyEclipse会自动会在web.xml中为我们映射这个资源
/day05/WebRoot/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet> <servlet-name>FirstServlet</servlet-name> <servlet-class>cn.itcast.servlet.FirstServlet</servlet-class> </servlet> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>SecondServlet</servlet-name> <servlet-class>cn.itcast.servlet.SecondServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>FirstServlet</servlet-name> <url-pattern>/servlet/FirstServlet</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>SecondServlet</servlet-name> <url-pattern>/servlet/SecondServlet</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
4.修改servlet模板
#---------------------------------------------# # <aw:description>Template for Servlet</aw:description> # <aw:version>1.1</aw:version> # <aw:date>04/05/2003</aw:date> # <aw:author>Ferret Renaud</aw:author> #---------------------------------------------# <aw:import>java.io.IOException</aw:import> <aw:import>java.io.PrintWriter</aw:import> <aw:import>javax.servlet.ServletException</aw:import> <aw:import>javax.servlet.http.HttpServlet</aw:import> <aw:import>javax.servlet.http.HttpServletRequest</aw:import> <aw:import>javax.servlet.http.HttpServletResponse</aw:import> <aw:parentClass>javax.servlet.http.HttpServlet</aw:parentClass> <aw:constructor name="c1"> public <aw:className/>() { super(); } </aw:constructor> <aw:method name="doGet"> public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } </aw:method> <aw:method name="doPost"> public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } </aw:method>
这里要注意,在修改时要关闭MyEclipse
04-servlet的7个小细节
1.Servlet的一些细节(1)

package cn.itcast.servlet; import java.io.IOException; import java.io.OutputStream; import javax.servlet.GenericServlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class FirstServlet extends GenericServlet { public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { OutputStream out = res.getOutputStream(); out.write("hello servelt".getBytes()); } }
/day05/WebRoot/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet> <servlet-name>FirstServlet</servlet-name> <servlet-class>cn.itcast.servlet.FirstServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>FirstServlet</servlet-name> <url-pattern>/servlet/FirstServlet</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>FirstServlet</servlet-name> <url-pattern>/1.html</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
2.Servlet的一些细节(2)
<servlet-mapping> <servlet-name>AnyName</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
<servlet-mapping> <servlet-name>AnyName</servlet-name> <url-pattern>/action/*</url-pattern> </servlet-mapping>
package cn.itcast.servlet; import java.io.IOException; import java.io.OutputStream; import javax.servlet.GenericServlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class FirstServlet extends GenericServlet { public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { OutputStream out = res.getOutputStream(); out.write("hello servelt".getBytes()); } }
/day05/WebRoot/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet> <servlet-name>FirstServlet</servlet-name> <servlet-class>cn.itcast.servlet.FirstServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>FirstServlet</servlet-name> <url-pattern>/servlet/FirstServlet</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>FirstServlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>FirstServlet</servlet-name> <url-pattern>/1.html</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
3.Servlet的一些细节(3)
比如如下的一些映射关系:
问题:
Servlet引擎将调用Servlet1,看谁长的最像那个就匹配,这里Servlet1的映射路径/abc/*长的最像
Servlet引擎将调用Servlet3,这里Servlet3的映射路径/abc长的最像,随意匹配
Servlet引擎将调用Servlet1,这里由于以“/*”开头的毕“*.xx”开头的优先级高,所以这里Servlet1优先级高
Servlet引擎将调用Servlet2,这里同样由于“/*”的优先级比“*.xx”高,所以选择Servlet2
Servlet引擎将调用Servlet2,同样由于“/*”比“*.xx”优先级高,所以选Servlet2
4.Servlet的一些细节(4)
package cn.itcast.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ServletDemo1 extends HttpServlet { public void init() throws ServletException { System.out.println("servlet创建了"); } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } public void destroy() { super.destroy(); System.out.println("servlet销毁了"); } }
/day05/WebRoot/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>ServletDemo1</servlet-name> <servlet-class>cn.itcast.servlet.ServletDemo1</servlet-class> </servlet> <servlet-mapping> <servlet-name>ServletDemo1</servlet-name> <url-pattern>/servlet/ServletDemo1</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
5.Servlet的一些细节(5)
举例:
<servlet> <servlet-name>invoker</servlet-name> <servlet-class>org.apache.catalina.servlets.InvokerServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet>
用途:为web应用写一个InitServlet,这个servlet配置为启动时装载,为整个web应用创建必要的数据库表和数据


6.Servlet的一些细节(6)



7.Servlet的一些细节(7)—线程安全
package cn.itcast.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //这个Servlet模拟多个浏览器并发访问这个servlet的同一个资源,从而来讨论servlet的多线程同步安全问题 public class ServletDemo3 extends HttpServlet { int i = 0; //这个就相当于多线程共享的数据 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { i++; //这里休眠5秒,模拟多线程并发访问这个servlet,从而导致线程安全问题 //还要注意,这里不能将异常抛出去,因为这个ServletDemo3继承自HttpServlet //子类不能抛比父类更多的异常,也就说子类抛的异常只能是父类异常的子集 try { Thread.sleep(1000*5); } catch (InterruptedException e) { e.printStackTrace(); } //当多浏览器访问这个servlet时,由于共享同一个i,所以会导致每个浏览器得到的数据都不是预期的结果 //这个就是安全问题所在,为了避免安全问题 response.getOutputStream().write(i); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
我们这里有两种解决方案
第一种为操作共享数据的代码加上同步代码块,虽然添加同步代码块也可以解决同步安全问题,但是在实际开发中不要用,理由是,如果用这个同步代码块的话,你的网站效率会非常
低,当一个浏览器占整个这个servlet,其它的浏览器就只有等这个浏览器访问这个Servlet才能访问,这个就相当于单线程了
并且这里还要注意一点,这里的异常必须try...catch,因为子类抛出的异常必须是父类异常的子集
/day05/src/cn/itcast/servlet/ServletDemo3.java
package cn.itcast.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //这个Servlet模拟多个浏览器并发访问这个servlet的同一个资源,从而来讨论servlet的多线程同步安全问题 public class ServletDemo3 extends HttpServlet { int i = 0; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //为操作共享数据的代码加上同步代码块 synchronized (this) { i++; try { Thread.sleep(1000*5); } catch (InterruptedException e) { e.printStackTrace(); } response.getOutputStream().write(i); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
package cn.itcast.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //这个Servlet模拟多个浏览器并发访问这个servlet的同一个资源,从而来讨论servlet的多线程同步安全问题 public class ServletDemo3 extends HttpServlet implements SingleThreadModel{ int i = 0; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { i++; try { Thread.sleep(1000*5); } catch (InterruptedException e) { e.printStackTrace(); } response.getOutputStream().write(i); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
这里还要注意,所谓的标记接口就是只有接口名没有方法,类似的标记接口还有序列化标记接口Serializable,可以克隆标记接口Cloneable
标记接口的作用就是让某个类实现它,以让这个类具有某种特殊的行为,标记接口就好像现实生活中的特权卡,具有某些特权

05-servltConfig和servletConfig对象
1.ServletConfig对象


package cn.itcast.servlet; import java.io.IOException; import java.util.Enumeration; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ServletDemo4 extends HttpServlet { ServletConfig config = null; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //通过ServeltConfig获取到字符集编码 String character = this.config.getInitParameter("Character"); System.out.println(character); //通过ServeltConfif获取到链接数据库的地址,用户名和密码 String url = this.config.getInitParameter("url"); System.out.println(url); String username = this.config.getInitParameter("username"); System.out.println(username); String password = this.config.getInitParameter("password"); System.out.println(password); //通过ServletConfig获取到要strust的配置文件 String config = this.config.getInitParameter("config"); System.out.println(config); //当然我们还可以通过getInitParameterNames来迭代出当前Servlet在web.xml中配置的所有初始化参数 Enumeration e = this.config.getInitParameterNames(); while(e.hasMoreElements()){ String name = (String) e.nextElement(); String value = this.config.getInitParameter(name); System.out.println(name+"->"+value); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } public void init(ServletConfig config) throws ServletException { this.config = config; } }
/day05/WebRoot/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>ServletDemo4</servlet-name> <servlet-class>cn.itcast.servlet.ServletDemo4</servlet-class> <!-- 这个是为Servlet配置的字符集 参数--> <init-param> <param-name>Character</param-name> <param-value>UTF-8</param-value> </init-param> <!-- 这个是为Servlet配置的链接数据的一些 参数--> <init-param> <param-name>url</param-name> <!-- 表示要链接mysql数据库中的test库--> <param-value>dbc:mysql://localhost:3306/test</param-value> </init-param> <init-param> <param-name>username</param-name> <param-value>root</param-value> </init-param> <init-param> <param-name>password</param-name> <param-value>root</param-value> </init-param> <!-- 这个是为Servlet配置的要读取struts的配置文件--> <init-param> <param-name>config</param-name> <param-value>WEB-INF/struts-config.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>ServletDemo4</servlet-name> <url-pattern>/servlet/ServletDemo4</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
这里要明白一点,其实struts就是一个大大的Servlet,在struts的web.xml中就有<init-param>配置了需要读取的配置文件,要用到struts就要读取它的配置文件


package cn.itcast.servlet; import java.io.IOException; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ServletDemo5 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //由于服务器在创建Servlet实例对象的时候会自动将web.xml中的配置参数封装到ServletConfig的对象中 //并在调用servlet的init方法时,将ServletConfig对象传递给serverlet //而我们这里创建的servlet实际上是继承成HttpServlet,而HttpServelt继承于GenericServlet //在GenericServlet中就已经通过init方法将ServletConfig对象拿到,所以我们这里可以通过getServletConfig //方法拿到ServletConfig对象,而不像ServletDemo4中那样亲自在init方法中获取ServletConfig对象 ServletConfig config = this.getServletConfig(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
/day05/WebRoot/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>ServletDemo5</servlet-name> <servlet-class>cn.itcast.servlet.ServletDemo5</servlet-class> </servlet> <servlet-mapping> <servlet-name>ServletDemo5</servlet-name> <url-pattern>/servlet/ServletDemo5</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
2.ServletContext

getAttribute(java.lang.String name)getContext(java.lang.String uripath) //通过给定servlet的url(字符串),返回一个ServletContext,这个方法用于多个web应用之间的交互getInitParameter(java.lang.String name)getMajorVersion() //获取到Servelt的主要版本号getMimeType(java.lang.String file) //给定文件名(字符串),返回文件Servelt认定的文件类型,比如给定"1.jpg",返回"image/jpeg",这个在Tomcat的web.xml中可以查询getMinorVersion() //获取到Servlet的次要版本号getNamedDispatcher(java.lang.String name) //通过传递Servlet的名称(在web.xml中配置的名称)实现将数据转发给该ServeletgetRealPath(java.lang.String path) //得到资源的绝对路径getRequestDispatcher(java.lang.String path) //得到请求转发对象getResource(java.lang.String path) //把资源当作URL返回getResourceAsStream(java.lang.String path) //把资源作为一个流getResourcePaths(java.lang.String path) //得到一个路径下所有的资源的路径,返回Set集合getServerInfo() //得到Servlet的信息getServlet(java.lang.String name) Deprecated.getServletContextName() //获取到ServletContext的名称getServlets() Deprecated. log(java.lang.Exception exception, java.lang.String msg) Deprecated.log(java.lang.String msg) //输出日志log(java.lang.String message, java.lang.Throwable throwable) //输出日志removeAttribute(java.lang.String name) //移除属性setAttribute(java.lang.String name, java.lang.Object object) //设置属性3.ServletContext应用
1.多个Servlet通过ServletContext对象实现数据共享。
package cn.itcast.context; import java.io.IOException; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //ServeltContext中常见运用,多个Servlet通过ServletContext对象实现数据共享 public class ContextDemo1 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //我们可以通过ServletConifig获取ServeletContext域对象 //this.getServletConfig().getServletContext(); //也可以直接获取ServletContext域对象 ServletContext context = this.getServletContext(); //ServletContext代表web应用,而ServletConfig代表当前Servlet的配置对象 //我们可以在ServletContext中存入数据,这样在同一个web应用中实现各个Servlet之间的通信 //比如下面我们将在ServletContext中存入一个name的属性,记住这里是向域中存入一个name的属性,而非对象 //这是别人这么叫的,至于为什么就不知道了,这叫做专业术语 context.setAttribute("name", "haha"); //然后创建ContextDemo2来获取到ServletContext域中存入的数据 } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
/day05/src/cn/itcast/context/ContextDemo2.java
package cn.itcast.context; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ContextDemo2 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取到ServletContext中存入的属性name String value = (String) this.getServletContext().getAttribute("name"); System.out.println(value); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>ContextDemo1</servlet-name> <servlet-class>cn.itcast.context.ContextDemo1</servlet-class> </servlet> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>ContextDemo2</servlet-name> <servlet-class>cn.itcast.context.ContextDemo2</servlet-class> </servlet> <servlet-name>ContextDemo1</servlet-name> <url-pattern>/servlet/ContextDemo1</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>ContextDemo2</servlet-name> <url-pattern>/servlet/ContextDemo2</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
2.获取WEB应用的初始化参数
package cn.itcast.context; import java.io.IOException; import java.util.Enumeration; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //ServletContext域对象的常见运用之获取WEB应用的初始化参数。 //在ServletConfig中我们开始配置了单个Servlet链接数据库的信息 //但是在实际开发中要链接数据库的Servlet有很多个,如果都在各自的Servlet中配置这些链接信息就比较繁琐 //所以为了避免重复,我们可以再web域对象ServeltContext域对象中配置好这些链接信息,那么在整个web应用中 //我们就可以公用这些信息了,当web应用启动的时候就会将这些初始化参数封装到ServeltContext中 public class ContextDemo3 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Enumeration e = this.getServletContext().getInitParameterNames(); while(e.hasMoreElements()){ String name = (String) e.nextElement(); System.out.println(name+"->"+this.getServletContext().getInitParameter(name)); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
/day05/WebRoot/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <context-param> <param-name>url</param-name> <param-value>jdbc:mysql://localhost:3306/test</param-value> </context-param> <context-param> <param-name>username</param-name> <param-value>root</param-value> </context-param> <context-param> <param-name>password</param-name> <param-value>root</param-value> </context-param> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>ContextDemo3</servlet-name> <servlet-class>cn.itcast.context.ContextDemo3</servlet-class> </servlet> <servlet-mapping> <servlet-name>ContextDemo3</servlet-name> <url-pattern>/servlet/ContextDemo3</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
3.实现Servlet的转发
在实际开发中,Servlet用于响应数据请求的,但是显示数据却是在jsp页面,所以需要servlet将请求数据转发到jsp页面
package cn.itcast.context; import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //ServletContext应用:实现Servlet请求的转发。 public class ContextDemo4 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String data = "hahahaha"; //将数据存入到ServletConext域对象中,但注意,在实际开发中我们并不将数据存入到ServeltContext中,因为它的作用范围是整个web应用内 this.getServletContext().setAttribute("data", data); //通过ServletContext域对象获取一个请求转发对象 //要知道这里由于是ServletContext在转发,ServletContext代表web应用,所以这里的"/"代表web应用 RequestDispatcher rd = this.getServletContext().getRequestDispatcher("/viewpage.jsp"); //实现转发,然后我们到viewpage.jsp去接受处理数据 rd.forward(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
/day05/WebRoot/viewpage.jsp
<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'viewpage.jsp' starting page</title> </head> <body> <h1> <font color="red"> <% String data = (String)this.getServletContext().getAttribute("data"); out.write(data); %> </font> </h1> </body> </html>
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>ContextDemo4</servlet-name> <servlet-class>cn.itcast.context.ContextDemo4</servlet-class> </servlet> <servlet-mapping> <servlet-name>ContextDemo4</servlet-name> <url-pattern>/servlet/ContextDemo4</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
这里要注意,在实际开发中我们并不会将请求数据存入到ServletContext中转发,因为ServletContext是域对象,存入的数据在整个web应用中通用
假如有多个用户同时请求这个web应用,当第一个用户请求的数据保存到名为data的变量中,然后将data保存到ServletContext中,还没来得及在jsp页面显示,另一个用户请求的数据d也保存到名为data的变量中,这个时候ServletContext中data变量就被覆盖了,第一个用户得到的数据却是第二个用户的数据,所以在实际开发中我们并不会讲请求数据保存到
ServletConext中而是保存到request容器中
这里我们演示ServletContext的转发是想说明ServletContxt可以实现在web应用组建之间转发数据,而并非是说我们要将请求数据保存到ServletContet中然后转发给jsp页面
4.利用ServletContext对象读取资源文件
package cn.itcast.context; import java.io.FileInputStream; import java.io.IOException; import java.util.Properties; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; //这个Servelt实现利用ServletContext对象读取资源文件 //在java中资源文件有两种方式存在,一种是xml文件,一种是propertier文件 //如果是xml则需要dom4j去读取xml文件,如果是properties文件则可以直接读取 //那什么时候用xml文件什么时候用properties,当我们的资源文件是由层次关系的则使用xml //如果我们的资源文件没有层次关系则用properties public class ContextDemo5 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //这里有很重要的一个问题,就是要分清web开发中,编译时的目录和运行时的目录是不同的 //比如这里的db.propertier编译时的目录在src下,而当我们将其发布到服务器运行时则目录 //在classes目录下,于是我们用传统的读取文件的方式去读取它 //但是当我们发布之后我们去访问这个Servlet时发现出错了 FileInputStream in = new FileInputStream("classes/db.properties"); //读取properties文件的固定代码 //其实Properties是map的孩子 Properties p = new Properties(); p.load(in); String url = p.getProperty("url"); System.out.println(url); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
/day05/src/db.properties
url=jdbc:mysql://localhost:3306/test username=root password=root



package cn.itcast.context; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.Properties; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ContextDemo6 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //使用ServletContext读取配置文件的第一种方法,我们通过它的getResourceAsStream()方法将资源转换成流然后载入Properties method1(); //使用ServletContext读取配置文件的第二种方法,我们通过它的getRealPath()获取到资源的绝对路径,然后通过传统的方式去读取配置文件 //这种方式很有好处,我们可以通过绝对路径将文件名抽取出来 method2(); //使用ServletContext读取配置文件的第三种方法,我们通过它的getResource()方法获取到资源的URL,然后通过URL的openStream()方法获取流 //然后再通过固定格式读取配置文件 method3(); //使用ServletContext读取配置文件的第四种方法,我们通过他的getResourcePaths()方法获取到某个路径下的所有资源的路径,然后迭代出想要的路径 //之后就可以用传统的方法读取配置文件了,注意这个方法返回的是一个set集合,这种方法不常用,这里就不演示了 //this.getServletContext().getResourcePaths(path) } public void method3() throws MalformedURLException, IOException { URL url = this.getServletContext().getResource("/WEB-INF/classes/db.properties"); InputStream in = url.openStream(); //然后用固定读取Properties文件的方式将流装载到Properties中读取 Properties p = new Properties(); p.load(in); String username = p.getProperty("username"); System.out.println(username); } public void method2() throws FileNotFoundException, IOException { String path = this.getServletContext().getRealPath("/WEB-INF/classes/db.properties"); System.out.println(path); //截取字符串最后一个'/'之后的字符串 String fileName = path.substring(path.lastIndexOf("\\")+1); System.out.println(fileName); //然后通过传统方式读取配置文件 FileInputStream in = new FileInputStream(path); //然后用固定读取Properties文件的方式将流装载到Properties中读取 Properties p = new Properties(); p.load(in); String driver = p.getProperty("driver"); System.out.println(driver); } public void method1() throws IOException { //注意这里记住一点,凡是在servlet中涉及到写地址的,建议最好以"/"开头 //这里由于是ServletContext调用db.properties(ServletContext代表web应用)所以这里的'/'代表web应用(相对于web应用) InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties"); //读取properties类型的配置文件就是固定格式 //要知道Properties是map的孩子 Properties p = new Properties(); //将输入流中的内容载入到Properties中 p.load(in); //获取到配置文件中的地址 String url = p.getProperty("url"); System.out.println(url); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
/day05/WebRoot/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>ContextDemo6</servlet-name> <servlet-class>cn.itcast.context.ContextDemo6</servlet-class> </servlet> <servlet-mapping> <servlet-name>ContextDemo6</servlet-name> <url-pattern>/servlet/ContextDemo6</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>

package cn.itcast.context; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ContextDemo7 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //这里都要注意一下,这里路径中开始的"/"代表的是web应用 //第一个db.properties路径为 this.getServletContext().getResourceAsStream("/WEB-INT/classes/cn/itcast/context/db.properties"); //第二个db.properties路径为 this.getServletContext().getResourceAsStream("/WEB-INT/classes/db.properties"); //第三个db.properties路径为 this.getServletContext().getResourceAsStream("/WEB-INT/db.properties"); //第二个db.properties路径为 this.getServletContext().getResourceAsStream("/db.properties"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
/day05/WebRoot/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>ContextDemo7</servlet-name> <servlet-class>cn.itcast.context.ContextDemo7</servlet-class> </servlet> <servlet-mapping> <servlet-name>ContextDemo7</servlet-name> <url-pattern>/servlet/ContextDemo7</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
07-servletContext读取配置文件
1.在非Servlet中如何读取资源配置文件
package cn.itcast.context; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import cn.itcast.dao.Student; public class ContextDemo8 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Student student = new Student(); student.add("student"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
/day05/WebRoot/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>ContextDemo7</servlet-name> <servlet-class>cn.itcast.context.ContextDemo7</servlet-class> </servlet> <servlet-mapping> <servlet-name>ContextDemo7</servlet-name> <url-pattern>/servlet/ContextDemo7</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
/day05/src/cn/itcast/dao/Student.java
package cn.itcast.dao; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.Properties; public class Student { public void add(String student) throws IOException{ //通过类加载器读取classes目录下资源文件的第一种方法 //获取到类加载器,然后通过类加载器的getResourceAsStream()方法将资源文件读取到流中,然后在通过固定方式读取 //这里要注意类加载器指向的路径时classes目录,只要在classes目录下的文件才能被加载,不在的就不行 //所以这里的相对路径时classes目录,这里的/可以加也可以不加,但在开发中建议加上 method1(); //通过类加载器读取classes目录下资源文件的第二种方法 //获得加载器之后,然后通过类加载器的getResource()方法将资源文件转成一个URL,然后通过URL的openStream()将 //资源文件读取到流中,最后用固定读取资源文件的方式读取资源文件 //同样这里要注意,类加载器执行的目录同样是classes目录,所以在有classes目录下的文件才能被加载 //在Servlet中用URL读取资源文件的方式不常见,但是在这里却非常常用,因为用这种方式可以得到绝对地址 method2(); } public void method2() throws IOException { URL url = Student.class.getClassLoader().getResource("/db.properties"); //获取绝对地址 String path = url.getPath(); System.out.println(path); InputStream in = url.openStream(); //通过固定方式将流中的数据读取到Properties中 Properties p = new Properties(); p.load(in); String driver = p.getProperty("driver"); System.out.println(driver); } public void method1() throws IOException { InputStream in = Student.class.getClassLoader().getResourceAsStream("/db.properties"); //只要是在classes目录下就可以读取 in = Student.class.getClassLoader().getResourceAsStream("/cn/itcast/context/db.properties"); //通过固定方式将资源文件读取到Properties中 Properties p = new Properties(); p.load(in); String driver = p.getProperty("driver"); System.out.println(driver); } }
2.在非Servelt中读取资源文件的注意事项
package cn.itcast.context; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import cn.itcast.dao.Student; public class ContextDemo9 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Student s = new Student(); s.delete(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
/day05/src/db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=root
password=root
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>ContextDemo7</servlet-name> <servlet-class>cn.itcast.context.ContextDemo7</servlet-class> </servlet> <servlet-mapping> <servlet-name>ContextDemo7</servlet-name> <url-pattern>/servlet/ContextDemo7</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
/day05/src/cn/itcast/dao/Student.java
package cn.itcast.dao; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLDecoder; import java.util.Properties; public class Student { public void add(String student) throws IOException{ //通过类加载器读取classes目录下资源文件的第一种方法 //获取到类加载器,然后通过类加载器的getResourceAsStream()方法将资源文件读取到流中,然后在通过固定方式读取 //这里要注意类加载器指向的路径时classes目录,只要在classes目录下的文件才能被加载,不在的就不行 //所以这里的相对路径时classes目录,这里的/可以加也可以不加,但在开发中建议加上 //method1(); //通过类加载器读取classes目录下资源文件的第二种方法 //获得加载器之后,然后通过类加载器的getResource()方法将资源文件转成一个URL,然后通过URL的openStream()将 //资源文件读取到流中,最后用固定读取资源文件的方式读取资源文件 //同样这里要注意,类加载器执行的目录同样是classes目录,所以在有classes目录下的文件才能被加载 //在Servlet中用URL读取资源文件的方式不常见,但是在这里却非常常用,因为用这种方式可以得到绝对地址 method2(); } public void method2() throws IOException { URL url = Student.class.getClassLoader().getResource("/db.properties"); //获取绝对地址 String path = url.getPath(); System.out.println(path); InputStream in = url.openStream(); //通过固定方式将流中的数据读取到Properties中 Properties p = new Properties(); p.load(in); String driver = p.getProperty("driver"); System.out.println(driver); } public void method1() throws IOException { InputStream in = Student.class.getClassLoader().getResourceAsStream("/db.properties"); //只要是在classes目录下就可以读取 in = Student.class.getClassLoader().getResourceAsStream("/cn/itcast/context/db.properties"); //通过固定方式将资源文件读取到Properties中 Properties p = new Properties(); p.load(in); String driver = p.getProperty("driver"); System.out.println(driver); } public void delete() throws IOException{ //对于在非Servlet中读取变动的资源文件的方式,我们需要先获取到资源文件的绝对地址 //然后根据地址通过传统方式去读取资源文件按 URL url = Student.class.getClassLoader().getResource("/db.properties"); String path = url.getPath(); //注意这里要转一下编码,得到的路径中可能有空格,空格都是用%20来代替的,所以需要转码,否则要报错 path=URLDecoder.decode(path,"utf-8"); System.out.println(path); //传统方式读取资源文件 FileInputStream in = new FileInputStream(path); Properties p = new Properties(); p.load(in); System.out.println(p.getProperty("driver")); //假设这里间隔10S,在这10s内我去修改资源文件 try { Thread.sleep(1000*10); } catch (InterruptedException e) { e.printStackTrace(); } //修改之后我们再去读取资源文件 in = new FileInputStream(path); p = new Properties(); p.load(in); System.out.println(p.getProperty("driver")); } }
—————————————————————————————————————————————————————————————————————————————————
最后说一下这里缺少一个总结:

浙公网安备 33010602011771号