Tomcat学习2.2(简单的Servlet容器)

在上一节的程序中有一个严重的问题,ServletProcessor.process()方法:

try {
	servlet=(Servlet) myClass.newInstance();
	servlet.service((ServletRequest)request, (ServletResponse)response);
}
在servlet中,public void service(ServletRequest req, ServletResponse res)接受 servlet.service((ServletRequest)request, (ServletResponse)response)传过来的参数,
,因此,在service方法中可以通过向下转型的方法,将req和res分别转型为Response和Request,这样就可以访问到Request和Response中自己特有的公有方法,这是不安全的。按照servlet的设计,在service()方法中只能访问ServletRequest req接口和ServletResponse接口中已经声明的方法。

下面将简单演示这种不安全的做法:

在Request类中添加一个测试方法

	public void Test(){
		System.out.println("这个方法是Request类特有的,不能再servlet中进行调用");
	}

在Response类中添加一个测试方法

	public void Test(){
		System.out.println("这个方法是Response类特有的,不能再servlet中进行调用");
	}
在MyFirstServlet类中通过向下转型调用上面两个测试方法:
@Override
	public void service(ServletRequest req, ServletResponse res)
			throws ServletException, IOException {
		PrintWriter printWriter=res.getWriter();
		System.out.println("servlet开始执行");
		printWriter.println("Hello,Servlet");
		/***********************************/
		Request re=(Request) req;//向下转型为Request,可以调用Request中的公有方法和属性
		Response rs=(Response) res;//向下转型为Response,可以调用Response中的公有方法和属性
		re.Test();
		rs.Test();
		/***********************************/
	}
在浏览器中输入http://127.0.0.1:8888/servlet/MyFirstServlet后,控制台显示如下:

Request和Response中特有的方法被成功调用。

为了很好的解决这个问题,那么就需要使用外观类,将Request和Response自己的方法进行屏蔽(或者说私有化),这样在其它类中就不能调用它们自己的方法,UML关系简图如下:


需要上一节的基础上增加两个类,RequestFacade类和ResponseFacade类。另外,ServletProcessor类也需要做一点小的修改

=====================分割线=====================

import java.io.BufferedReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Map;

import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;


public class RequestFacade implements ServletRequest  {
	private ServletRequest request=null;//包装类的所有方法都调用request对应的方法来完成

	public RequestFacade(ServletRequest request){
		this.request=request;
	}
	
	@Override
	public AsyncContext getAsyncContext() {
		return request.getAsyncContext();
	}

	@Override
	public Object getAttribute(String name) {
		return request.getAttribute(name);
	}

	@Override
	public Enumeration<String> getAttributeNames() {
		return request.getAttributeNames();
	}

	@Override
	public String getCharacterEncoding() {
		return request.getCharacterEncoding();
	}

	@Override
	public int getContentLength() {
		return request.getContentLength();
	}

	@Override
	public String getContentType() {
		return request.getContentType();
	}

	@Override
	public DispatcherType getDispatcherType() {
		return request.getDispatcherType();
	}

	@Override
	public ServletInputStream getInputStream() throws IOException {
		return request.getInputStream();
	}

	@Override
	public String getLocalAddr() {
		return request.getLocalAddr();
	}

	@Override
	public String getLocalName() {
		return request.getLocalName();
	}

	@Override
	public int getLocalPort() {
		return request.getLocalPort();
	}

	@Override
	public Locale getLocale() {
		return request.getLocale();
	}

	@Override
	public Enumeration<Locale> getLocales() {
		return request.getLocales();
	}

	@Override
	public String getParameter(String name) {
		return request.getParameter(name);
	}

	@Override
	public Map<String, String[]> getParameterMap() {
		return request.getParameterMap();
	}

	@Override
	public Enumeration<String> getParameterNames() {
		return request.getParameterNames();
	}

	@Override
	public String[] getParameterValues(String name) {
		return request.getParameterValues(name);
	}

	@Override
	public String getProtocol() {
		return request.getProtocol();
	}

	@Override
	public BufferedReader getReader() throws IOException {
		return request.getReader();
	}

	@Override
	public String getRealPath(String path) {
		return request.getRealPath(path);
	}

	@Override
	public String getRemoteAddr() {
		return request.getRemoteAddr();
	}

	@Override
	public String getRemoteHost() {
		return request.getRemoteHost();
	}

	@Override
	public int getRemotePort() {
		return request.getRemotePort();
	}

	@Override
	public RequestDispatcher getRequestDispatcher(String path) {
		return request.getRequestDispatcher(path);
	}

	@Override
	public String getScheme() {
		return request.getScheme();
	}

	@Override
	public String getServerName() {
		return request.getServerName();
	}

	@Override
	public int getServerPort() {
		return request.getServerPort();
	}

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

	@Override
	public boolean isAsyncStarted() {
		return request.isAsyncStarted();
	}

	@Override
	public boolean isAsyncSupported() {
		return request.isAsyncSupported();
	}

	@Override
	public boolean isSecure() {
		return request.isSecure();
	}

	@Override
	public void removeAttribute(String name) {
		request.removeAttribute(name);
	}

	@Override
	public void setAttribute(String name, Object o) {
		request.setAttribute(name, o);
	}

	@Override
	public void setCharacterEncoding(String env)
			throws UnsupportedEncodingException {
		request.setCharacterEncoding(env);
	}

	@Override
	public AsyncContext startAsync() throws IllegalStateException {
		return request.startAsync();
	}

	@Override
	public AsyncContext startAsync(ServletRequest servletRequest,
			ServletResponse servletResponse) throws IllegalStateException {
		return request.startAsync(servletRequest, servletResponse);
	}
}
=====================分割线=====================
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Locale;

import javax.servlet.ServletOutputStream;
import javax.servlet.ServletResponse;


public class ResponseFacade implements ServletResponse{

	private ServletResponse response;//包装类的所有方法都有response对应的方法完成
	
	public ResponseFacade(ServletResponse response){
		this.response = response;
	}
	
	@Override
	public void flushBuffer() throws IOException {
		response.flushBuffer();
	}

	@Override
	public int getBufferSize() {
		return response.getBufferSize();
	}

	@Override
	public String getCharacterEncoding() {
		return response.getCharacterEncoding();
	}

	@Override
	public String getContentType() {
		return response.getContentType();
	}

	@Override
	public Locale getLocale() {
		return response.getLocale();
	}

	@Override
	public ServletOutputStream getOutputStream() throws IOException {
		return response.getOutputStream();
	}

	@Override
	public PrintWriter getWriter() throws IOException {
		return response.getWriter();
	}

	@Override
	public boolean isCommitted() {
		return response.isCommitted();
	}

	@Override
	public void reset() {
		response.reset();
	}

	@Override
	public void resetBuffer() {
		response.resetBuffer();
	}

	@Override
	public void setBufferSize(int size) {
		response.setBufferSize(size);
	}

	@Override
	public void setCharacterEncoding(String charset) {
		response.setCharacterEncoding(charset);
	}

	@Override
	public void setContentLength(int len) {
		response.setContentLength(len);
	}

	@Override
	public void setContentType(String type) {
		response.setContentType(type);
	}

	@Override
	public void setLocale(Locale loc) {
		response.setLocale(loc);
	}

}
=====================分割线=====================

ServletProcessor类只需新构建RequestFacade和ResponseFacade类,并将其引用作为参数传入servlet.service()方法中

		Servlet servlet=null;
		RequestFacade requestFacade = new RequestFacade(request);
		ResponseFacade responseFacade = new ResponseFacade(response);
		try {
			/**
			 * servlet实例化
			 */
			servlet=(Servlet) myClass.newInstance();
			/**
			 * 调用servlet的service()方法
			 */
			servlet.service((ServletRequest)requestFacade, (ServletResponse)responseFacade);//传入包装类
		}
程序经过上述修改后,在servlet中便不能再访问Request和Response中自己的方法了,同时运行结果也和上一节相同。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值