servlet的介绍 & xml中配置 以及 & 三种实现方式(补充设置浏览器不缓存的方法)

版权声明:本文为博主原创,无版权,未经博主允许可以随意转载,无需注明出处,随意修改或保持可作为原创! https://blog.csdn.net/qq_41517071/article/details/83003059

开始时间:2018年10月13日20:53:30 | 2018年10月14日16:10:56

结束时间:2018年10月13日21:53:30 | 2018年10月14日17:02:23

累计时间:2小时

备注:几乎每一句话都很有收获,复习的时候务必要仔细一点


Servlet 简单介绍: 


 Servlet 服务器端的一个小程序:   运行在服务器上。 能够接收客户端请求,并且给客户端做出相应。 
    
  * 实现方式: 三种: 
   (1)实现Servlet 接口: 
   (2)继承GenericServlet:类。 
   (3)继承HttpServlet: 
   
 * Servlet 当中设定的方法: 
        初始化的方法; init();
        接收客户端的请求,Service(); 
        销毁Servlet:     destroy();  

 * Servlet 的生命周期: 
   和Servlet 声明周期相关的方法: 
   init(ServletConfig config);                                                             Servlet创建之后,自动执行。 
   service(ServletRequest request, ServletResponse response);   当客户端浏览器发出请求的时候 service方法被调用。 
   destroy()                                                                                       服务器关闭的时候,当前的应用称web服务器上卸载的时候。 
 
  生命周期---(面试问题)  
  诞生: 当客户端浏览器 第一次 访问该Servlet的时候,此时Servlet诞生。

第二次访问不创建,所以说servlet是单例 
                自动会调用init方法,执行一个初始化操作。 
                
  服务:  当客户端浏览器每次发出请求,service方法都会被执行。 
  
 销毁:  服务器关闭的时候,当前的应用称web服务器上卸载的时候。

* 访问方式

不能被浏览器直接访问, 需要在当前应用的核心配置当中 对 当前servlet进行配置

配置方法如下:

 

1 打开webinfo文件 下面的web.xml (是web应用的核心配置文件)


   <!--注册Servlet:  -->
  <servlet>//需要有两个子标签  第一个放文件名  第二个放你的文件所在的全路径名

(如果是eclipse的话 可以快速copy全路径  如图  点击 copy qualified name即可)
       <servlet-name>FirstServlet</servlet-name>    
       <servlet-class>web.servlet.FirstServlet</servlet-class>
  </servlet>
  
  <!-- 映射 -->(本质上是一个图结构)
  <servlet-mapping>
        <servlet-name>FirstServlet</servlet-name>             和上面注册一样
        <url-pattern>/xxx</url-pattern>                                  /表示相对当前路径  映射上面那个class 自己命名的值会显示在URL栏
  </servlet-mapping>         

servlet访问原理                                               

  • url-pattern绑定 路径。访问的是xxx ,通过name 获得当前全路径名称
  • 底层通过反射,创建了实例

补充一个Servlet 简单案例: 

 重点是浏览器设置不缓存

下面代码设置了浏览器不缓存,避免出现 修改服务器端给浏览器的响应  而浏览器显示不改变 的情况!

如果已经出现的话,清空浏览器缓存,或者重启。

package com.yidongxueyuan.web.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 AServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doPost(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		
		response.getWriter().println("yyy");
		
		//设置浏览器不缓存: 
		// 同时出现,设置浏览器的不缓存: 
		response.setHeader("expires", "-1");
		response.setHeader("Pragma", "no-cache");// http10.0 
		response.setHeader("Cache-Control", "no-cache");// http1.1
			
	}

}

response.setHeader("expires", "-1");  中的 第二个参数 不一定非得是-1,只要小于当前时间的毫秒值,即可。一般是-1或0


  
  
 重点介绍三种实现方式

方式一: 实现步骤
   (1)   创建一个类: 类实现implements Servlet 
   (2)   重写Servlet当中的方法: 
   (3)  访问》  通过浏览器访问: 

下面程序中: servlet实例被创建的时候,自动执行init方法。

继承之后要重写的五个方法中,三个是servlet生命周期的方法

package com.yidongxueyuan.web.servlet;

import java.io.IOException;

import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class FirstServlet implements Servlet {
	//第一步: 创建一个Servlet 实例: 
	public FirstServlet(){
		System.out.println("servlet 被创建了");
	}
	
	//初始化方法:  对当前的Servlet 进行初始化操作: 
	@Override
	public void init(ServletConfig paramServletConfig) throws ServletException {
		System.out.println("init方法被执行了,完成了一个初始化操作。 ");
	}

	@Override
	public ServletConfig getServletConfig() {
		return null;
	}

	//service 方法: 对客户端的请求 进行相关的处理: 
	@Override
	public void service(ServletRequest request,
			ServletResponse paramServletResponse) throws ServletException,
			IOException {
		
		System.out.println("serice方法被执行了。。。。。。");
	}

	@Override
	public String getServletInfo() {
		return null;
	}

	@Override
	public void destroy() {
		System.out.println("destroy方法被执行了。 此时Servlet被销毁。 ");

	}

}

方式二:继承GenericServlet:类。 

  • servlet是单例的,如果定义全局变量 的话,当多线程并发访问时候,会出现数据 安全问题。(尽量不要使用单例)

       第二种方式用了config对象作为全局变量,所以不太好。

关于这个类,手写如下:

package com.yidongxueyuan.web.servlet;

import java.io.IOException;
import java.util.Enumeration;

import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/*
 * 自定义的GenericServlet: 
 */
public class MyGenericServlet implements Servlet {//Servlet 单例:  定义的全局变量 会引发数据安全问题。  尽量不要使用全局变量。 
	
	//提供一个了一个全局的config对象: 
	private ServletConfig config; 
	
	//不是一个生命周期方法: 
	public void init(){
		
	}
	
	//生命周期方法: 
	@Override
	public void init(ServletConfig config) throws ServletException {
		this.config=config; 
		init(); 
	}

	@Override
	public ServletConfig getServletConfig() {
		return config;
	}

	@Override
	public void service(ServletRequest paramServletRequest,
			ServletResponse paramServletResponse) throws ServletException,
			IOException {
			
	}

	@Override
	public String getServletInfo() {
		return "这是一个快乐的Servlet ";
	}

	@Override
	public void destroy() {

	}
	
	
	
	
	//提供一个方法; 获得servlet 的名称: 
	public String getServletName(){
		String servletName = config.getServletName();
		return servletName; 
	}
	
	//提供一个方法:获得初始化参数的值: 
	public String getInitParameter(String key){
		String value = config.getInitParameter(key);
		return value; 
	}
	
	//获得初始化参数的名称; 
	public Enumeration  getInitParamNames(){
		return config.getInitParameterNames();
	}
	
	//获得上下文环境对象: 
	public ServletContext getServletContext(){
		return config.getServletContext();
	}
	
	
}

深入这个类的目的:是为了让别的类去继承,那么现在手写一个类去继承


import javax.servlet.ServletConfig;
import javax.servlet.ServletException;

public  class BServlet extends MyGenericServlet {
	//一堆: 实现Servlet的方式二: 
	
	
	//这是一个生命周期方法: 原因: 覆写了父类的生命周期方法; 那么父类的init方法单中所有的操作被覆盖了。 引发了其他的方法不能被使用。  
	/*@Override
	public void init(ServletConfig config) throws ServletException {
		System.out.println("xxxx");
	}*/
	@Override
	public void init() {
//		.....
	}
	
	
	
}

如果重写init方法的话:

这是一个生命周期方法: 原因-- 覆写了父类的声明周期方法; 那么父类的init方法单中所有的操作被覆盖了。 引发了其他的方法不能被使用。

那么该如何解决呢?

在被继承的父类Generic中写一个重载的方法

//不是一个生命周期方法: 
	public void init(){
		
	}
	
	//生命周期方法: 
	@Override
	public void init(ServletConfig config) throws ServletException {
		this.config=config; 
		init(); 
	}

这样的话,子类再去继承的时候,重写无参的方法即可

方式三:继承HttpServlet:

重点!!!!!! 与第二种实现方式的关系如下:

API文档中提到:必须去复写其中一个方法

 HttpServlet类:详解:  
   HttpServlet类提供的自定义的方法: 不是生命周期的方法: 
   service(HttpServletReuqest request, HttpServletResponse response); //提供的方法:
   在该方法当中, 可以获得客户端的请求方式, 根据不同的请求方式,做了具体的派发。 
   例如: get请求  :   调用doGet方法: 
               post请求: doPost方法:  
      
    原有的生命周期的方法;      service(ServletRequest req, ServletResponse res) 
   
   在生命周期方法当中, 将req 强制转换成了其子类对象, 调用了service方法(该类源码): 

 {
     HttpServletRequest request;
     HttpServletResponse response;
     try
     {
       request = (HttpServletRequest)req;
       response = (HttpServletResponse)res;
     }
     catch (ClassCastException e)
     {
       throw new ServletException("non-HTTP request or response");
     }
     service(request, response);
   }

* 很多人在继承这个类之后重写方法的时候直接重写的是service方法,既可以处理post,又可以处理get,但是坏处在于:父类已经给你给你完成的 (针对不同请求分类的派发操作) 会被复写掉,不建议但是可以。

实现具体步骤如下:

 (1)类 继承HttpServlet。 
 (2)重写doGet方法或者是doPost方法即可。 
 (3)配置: web.xml 

补充   web.xml文件中配置<context-param>和<init-param>的区别

{
<context-param>和<init-param>都是上下文参数,但它们的范围和使用方式不同。

<context-param>是application范围内的初始化参数,用于向servlet-context提供键值对,即应用程序的上下文信息,listener、filter等初始化时会用到这些信息

<init-param>是servlet范围内的参数,只能在servlet类的init()方法中取得
来源:CSDN 
原文:https://blog.csdn.net/blacktal/article/details/72843737?utm_source=copy 

}
 

1 注册 先写class里面的全路径名称  然后写上面的 name 理论上任意,但规范是类名

2 写下面的映射(以前写过)


 (4)访问: \
 代码如下:

import java.io.IOException;
import java.util.Enumeration;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/*
 * 实现三: 
 1)类 继承HttpServlet。 
 (2)重写doGet方法或者是doPost方法即可。 
 (3)配置: web.xml 
 (4)访问:  http://localhost:8080/javaEE-04/servlet/AServlet
  
 */
public class AServlet extends HttpServlet {
	@Override
	public void init() throws ServletException {
	    System.out.println("AServlet被创建了 并且完成了初始化");
	}
    @Override
	public  void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
    	
    	//获得一个参数的值: 
    	String value= this.getServletConfig().getInitParameter("username");
    	System.out.println(value);
    	
    	System.out.println("============");
    	
    	//获得参数的名称: 
    	Enumeration<String> enumeration = this.getServletConfig().getInitParameterNames();
    	while(enumeration.hasMoreElements()){
    		String nextElement = enumeration.nextElement();// 参数的名称: 
    		String val =  this.getServletConfig().getInitParameter(nextElement);
    		System.out.println(nextElement+"	"+val);
    	}
    	System.out.println("============");
    	//获得servlet的名称: 
    	String servletName = this.getServletConfig().getServletName();
    	System.out.println("servletName"+servletName);
    	
    	//获得上下文对象: 
    	ServletContext servletContext = getServletConfig().getServletContext();
    	System.out.println("servletContext"+servletContext);
    	
    	System.out.println("doget方法被执行了");
	}
    
    
    @Override
    public void doPost(HttpServletRequest req, HttpServletResponse resp)
    		throws ServletException, IOException {
    	System.out.println("dopost方法被执行了");
    }
}

注:以后凡是说servlet的都是指第三种实现方式的servlet。


 Servlet的补充: 


1: web的三大组件: 
  Servlet: 动态资源(作用是处理请求)
  Filter : 过滤器
  Listener: 监听器
  
2:作用: 
  接收请求: 
  处理请求: 
  完成响应: 
  
  
3:  初始化的方法,init service的方法, 参数都是来源于Tomcat服务器。 
  Tomcat服务器帮忙创建的。

4 :config 对象

config对象: 类型ServletConfig 接口


     config 对象当中的方法: 
     java.lang.String getInitParameter(java.lang.String name) 
     Gets the value of the initialization parameter with the given name. 
     java.util.Enumeration<java.lang.String> getInitParameterNames() 
     Returns the names of the servlet's initialization parameters as an Enumeration of String objects, or an empty Enumeration if       the servlet has no initialization parameters. 
      ServletContext getServletContext() 
      Returns a reference to the ServletContext in which the caller is executing. 
      java.lang.String getServletName() 
      Returns the name of this servlet instance. 
     

Servlet的配置信息都保存在当前的对象中   具体哪些信息如下:

ServletConfig 对象 : 对应Servlet的配置信息------------

<servlet>
       <servlet-name>FirstServlet</servlet-name>
       <servlet-class>com.yidongxueyuan.web.servlet.FirstServlet</servlet-class>
       <!-- 给出一些配置的参数 ,给出的初始化参数只能在当前的Servlet当中有效: -->
       
       <init-param>
       	   <param-name>encoding</param-name>
       	   <param-value>gbk</param-value>
       </init-param>
       
        <init-param>
       	   <param-name>encoding1</param-name>
       	   <param-value>utf-8</param-value>
       </init-param>
  </servlet>
  
  <!-- 映射 -->
  <servlet-mapping>
  	  <servlet-name>FirstServlet</servlet-name>
  	  <url-pattern>/FirstServlet</url-pattern>
  </servlet-mapping>
</web-app>

 
  

猜你喜欢

转载自blog.csdn.net/qq_41517071/article/details/83003059