javaWEB总结(8):自定义GenericServlet

本文通过具体实践,对比了直接实现Servlet接口与继承GenericServlet类的区别,重点介绍了如何通过继承简化Servlet配置参数的获取。

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

前言:

项目的实际应用中,我们往往为了方便去继承GenericServlet类,而不是去实现Servlet接口,是什么原因呢?下面进行简单的实践操作。

一. 准备工作


1.首先看GenericServlet的API:

GenericServlet

javax.servlet
Class GenericServlet

All Implemented Interfaces:
Serializable, Servlet, ServletConfig
Direct Known Subclasses:

HttpServlet

Method Summary
 voiddestroy()
          Called by the servlet container to indicate to a servlet that the servlet is being taken out of service.
 StringgetInitParameter(String name)
          Returns a String containing the value of the named initialization parameter, ornull if the parameter does not exist.
 EnumerationgetInitParameterNames()
          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.
 ServletConfiggetServletConfig()
          Returns this servlet's ServletConfig object.
 ServletContextgetServletContext()
          Returns a reference to the ServletContext in which this servlet is running.
 StringgetServletInfo()
          Returns information about the servlet, such as author, version, and copyright.
 StringgetServletName()
          Returns the name of this servlet instance.
 voidinit()
          A convenience method which can be overridden so that there's no need to callsuper.init(config).
 voidinit(ServletConfig config)
          Called by the servlet container to indicate to a servlet that the servlet is being placed into service.
 voidlog(String msg)
          Writes the specified message to a servlet log file, prepended by the servlet's name.
 voidlog(String message,Throwable t)
          Writes an explanatory message and a stack trace for a given Throwable exception to the servlet log file, prepended by the servlet's name.
abstract  voidservice(ServletRequest req,ServletResponse res)
          Called by the servlet container to allow the servlet to respond to a request.

可以看出:GenericServlet共有两个实现类Servlet和ServletConfig,还有一个子类HttpServlet.


二. 项目实践


实验目标:在web.xml中分别定义当前web应用的参数和当前servlet的参数,并在java类当中获取,控制台中打印出来。


2.1 只实现servlet的方式:


(a)项目目录结构:



(b)web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
    <display-name>javaWeb_08</display-name>
    
    <!-- 当前web应用的参数 -->
    <context-param>
    	<param-name>user1</param-name>    
    	<param-value>admin</param-value>
    </context-param>
    <context-param>
    	<param-name>password1</param-name>
    	<param-value>123456</param-value>
    </context-param>
    
    <servlet>
        <!-- 当前servlet的参数 -->
        <init-param>
            <param-name>user2</param-name>
            <param-value>admin</param-value>
        </init-param>
        <init-param>
            <param-name>password2</param-name>
            <param-value>123456</param-value>
        </init-param>
        
        <servlet-name>MyGenericServlet</servlet-name>
        <servlet-class>com.dao.chu.MyGenericServlet</servlet-class>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>MyGenericServlet</servlet-name>
        <url-pattern>/MyGenericServlet</url-pattern>
    </servlet-mapping>
    
</web-app>

(c) MyGenericServlet.java

package com.dao.chu;

import java.io.IOException;

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

/**
 * 
* <p>Title: MyGenericServlet</p>
* <p>Description: 自定义MyGenericServlet</p>
 */
public class MyGenericServlet implements Servlet{
	
	
	//ServletConfig对象,在init方法执行后赋值
	private ServletConfig servletConfig;

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

	//ServletConfig对象的get方法
	@Override
	public ServletConfig getServletConfig() {
		return servletConfig;
	}

	@Override
	public String getServletInfo() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void init(ServletConfig servletConfig) throws ServletException {
		
		System.out.println("init...");
		this.servletConfig=servletConfig;
		
	}

	@Override
	public void service(ServletRequest servletRequest, ServletResponse servletResponse)
			throws ServletException, IOException {
		
		//得到servletContext对象
		ServletContext servletContext = servletConfig.getServletContext();
		
		//当前web应用的参数
		String user1 = servletContext.getInitParameter("user1");
		String password1 = servletContext.getInitParameter("password1");
		
		String user2 = servletConfig.getInitParameter("user2");
		String password2 = servletConfig.getInitParameter("password2");
		
		
		System.out.println("user1 is: "+user1);
		System.out.println("passwrod1 is: "+password1);
		System.out.println("user2 is: "+user2);
		System.out.println("passwrod2 is: "+password2);
	}

	

}

(d) 运行结果

e)小结:我们首先需要获取servletConfig对象,而servletConfig对象在init方法中,方法却写在service方法中,所以我们定义了私有的servletConfig对象,并在init方法中把参数传给我们定义的servletConfig对象,写好servletConfig的get方法。



2.2 将MyGenericServlet作为父类,其他类来继承这个类


(a)项目结构:

(b) web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
    <display-name>javaWeb_08</display-name>
    
    <!-- 当前web应用的参数 -->
    <context-param>
    	<param-name>user1</param-name>    
    	<param-value>admin</param-value>
    </context-param>
    <context-param>
    	<param-name>password1</param-name>
    	<param-value>123456</param-value>
    </context-param>
    
    <servlet>
        <!-- 当前servlet的参数 -->
        <init-param>
            <param-name>user2</param-name>
            <param-value>admin</param-value>
        </init-param>
        <init-param>
            <param-name>password2</param-name>
            <param-value>123456</param-value>
        </init-param>
        
        <servlet-name>myGenericServletExtends</servlet-name>
        <servlet-class>com.dao.chu.MyGenericServletExtends</servlet-class>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>myGenericServletExtends</servlet-name>
        <url-pattern>/myGenericServletExtends</url-pattern>
    </servlet-mapping>
    
</web-app>

(c) MyGenericServlet

package com.dao.chu;

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

/**
 * 
* <p>Title: MyGenericServlet</p>
* <p>Description: 自定义MyGenericServlet</p>
 */
public abstract class MyGenericServlet implements Servlet{
	
	
	//ServletConfig对象,在init方法执行后赋值
	private ServletConfig servletConfig;

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

	//ServletConfig对象的get方法
	@Override
	public ServletConfig getServletConfig() {
		return servletConfig;
	}

	@Override
	public String getServletInfo() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void init(ServletConfig servletConfig) throws ServletException {
		
		System.out.println("init...");
		this.servletConfig=servletConfig;
		
	}

	/**
	 * 抽象方法,必需被子类实现
	 */
	@Override
	public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse);

}

(d) MyGenericServletExtends

package com.dao.chu;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
 * 
* <p>Title: MyGenericServletExtends</p>
* <p>Description: MyGenericServlet的子类</p>
 */
public class MyGenericServletExtends extends MyGenericServlet{

	@Override
	public void service(ServletRequest srvletRequest,
			ServletResponse servletResponse) {
		
		String user1 = getServletConfig().getServletContext().getInitParameter("user1");
		String password1 = getServletConfig().getServletContext().getInitParameter("password1");
		
		
		String user2 = getServletConfig().getInitParameter("user2");
		String password2 = getServletConfig().getInitParameter("password2");
		
		
		System.out.println("user1:"+user1);
		System.out.println("user2:"+user2);
		System.out.println("password1:"+password1);
		System.out.println("password2:"+password2);
		
	}

}

(e) 运行结果:

f)小结:我们大多的业务操作都在service里面,虽然servlet当中的方法很多,也不需要所有都去实现,我们定义的MyGenericServlet只需让他的子类必需实现service方法就可以,所以MyGenericServlet定义为抽象类,service方法定义为抽象方法。


2.3 和API中一致,加入实现ServletConfig

(a) 目录结构:

b)web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
    <display-name>javaWeb_08</display-name>
    
    <!-- 当前web应用的参数 -->
    <context-param>
    	<param-name>user1</param-name>    
    	<param-value>admin</param-value>
    </context-param>
    <context-param>
    	<param-name>password1</param-name>
    	<param-value>123456</param-value>
    </context-param>
    
    <servlet>
        <!-- 当前servlet的参数 -->
        <init-param>
            <param-name>user2</param-name>
            <param-value>admin</param-value>
        </init-param>
        <init-param>
            <param-name>password2</param-name>
            <param-value>123456</param-value>
        </init-param>
        
        <servlet-name>myGenericServletExtends</servlet-name>
        <servlet-class>com.dao.chu.MyGenericServletExtends</servlet-class>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>myGenericServletExtends</servlet-name>
        <url-pattern>/myGenericServletExtends</url-pattern>
    </servlet-mapping>
    
</web-app>

(c) MyGenericServlet

package com.dao.chu;

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;

/**
 * 
* <p>Title: MyGenericServlet</p>
* <p>Description: 自定义MyGenericServlet</p>
 */
public abstract class MyGenericServlet implements Servlet,ServletConfig{
	
	
	//ServletConfig对象,在init方法执行后赋值
	private ServletConfig servletConfig;

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

	//ServletConfig对象的get方法
	@Override
	public ServletConfig getServletConfig() {
		return servletConfig;
	}

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

	@Override
	public void init(ServletConfig servletConfig) throws ServletException {
		
		System.out.println("init...");
		this.servletConfig=servletConfig;
		
	}

	/**
	 * 抽象方法,必需被子类实现
	 */
	@Override
	public abstract void service(ServletRequest servletRequest, ServletResponse servletResponse);
	
	
	
	//实现ServletConfig的方法
	@Override
	public String getServletName() {
		return getServletConfig().getServletName();
	}

	@Override
	public ServletContext getServletContext() {
		return getServletConfig().getServletContext();
	}

	@Override
	public String getInitParameter(String paramString) {
		return getServletConfig().getInitParameter(paramString);
	}

	@Override
	public Enumeration<String> getInitParameterNames() {
		return getServletConfig().getInitParameterNames();
	}

}

(d) MyGenericServletExtends

package com.dao.chu;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
 * 
* <p>Title: MyGenericServletExtends</p>
* <p>Description: MyGenericServlet的子类</p>
 */
public class MyGenericServletExtends extends MyGenericServlet{

	@Override
	public void service(ServletRequest srvletRequest,
			ServletResponse servletResponse) {
		
		String user1 = getServletContext().getInitParameter("user1");
		String password1 = getServletContext().getInitParameter("password1");
		
		
		String user2 = getInitParameter("user2");
		String password2 = getInitParameter("password2");
		
		
		System.out.println("user1:"+user1);
		System.out.println("user2:"+user2);
		System.out.println("password1:"+password1);
		System.out.println("password2:"+password2);
		
	}

}

(e) 控制台输出:


(f)小结:我们已经得到了servletConfig对象,又实现了servletConfig的接口,所以可以直接调用里面的方法,代码也变得更加简洁。


三 为了防止子类覆盖MyGenericServlet中init(ServletConfig servletConfig)的方法出现的错误,自定义MyGenericServlet修改如下:

package com.dao.chu;

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;

/**
 * 
 * <p>
 * Title: MyGenericServlet
 * </p>
 * <p>
 * Description: 自定义MyGenericServlet
 * </p>
 */
public abstract class MyGenericServlet implements Servlet, ServletConfig {

	// ServletConfig对象,在init方法执行后赋值
	private ServletConfig servletConfig;
	
	/**
	 * 实现Servlet的方法
	 */

	@Override
	public void destroy() {

	}

	@Override
	public String getServletInfo() {
		return "";
	}
	
	// ServletConfig对象的get方法
	@Override
	public ServletConfig getServletConfig() {
		return servletConfig;
	}

	@Override
	public void init(ServletConfig servletConfig) throws ServletException {

		this.servletConfig = servletConfig;
		init();

	}

	// 空的init函数,用来给子类继承,防止覆盖init(ServletConfig servletConfig)方法引起的错误
	public void init() {

	}

	//抽象方法,必需被子类实现
	@Override
	public abstract void service(ServletRequest servletRequest,
			ServletResponse servletResponse);

	/**
	 * 实现ServletConfig的方法
	 */
	
	@Override
	public String getServletName() {
		return getServletConfig().getServletName();
	}

	@Override
	public ServletContext getServletContext() {
		return getServletConfig().getServletContext();
	}

	@Override
	public String getInitParameter(String paramString) {
		return getServletConfig().getInitParameter(paramString);
	}

	@Override
	public Enumeration<String> getInitParameterNames() {
		return getServletConfig().getInitParameterNames();
	}

}

基本还原API中的一些方法。


附:

本次项目代码:点击打开链接

     


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值