在上一节的程序中有一个严重的问题,ServletProcessor.process()方法:
- try {
- servlet=(Servlet) myClass.newInstance();
- 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类中添加一个测试方法
- <span style="white-space:pre"> </span>public void Test(){
- System.out.println("这个方法是Response类特有的,不能再servlet中进行调用");
- }
- @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();
- /***********************************/
- }
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()方法中
- <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);//传入包装类
- }