2014.08.31 周日-servlet运行过程、线程安全、ServletConfig对象、ServletContext对象

本文详细介绍了Servlet的工作原理和技术要点,包括Servlet的生命周期、初始化参数、线程安全性处理、配置映射及其实现类等核心内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、servlet

1、servlet的运行过程
  1. servlet调用图...
  2. 覆写init() destroy()
    package cn.itcast;
    import javax.servlet.GenericServlet;
    import javax.servlet.ServletResponse;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletException;
    import java.io.OutputStream;
    import javax.servlet.ServletConfig;
    
    public class FirstServlet extends GenericServlet { 
    	public void service(ServletRequest req, ServletResponse res)  
                          throws ServletException, java.io.IOException {  
    		
    		String data = "Hello servlet!";
    		OutputStream out = res.getOutputStream();
    		out.write(data.getBytes());
    	}
    
    	public void init(ServletConfig config)
              throws ServletException {
    		
    		System.out.println("对象创建");
    	}
    
    	public void destroy() {
    		System.out.println("对象被销毁");		
    	}
    }
    访问http://localhost:8080/day05/xxx,对象创建;
    移除web应用day05或者关闭web服务器(tomcat),对象被销毁。
2、用eclipse开发servlet
3、servlet接口实现类
  1. GenericServlet、HttpServlet。
  2. HttpServlet在实现Servlet接口时,覆写了service方法,该方法体内的代码会自动判断用户的请求方式,如为GET请求,则调用HttpServlet的doGet方法,如为Post请求,则调用doPost方法。因此,开发人员在编写Servlet时,通常只需要覆写doGet或doPost方法,而不要去覆写service方法。
4、servlet的一些细节(web.xml)
  1. Servlet 映射到的 URL 中也可以使用*通配符,但是只能有 两种固定的格式 :一种格式是“* . 扩展名”,另一种格式是以正斜杠( / )开头并以“ /*” 结尾。
    /开头的优先级高些。
    在学到框架的时候,会用到这些通配
    符。
  2. 如果在<servlet>元素中配置了一个<load-on-startup>元素,那么WEB应用程序在启动时,就会装载并创建Servlet的实例对象、以及调用Servlet实例对象的init()方法。(而不是在servlet第一次访问才创建)。
    如果你想让框架在服务器启动的时候就启动起来,就可以把这个框架写到init()里面去。
  3. 如果某个Servlet的映射路径仅仅为一个正斜杠(/),那么这个Servlet就成为当前Web应用程序的缺省Servlet。
    凡是在web.xml文件中找不到匹配的<servlet-mapping>元素的URL,它们的访问请求都将交给缺省Servlet处理,也就是说,缺省Servlet用于处理所有其他Servlet都不处理的访问请求。
    在<tomcat的安装目录>\conf\web.xml文件中,注册了一个名称为org.apache.catalina.servlets.DefaultServlet的Servlet,并将这个Servlet设置为了缺省Servlet。
    在<tomcat的安装目录>\conf\web.xml文件中,注册了一个名称为org.apache.catalina.servlets.DefaultServlet的Servlet,并将这个Servlet设置为了缺省Servlet。
5、servlet的一些细节(线程安全)
  1. servletDemo4.java  int i = 1; i++;(并发访问这个servlet,存在线程安全问题)
    package cn.itcast;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet("/ServletDemo4")
    public class ServletDemo4 extends HttpServlet {
    
    	int i = 1;
    	
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		i++;
    		try {
    			Thread.sleep(1000 * 5);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		//response.getOutputStream().write(i);  //为什么这句话无法显示int型变量i呢?
    		response.getWriter().write(i + "");  //为什么后面要加上"",浏览器才会显示i的值呢?
    	}
    
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		
    	}
    
    }
  2. synchronized。但是在互联网上不能这样做,因为这样就变成单线程的了,比如每天有成千上万的人访问新浪,如果有一个人在访问了,其它人就访问不了了。我们要知道的是servlet是线程不安全的。
    package cn.itcast;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet("/ServletDemo4")
    public class ServletDemo4 extends HttpServlet {
    
    	int i = 1;
    	
    	protected 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);  //为什么这句话无法显示int型变量i呢?
    			response.getWriter().write(i + "");  //为什么后面要加上"",浏览器才会显示i的值呢?
    		}
    	}
    
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		
    	}
    
    }
    
  3.  SingleThreadModel接口(Deprecated过时的):
    如果某个Servlet实现了SingleThreadModel接口,那么Servlet引擎将以单线程模式来调用其service方法。
  4. 子类不能抛比父类更多的异常。

二、ServletConfig对象

1、初始化参数
  1. init-param初始化参数(封装到servletconfig中,这是服务器自己做的);覆盖init方法。  
    web.xml:
     <servlet>
      	<servlet-name>/ConfigServletDemo1</servlet-name>
      	<servlet-class>cn.itcast.servletConfig.ConfigServletDemo1</servlet-class>
      	
      	<init-param>
      		<param-name>xx</param-name>
      		<param-value>yyyy</param-value>
      	</init-param>
      </servlet>
      
      <servlet-mapping>
      	<servlet-name>/ConfigServletDemo1</servlet-name>
      	<url-pattern>/servletConfig/ConfigServletDemo1</url-pattern>
      </servlet-mapping>
    ConfigServletDemo1.java:
    	@Override
    	public void init(ServletConfig config) throws ServletException {
    		String value = config.getInitParameter("xx");
    		System.out.println(value);
    	}
    在控制台得到xx的value:yyyy。
  2. 在浏览器中得到xx的value,ConfigServletDemo1.java:
    package cn.itcast.servletConfig;
    
    import java.io.IOException;
    
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class ConfigServletDemo1 extends HttpServlet {
    
    	private ServletConfig config;
    	
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		String value = config.getInitParameter("xx");
    		response.getOutputStream().write(value.getBytes());
    	}
    
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		
    	}
    
    	@Override
    	public void init(ServletConfig config) throws ServletException {
    		this.config = config;
    	}
    
    }
    
  3. getInitParameterNames() 获取所有的初始化参数。迭代:
    web.xml:
     <servlet>
      	<servlet-name>/ConfigServletDemo1</servlet-name>
      	<servlet-class>cn.itcast.servletConfig.ConfigServletDemo1</servlet-class>
      	
      	<init-param>
      		<param-name>xx</param-name>
      		<param-value>yyyy</param-value>
      	</init-param>
      	
      	<init-param>
      		<param-name>mm</param-name>
      		<param-value>nnnn</param-value>
      	</init-param>
      	
      	<init-param>
      		<param-name>pp</param-name>
      		<param-value>qqqq</param-value>
      	</init-param>
      </servlet>
    ConfigServletDemo1.java:
    package cn.itcast.servletConfig;
    
    import java.io.IOException;
    import java.util.Enumeration;
    
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class ConfigServletDemo1 extends HttpServlet {
    
    	private ServletConfig config;
    	
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		Enumeration e = config.getInitParameterNames();
    		while(e.hasMoreElements()) {
    			String name = (String) e.nextElement();
    			String value = config.getInitParameter(name);
    			response.getOutputStream().write((name + "-" + value + "<br/>").getBytes());  //怎么在浏览器中换行?
    		}
    	}
    
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		
    	}
    
    	@Override
    	public void init(ServletConfig config) throws ServletException {
    		this.config = config;
    	}
    
    }
2、应用:
  1. 获得字符集编码:
    web.xml:
      	<init-param>
      		<param-name>charset</param-name>
      		<param-value>UTF-8</param-value>
      	</init-param>
    .java:doGet方法里面:
    String charset = config.getInitParameter("charset");  //从配置文件获取这个值。
  2. 获得数据库连接信息:
    web.xml:
      	<init-param>
      		<param-name>url</param-name>
      		<param-value>jdbc: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>
    .java:doGet方法里面:
    		String url = this.config.getInitParameter("url");
    		String username = this.config.getInitParameter("username");
    		String password = this.config.getInitParameter("password");
  3. 获得配置文件查看struts案例的web.xml文件...
  4. 在实际开发中,不用写init方法,可以这么写:
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		ServletConfig config = this.getServletConfig();
    		System.out.println(config.getInitParameter("xx"));
    	}

三、ServletContext对象

1、ServletContext
  1. 这个对象代表的是一个web应用。
  2. 多个servlet之间可以通过其共享数据。
2、应用
  1. 多个Servlet通过ServletContext对象实现数据共享:
    ServletContext1.java:
    package cn.itcast.context;
    
    import java.io.IOException;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class ServletContext1 extends HttpServlet {
    
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		
    		String data = "abcdefg";
    		ServletContext context = this.getServletConfig().getServletContext();
    		context.setAttribute("data", data);
    	}
    
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		
    	}
    
    }
    ServletContext2.java:
    package cn.itcast.context;
    
    import java.io.IOException;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class ServletContext2 extends HttpServlet {
    
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		ServletContext context = this.getServletContext();
    		String data = (String) context.getAttribute("data");
    		response.getOutputStream().write(data.getBytes());
    		System.out.print(data);
    	}
    
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		
    	}
    
    }
    web.xml:
      <servlet>
      	<servlet-name>ServletContext1</servlet-name>
      	<servlet-class>cn.itcast.context.ServletContext1</servlet-class>
      </servlet>
      <servlet-mapping>
      	<servlet-name>ServletContext1</servlet-name>
      	<url-pattern>/context/ServletContext1</url-pattern>
      </servlet-mapping>
      
      <servlet>
      	<servlet-name>ServletContext2</servlet-name>
      	<servlet-class>cn.itcast.context.ServletContext2</servlet-class>
      </servlet>
      <servlet-mapping>
      	<servlet-name>ServletContext2</servlet-name>
      	<url-pattern>/context/ServletContext2</url-pattern>
      </servlet-mapping>
    先访问 http://localhost:8080/fanglixun_day05/context/ServletContext1
    再访问 http://localhost:8080/fanglixun_day05/context/ServletContext2
    就可以显示data的内容abcdefg了。
  2. 获取WEB应用的初始化参数:
    web.xml:(获取整个web站点的初始化参数)
      <context-param>
      	<param-name>url</param-name>
      	<param-value>jdbc:mysql://localhost:3306/test</param-value>
      </context-param>
    ServletContext3.java:
    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;
    
    public class ServletContext3 extends HttpServlet {
    
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		ServletContext context = this.getServletContext();
    		String url = context.getInitParameter("url");
    		response.getOutputStream().write(url.getBytes());
    	}
    
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		
    	}
    
    }
    访问http://localhost:8080/fanglixun_day05/context/ServletContext3,会显示url的value。
  3. 实现Servlet的转发:
    ServletContext4和ServletContext5是用的同一个request和response。
    ServletContext4.java:
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		ServletContext context = this.getServletContext();
    		RequestDispatcher rd = context.getRequestDispatcher("/context/ServletContext5");
    		rd.forward(request, response);
    	}
    ServletContext5.java:
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    		response.getOutputStream().write("ServletContext5".getBytes());
    	}
    访问http://localhost:8080/fanglixun_day05/context/ServletContext4
    显示ServletContext5。 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值