您的位置:首页 > 运维架构 > Tomcat

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

2017-01-12 12:45 543 查看
在上一节的程序中有一个严重的问题,ServletProcessor.process()方法:

[java] view
plain copy

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类中添加一个测试方法

[java] view
plain copy

public void Test(){

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

}

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

[java] view
plain copy

<span style="white-space:pre"> </span>public void Test(){

System.out.println("这个方法是Response类特有的,不能再servlet中进行调用");

}

在MyFirstServlet类中通过向下转型调用上面两个测试方法:

[java] view
plain copy

@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,可以调用<span style="font-family: Arial, Helvetica, sans-serif;">Request中的公有方法和属性</span>

Response rs=(Response) res;//向下转型为Response,<span style="font-family: Arial, Helvetica, sans-serif;">可以调用</span><span style="font-family: Arial, Helvetica, sans-serif;">Response</span><span style="font-family: Arial, Helvetica, sans-serif;">中的公有方法和属性</span><span style="font-family: Arial, Helvetica, sans-serif;">

</span> re.Test();

rs.Test();

/***********************************/

}

在浏览器中输入http://127.0.0.1:8888/servlet/MyFirstServlet后,控制台显示如下:



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

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



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

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

[java] view
plain copy

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);

}

}

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

[java] view
plain copy

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()方法中

[java] view
plain copy

<span style="white-space:pre"> </span>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中自己的方法了,同时运行结果也和上一节相同。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: