JavaWeb世界(二):Servlet

Servlet

一、Servlet简介

二、Servlet编写一个简单的程序

三、Servlet的生命周期

四、Servlet的请求流程

五、Servlet的初始化参数

六、Servlet的继承体系

1.MyGenericServlet

如上图,每一个自定义Servlet类都要编写红色方框中的代码,当有多个Servlet类时,会造成严重的代码冗余。所以我们进行代码重构以消除冗余。

解决方案:定义MyGenericServlet,定义上述三行红框中的代码:

abstract public class MyGenericServlet implements Servlet {

	private ServletConfig config;

	public void init(ServletConfig config) throws ServletException {
		this.config = config;
	}

	abstract public void service(ServletRequest arg0, ServletResponse arg1) 
			throws ServletException, IOException;

	//把ServletConfig对象暴露给子类访问
	public ServletConfig getServletConfig() {
		return this.config;
	}

	public void destroy() {

	}

	public String getServletInfo() {
		return null;
	}

}

然后Servlet1和Servlet2继承该类:


public class Servlet2 extends MyGenericServlet {

	public void service(ServletRequest arg0, ServletResponse arg1) 
			throws ServletException, IOException {
		String encoding = super.getServletConfig().getInitParameter("encoding");
		System.out.println(encoding);
	}
}

但是看这样一行代码:

String encoding = super.getServletConfig().getInitParameter("encoding");

我觉得这样写太麻烦,代码太长,希望写成这样:

String encoding = super.getInitParameter("encoding");

我们在MyGenericServlet类中实现ServletConfig接口,在父类中替子类实现getServletConfig方法,完整代码如下:

abstract public class MyGenericServlet implements Serializable, Servlet, ServletConfig {

	private static final long serialVersionUID = 8151798658022325157L;
	private ServletConfig config;

	public void init(ServletConfig config) throws ServletException {
		this.config = config;
	}

	abstract public void service(ServletRequest arg0, ServletResponse arg1) 
            throws ServletException, IOException;

	//把ServletConfig对象暴露给子类访问
	public ServletConfig getServletConfig() {
		return this.config;
	}

	public void destroy() {

	}

	public String getServletInfo() {
		return null;
	}

	//-------------------------------------------
	public String getInitParameter(String arg0) {
		return config.getInitParameter(arg0);
	}

	public Enumeration<String> getInitParameterNames() {
		return config.getInitParameterNames();
	}

	public ServletContext getServletContext() {
		return config.getServletContext();
	}

	public String getServletName() {
		return config.getServletName();
	}

}

用这样的继承体系之后,虽然设计有点难度,但是开发的时候却变得非常简单,但是Servlet的继承体系还远不止这些。

2.init

如果子类要做自身的初始化操作,此时必须覆盖父类的init方法,并编写自己的初始化方法。

public class Servlet1 extends MyGenericServlet{

	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		System.out.println("初始化...");
	}
	
	public void service(ServletRequest arg0, ServletResponse arg1) 
			throws ServletException, IOException {
		
	}
}

但是若忘掉调用父类的init方法,那么父类中的config便会是空指针,服务器会报500错误。,

为了解决开发者在做自身初始化操作时忘记 super.init() ,Java在MyGenericServlet,专门提供了一个无参数的初始化方法init(),专门暴露给子类做初始化操作。

然后Servlet1中init()变成了:

public class Servlet1 extends MyGenericServlet {

	public void init() {
		System.out.println("无参数初始化...");
	}

	public void service(ServletRequest arg0, ServletResponse arg1) 
			throws ServletException, IOException {

	}
}

是不是简单了许多,这就是多态思想,调用了子类中的 init()

这是Sun公司一个人性化的设计。

3.MyHttpServlet

上述的Servlet1只能处理一般的响应,但是做BS开发,都是基于浏览器的,而基于浏览器都遵循HTTP协议。

        //只能处理一般的请求
	public void service(ServletRequest req, ServletResponse resp) 
			throws ServletException, IOException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;
		service(request,response);
	}
	
	//专门处理HTTP请求
	public void service(HttpServletRequest req, HttpServletResponse resp) 
			throws ServletException, IOException {
	}

上述代码没有问题,但是在处理http的service方法,会统一处理GET/POST请求,那如果GET和POST方法需要不同的处理,所以我们分成两个方法:doGet(), doPost():

	//专门处理HTTP请求
	public void service(HttpServletRequest req, HttpServletResponse resp) 
			throws ServletException, IOException {
		String method = req.getMethod();
		if ("GET".equals(method)) {
			doGet(req,resp);
		} else if ("POST".equals(method)){
			doPost(req,resp);
		}
	}

	//专门处理POST请求
	private void doPost(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("Servlet1.doPost()");
	}

	//专门处理GET请求
	private void doGet(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("Servlet1.doGet()");
	}

但是又出现了问题:每一个Servlet都要编写那么多的代码,因此我们又想到了封装,提取出一个专门用于处理HTTP协议的Servlet出来。

public class MyHttpServlet extends MyGenericServlet {
	//只能处理一般的请求
	public void service(ServletRequest req, ServletResponse resp) 
			throws ServletException, IOException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;
		service(request, response);
	}

	//专门处理HTTP请求
	public void service(HttpServletRequest req, HttpServletResponse resp) 
			throws ServletException, IOException {
		String method = req.getMethod();
		if ("GET".equals(method)) {
			doGet(req, resp);
		} else if ("POST".equals(method)) {
			doPost(req, resp);
		}
	}

	//专门处理POST请求
	private void doPost(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("Servlet1.doPost()");
	}

	//专门处理GET请求
	private void doGet(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("Servlet1.doGet()");
	}

}

抽取出MyHttpServlet,以后只要继承MyHttpServlet即可,再提供处理请求的service/doGet/doPost方法。

其实这里也体现了模板方法设计模式(含有doXXX方法通常要在子类调用,称为钩子方法)

简要总结如下:

编写Servlet的方式:

public class Servlet1 extends HttpServlet {

	public void service(HttpServletRequest req, HttpServletResponse resp) 
			throws ServletException, IOException {
		
	}
	
	public void doGet(HttpServletRequest req, HttpServletResponse resp) 
			throws ServletException, IOException {
		this.doPost(req, resp);
               //编写处理所有请求的代码
	}
	
	public void doPost(HttpServletRequest req, HttpServletResponse resp) 
			throws ServletException, IOException {
		
	}
}

并且在自己写Servlet的service方法时,应该去掉super.service()方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值