]Servlet编程

第四章 Servlet编程

目录

在这里插入图片描述

1、Servlet 执行过程

1.1 Servlet简介

在这里插入图片描述

1.1.1 servlet说明
  • 用java语言开发网页动态资源的技术
  1. Servlet 是 JavaEE 规范之一。规范就是接口
  2. Servlet 就 JavaWeb 三大组件之一。三大组件分别是:Servlet 程序、Filter 过滤器、Listener 监听器。
  3. Servlet 是运行在服务器上的一个 java 小程序,它可以接收客户端发送过来的请求,并响应数据给客户端。
1.1.2 servlet特点:
  • servlet就是一个普通的java类,继承HttpServlet类
  • 一个普通的java类实现了Servlet接口,也叫Servlet程序。我们通常继承HttpServlet是为了创建一个基于http协议的servlet程序。
  • servlet程序交给tomcat服务器运行

1.2 手动实现

  1. 编写一个类去实现 Servlet 接口

    实现 service 方法,处理请求,并响应数据

public class HelloServlet implements Servlet { 
  /*** service 方法是专门用来处理请求和响应的 
  	 * @param servletRequest 
  	 * @param servletResponse 
  	 * @throws ServletException 
  	 * @throws IOException */ 
  @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { 
    System.out.println("Hello Servlet 被访问了"); 
  } 
}
public class HelloServlet2 extends HttpServlet { 
  /*** doGet()在 get 请求的时候调用 
   * @throws ServletException 
   * @throws IOException */
  @Override 
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 				          
  		System.out.println("HelloServlet2 的 doGet 方法");
   }
  /*** doPost()在 post 请求的时候调用 
  * @throws ServletException 
  * @throws IOException */
  @Override 
  protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 		
  		System.out.println("HelloServlet2 的 doPost 方法"); 
        } 
}


  1. 到 web.xml 中去配置 servlet 程序的访问地址
<!-- 浏览器访问: http://localhost:8080/day10/hello -->
  <!-- 配置一个servlet -->
  <!-- servlet的配置 -->
  <servlet>
  	<!-- servlet内部名称。可以自定义 -->
  	<servlet-name>HelloServlet</servlet-name>
  	<!-- servlet类的全名:包名+简单类名 -->
  	<servlet-class>gz.itcast.a_servlet.HelloServlet</servlet-class>
  </servlet>
  
  <!-- servlet的映射配置 -->
  <servlet-mapping>
  	<!-- sevlet内部名称。和servlet配置的内部名称保持一致!! -->
  	<servlet-name>HelloServlet</servlet-name>
  	<!-- servlet的路径映射。访问servlet的名称 -->
  	<url-pattern>/hello</url-pattern>
  </servlet-mapping>

1.3 Servlet开发过程(url 地址到 Servlet 程序的访问)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uPtbEuYp-1584435134626)(media/servlet_kaifa.png)]

  • 前提: tomcat服务器启动时,会加载%conf%/web.xml文件。然后再加载站点下的每个web应用的web.xml文件。
  • http:// 本地hosts文件查询域名和ip的映射,找不到,联网到运营商的DNS服务起器找域名和ip的映射
  • **8080:**Tomcat端口
  • **06_servlet:**站点下的web应用名称
  • **hello:**资源名称。
    1. 如果读到对应的静态资源文件,那么就把内容返回给浏览器
    2. 如果读不到对应的静态资源文件,那么就返回404的错误页面。

2、Servlet的路径映射

url-pattern: 表示servlet的路径映射,也叫servlet访问名称。

2.1 精确匹配

  1. /demo1 http://localhost:8080/day10/demo1
  2. /itcast/demo1 http://localhost:8080/day10/itcast/demo1

2.2 模糊匹配

样式路径
/*http://localhost:8080/day10/任意路径
/itcast/*http://localhost:8080/day10/itcast/任意路径
后缀 (.do、 .action、.jsf、.html)http://localhost:8080/day10/任意路径.后缀

2.3 注意事项

  1. url-pattern要么以/开头,要么以*开头 例如: itcast/demo1错误写法。
  2. 不能同时使用两种模糊匹配。例如: /itcast/*.html 错误写法
  3. 当多个url-pattern同时符合匹配规则,那么
    • 精确匹配的url-pattern会优先被执行。(长的最像的url-pattern优先)
    • 后缀名结尾的模糊匹配的url-pattern优先级最低

3、Servlet生命周期

3.1 说明

  • 平常的java类自己去new对象,自己去使用对象调用。sevlet程序,servlet的生命周期由tomcat服务器控制的。

3.2 Servlet的四个生命周期

  1. 构造方法: 在创建servlet对象时调用,只调用1次。证明servlet对象在tomcat服务器中是单实例的。
  2. init方法:在创建完servlet对象后调用,只调用1次。
  3. service方法: 在每次请求servlet时调用,用n次。
  4. destroy方法: servlet对象销毁时调用只调用1次。tomcat服务器停止或web应用重新部署时调用

3.3 用伪代码模拟tomcat服务器调用servlet生命周期

3.3.1 tomcat服务器通过反射构造对象

得到字节码对象

Class clazz = Class.forName("浏览器中的地址");

构造对象

Object hello = clazz.newInstance();      //servlet的构造方法被调用
3.3.2 tomcat服务器调用init方法

得到init方法对象

Method m = clazz.getDeclareMethod("init",ServeletConfig.class);

执行方法

m.invoke(hello,config);                //servlet的init方法被调用
3.3.3 tomcat服务器创建request和response对象,调用service方法

得到service方法对象

Method m =clazz.getDeclareMethod("service",HttpServletRequest.class,HttpServletRespnose.class);

执行方法

 m.invoke(hello,request,response);     //servlet的service方法被调用
3.3.4 tomcat服务器停止或web应用重新部署时,tomcat服务器调用destroy方法

得到destroy方法对象

Method m = clazz.getDeclareMethod("destroy",null)

执行方法

m.invoke(hello,null);       //servlet的destroy方法被调用

3.4 时序图描述servlet执行过程

在这里插入图片描述

4、 Servlet线程安全问题

4.1 servlet对象特点

在tomcat服务器中是单实例多线程的。多个线程同时操作了Servlet的成员变量(共享数据)。

4.2 避免Servlet并发问题建议

  1. 尽量不要在servlet类中使用成员变量。
  2. 如果要使用成员变量,那么就要给使用到成员变量的代码块加上代码锁,尽量缩小同步锁的范围,以避免因为同步产生代码并发执行效率降低的问题。

5、Servlet自动加载

默认情况下,第一次访问servlet时创建servlet对象。创建对象的过程中会调用构造方法和inti方法。如果init方法的业务逻辑需要消耗比较长的时间,用户的第一次访问servlet时需要等待较长的时间。

改变servlet对象创建的时机: tomcat服务器启动的时候创建servlet对象。

<servlet>
    <servlet-name>LoadDemo2</servlet-name>
    <servlet-class>gz.itcast.e_load.LoadDemo2</servlet-class>
    <!-- 正整数:数值越大,创建对象的优先级越低 -->
    <load-on-startup>1</load-on-startup>
  </servlet>

6、init问题

在GenericServlet中,有两个init方法。

  1. 有参数的init方法:该方法是servlet的四个生命周期方法中的一个。由tomcat服务器默认调用的初始化方法。在GenericServet的实现中,该方法会调用无参数的init方法。
  2. 无参数的init方法:该方法的是Sun公司设计出来用于给开发者去覆盖,用于实现初始化逻辑的方法。

如果要编写servlet的初始化逻辑,只需要覆盖无参数的init方法即可

7、Servlet中重要对象

对象作用
HttpServletRequest对象封装请求信息
HttpServletResponse对象封装响应信息
ServletConfig对象封装一个servlet配置参数信息
ServletContext对象封装web应用环境信息

7.1 ServletContext对象

7.1.1 ServletContext对象简介
  • ServletContext叫Servlet上下文对象,该对象表示当前的web应用环境信息。一个web应用只会创建一个ServletContext对象。
  1. ServletContext 是一个接口,它表示 Servlet 上下文对象
  2. 一个 web 工程,只有一个 ServletContext 对象实例。
  3. ServletContext 对象是一个域对象。
  4. ServletContext 是在 web 工程部署启动的时候创建。在 web 工程停止的时候销毁。
  • 域对象,是可以像 Map 一样存取数据的对象,叫域对象。 这里的域指的是存取数据的操作范围,整个 web 工程。主要用于保存数据和获取数据,用于在web应用中不同资源之间共享数据。

  • 域对象的作用: 主要用于保存数据和获取数据,用于在web应用中不同资源之间共享数据。参数形式: 只能传递字符串数据

    Servlet中所有域对象:

    1. HttpServletRequest对象: request域
    2. ServletContext对象: context域
    3. HttpSession对象: session域

    Jsp中域对象:PageContext对象: page域

存数据取数据删除数据
Mapput()get()remove()
域对象setAttribute()getAttribute()removeAttribute()
7.1.2 ServletContext 类的四个作用
  1. 获取 web.xml 中配置的上下文参数 context-param
  2. 获取当前的工程路径,格式: /工程路径
  3. 获取工程部署后在服务器硬盘上的绝对路径
  4. 像 Map 一样存取数据
1、演示代码:
protected void doGet(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 目录<br/> 
    */ 
   System.out.println("工程部署的路径是:" + context.getRealPath("/"));
   System.out.println("工程下 css 目录的绝对路径是:" + context.getRealPath("/css")); 
   System.out.println("工程下 imgs 目录 1.jpg 的绝对路径是:" + context.getRealPath("/imgs/1.jpg")); }
2、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>
3、 ServletContext存取数据:
/**
  * 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")); }
7.1.3 ServletContext对象的常用方法
1、得到web应用的上下文路径
//得到web应用上下路径。也就是部署到tomcat服务器上运行的web应用名称。
java.lang.String         getContextPath() 
2、得到web应用的全局参数(所有servlet有效的!!)
java.lang.String 		getInitParameter(java.lang.String name)  
java.util.Enumeration 	 getInitParameterNames() 
3、域对象相关的方法
void setAttribute(java.lang.String name, java.lang.Object object) //保存数据
java.lang.Object getAttribute(java.lang.String name)   			 //得到数据
void removeAttribute(java.lang.String name)                       //清除数据
4、转发相关的
response.sendRedirect(路径);   							//请求重定向
// 在servlet中实现页面跳转 
RequestDispatcher 
getRequestDispatcher(java.lang.String path)  
request.getRequestDispacher(路径).forward(request,respone); //请求转发
5、web应用读取资源文件
java.lang.String 		   getRealPath(java.lang.String path)  
java.io.InputStream 	   getResourceAsStream(java.lang.String path)
 //不同资源
   //web应用内部资源。在当前web应用中的资源
   //其他web应用资源。在同一个站点下的其他web应用的资源
   //站点外的资源。其他站点下的资源
6、请求重定向和请求转发区别
请求重定向请求转发
地址栏改变,改变为重定向到地址地址栏不会改变
可以重定向到当前web应用,其他web应用,甚至是其他站点资源只能转发到当前web应用内部资源
两次不同的请求。不可以使用request域对象来共享数据同一次请求。可以使用request域对象来共享数据

7.2 ServletConfig对象

ServletConfig 类是 Servlet 程序的配置信息类。 Servlet 程序和 ServletConfig 对象都是由 Tomcat 负责创建,我们负责使用。 Servlet 程序默认是第一次访问的时候创建,ServletConfig 是每个 Servlet 程序创建时,就创建一个对应的ServletConfig 对象。

7.2.1 ServletConfig 类的三大作用
  1. 可以获取 Servlet 程序的别名 servlet-name 的值
  2. 取初始化参数 init-param
  3. 获取 ServletContext 对象
7.2.2 使用
<!-- XML配置 -->
<!-- servlet 标签给 Tomcat 配置 Servlet 程序 --> 
<servlet> 
  <!--servlet-name 标签 Servlet 程序起一个别名(一般是类名) --> 	      	
  	<servlet-name>HelloServlet</servlet-name>
  <!--servlet-class 是 Servlet 程序的全类名-->
  	<servlet-class>com.atguigu.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>
@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()); }
  • 注意:重写init()方法里面一定要调用父类的init(ServletConfig)操作,子类重写了init()方法,在调用init()方法的时候会直接调用子类的方法
//父类的init()方法
public void init(ServletConfig config) {
    this.config = config;
    this.init();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值