手写一个民用Tomcat (05)

server/2024/9/24 3:35:13/

继续我们这次的优化,上次是request, 这次是response,同时request,response 针对 引入门面模式,把负责的逻辑隐藏起来,展示一个 好的好的门面给servlet 。

先看下 response 

public class JxdResponse implements HttpServletResponse {private static final int BUFFER_SIZE = 1024;JxdRequest request;OutputStream output;PrintWriter writer;String contentType = null;long contentLength = -1;String charset = null;String characterEncoding = null;String protocol = "HTTP/1.1";public OutputStream getOutput() {return output;}public void setOutput(OutputStream output) {this.output = output;}public JxdResponse(OutputStream output) {this.output = output;}public void setRequest(JxdRequest request) {this.request = request;}//headers是一个保存头信息的mapMap<String, String> headers = new ConcurrentHashMap<>();//默认返回OKString message = getStatusMessage(HttpServletResponse.SC_OK);int status = HttpServletResponse.SC_OK;@Overridepublic void addHeader(String name, String value) {headers.put(name, value);if (name.toLowerCase() == DefaultHeaders.CONTENT_LENGTH_NAME) {setContentLength(Integer.parseInt(value));}if (name.toLowerCase() == DefaultHeaders.CONTENT_TYPE_NAME) {setContentType(value);}}@Overridepublic void setHeader(String name, String value) {headers.put(name, value);if (name.toLowerCase() == DefaultHeaders.CONTENT_LENGTH_NAME) {setContentLength(Integer.parseInt(value));}if (name.toLowerCase() == DefaultHeaders.CONTENT_TYPE_NAME) {setContentType(value);}}//"HTTP/1.1 ${StatusCode} ${StatusName}\r\n" +//            "Content-Type: ${ContentType}\r\n" +//            "Server: minit\r\n" +//            "Date: ${ZonedDateTime}\r\n" +public void sendHeaders() throws IOException {PrintWriter outputWriter = getWriter();//下面这一端是输出状态行outputWriter.print(this.getProtocol());outputWriter.print(" ");outputWriter.print(status);if (message != null) {outputWriter.print(" ");outputWriter.print(message);}outputWriter.print("\r\n");if (getContentType() != null) {outputWriter.print("Content-Type: " + getContentType() + "\r\n");if (getContentLength() >= 0) {outputWriter.print("Content-Length: " + getContentLength() + "\r\n");}//输出头信息Iterator<String> names = headers.keySet().iterator();while (names.hasNext()) {String name = names.next();String value = headers.get(name);outputWriter.print(name);outputWriter.print(": ");outputWriter.print(value);outputWriter.print("\r\n");}//最后输出空行outputWriter.print("\r\n");outputWriter.flush();}}/*** 获取状态码返回信息** @param status* @return*/protected String getStatusMessage(int status) {switch (status) {case SC_OK:return ("OK");case SC_ACCEPTED:return ("Accepted");case SC_BAD_GATEWAY:return ("Bad Gateway");case SC_BAD_REQUEST:return ("Bad Request");case SC_CONTINUE:return ("Continue");case SC_FORBIDDEN:return ("Forbidden");case SC_INTERNAL_SERVER_ERROR:return ("Internal Server Error");case SC_METHOD_NOT_ALLOWED:return ("Method Not Allowed");case SC_NOT_FOUND:return ("Not Found");case SC_NOT_IMPLEMENTED:return ("Not Implemented");case SC_REQUEST_URI_TOO_LONG:return ("Request URI Too Long");case SC_SERVICE_UNAVAILABLE:return ("Service Unavailable");case SC_UNAUTHORIZED:return ("Unauthorized");default:return ("HTTP Response Status " + status);}}/*** 这个方法是静态方法演示** @throws IOException*/public void sendStaticResource() throws IOException {byte[] bytes = new byte[BUFFER_SIZE];FileInputStream fis = null;try {File file = new File(JxdHttpServer.FILE_ROOT, request.getUri());if (file.exists()) {fis = new FileInputStream(file);int ch = fis.read(bytes, 0, BUFFER_SIZE);while (ch != -1) {output.write(bytes, 0, ch);ch = fis.read(bytes, 0, BUFFER_SIZE);}output.flush();} else {String errorMessage = "HTTP/1.1 404 FIle Not Found\r\n" +"Content-Type: text/html\r\n" +"Content-Length: 23\r\n" +"\r\n" +"<h1>error未知</h1>";output.write(errorMessage.getBytes());}} catch (Exception e) {System.out.println(e.toString());} finally {if (fis != null) {fis.close();}}}public long getContentLength() {return this.contentLength;}public void setContentLength(long contentLength) {this.contentLength = contentLength;}public String getProtocol() {return protocol;}public void setProtocol(String protocol) {this.protocol = protocol;}@Overridepublic String getContentType() {return this.contentType;}@Overridepublic PrintWriter getWriter() throws IOException {writer = new PrintWriter(new OutputStreamWriter(output, getCharacterEncoding()), true);return writer;}@Overridepublic String getCharacterEncoding() {return characterEncoding;}@Overridepublic void setCharacterEncoding(String characterEncoding) {this.characterEncoding = characterEncoding;}
}

我们整理了一下,返回引入一个getStatusMessage 方法和 sendHeaders 方法 这样不用再拼接字符串了。

在看一下我们的 JxdServletProcessor

    public void process(JxdRequest request, JxdResponse response) {
//首先根据uri最后一个/号来定位,后面的字符串认为是servlet名字String uri = request.getUri();String servletName = uri.substring(uri.lastIndexOf("/") + 1);URLClassLoader loader = null;try {
// create a URLClassLoaderURL[] urls = new URL[1];URLStreamHandler streamHandler = null;File classPath = new File(JxdHttpServer.WEB_ROOT);String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString();urls[0] = new URL(null, repository, streamHandler);loader = new URLClassLoader(urls);} catch (IOException e) {System.out.println(e.toString());}//由上面的URLClassLoader加载这个servletClass<?> servletClass = null;Servlet servlet = null;try {HttpRequestFacade requestFacade = new HttpRequestFacade(request);HttpResponseFacade responseFacade = new HttpResponseFacade(response);servletClass = loader.loadClass(servletName);response.setCharacterEncoding("UTF-8");response.addHeader(DefaultHeaders.CONTENT_TYPE_NAME,"text/html;charset=UTF-8");response.sendHeaders();servlet = (Servlet) servletClass.newInstance();servlet.service(requestFacade, responseFacade);} catch (ClassNotFoundException | IOException e) {System.out.println(e.toString());} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (ServletException e) {e.printStackTrace();}}
}

之前的 OKMessage 拼接 响应字符串方法就不需要了。

同时引入两个门面HttpRequestFacade,HttpResponseFacade

看下 我们的两个类的代码:

public class HttpRequestFacade implements HttpServletRequest {private HttpServletRequest request;public HttpRequestFacade(JxdRequest request) {this.request = request;}public Object getAttribute(String name) {return request.getAttribute(name);}public Enumeration getAttributeNames() {return request.getAttributeNames();}public String getCharacterEncoding() {return request.getCharacterEncoding();}@Overridepublic void setCharacterEncoding(String s) throws UnsupportedEncodingException {request.setCharacterEncoding(s);}public int getContentLength() {return request.getContentLength();}@Overridepublic long getContentLengthLong() {return 0;}public String getContentType() {return request.getContentType();}@Overridepublic String getAuthType() {return null;}public Cookie[] getCookies() {return request.getCookies();}@Overridepublic long getDateHeader(String s) {return 0;}@Overridepublic String getHeader(String s) {return null;}public Enumeration getHeaderNames() {return request.getHeaderNames();}public Enumeration getHeaders(String name) {return request.getHeaders(name);}public ServletInputStream getInputStream() throws IOException {return request.getInputStream();}public int getIntHeader(String name) {return request.getIntHeader(name);}public String getMethod() {return request.getMethod();}@Overridepublic String getPathInfo() {return null;}@Overridepublic String getPathTranslated() {return null;}@Overridepublic String getContextPath() {return null;}public String getParameter(String name) {return request.getParameter(name);}public Map getParameterMap() {return request.getParameterMap();}@Overridepublic String getProtocol() {return null;}@Overridepublic String getScheme() {return null;}@Overridepublic String getServerName() {return null;}@Overridepublic int getServerPort() {return 0;}public Enumeration getParameterNames() {return request.getParameterNames();}public String[] getParameterValues(String name) {return request.getParameterValues(name);}public String getQueryString() {return request.getQueryString();}@Overridepublic String getRemoteUser() {return null;}@Overridepublic boolean isUserInRole(String s) {return false;}@Overridepublic Principal getUserPrincipal() {return null;}@Overridepublic String getRequestedSessionId() {return null;}public BufferedReader getReader() throws IOException {return request.getReader();}@Overridepublic String getRemoteAddr() {return null;}@Overridepublic String getRemoteHost() {return null;}public String getRequestURI() {return request.getRequestURI();}public StringBuffer getRequestURL() {return request.getRequestURL();}@Overridepublic String getServletPath() {return null;}public HttpSession getSession() {return request.getSession();}@Overridepublic String changeSessionId() {return null;}@Overridepublic boolean isRequestedSessionIdValid() {return false;}@Overridepublic boolean isRequestedSessionIdFromCookie() {return false;}@Overridepublic boolean isRequestedSessionIdFromURL() {return false;}@Overridepublic boolean isRequestedSessionIdFromUrl() {return false;}@Overridepublic boolean authenticate(HttpServletResponse httpServletResponse) throws IOException, ServletException {return false;}@Overridepublic void login(String s, String s1) throws ServletException {}@Overridepublic void logout() throws ServletException {}@Overridepublic Collection<Part> getParts() throws IOException, ServletException {return null;}@Overridepublic Part getPart(String s) throws IOException, ServletException {return null;}@Overridepublic <T extends HttpUpgradeHandler> T upgrade(Class<T> aClass) throws IOException, ServletException {return null;}public HttpSession getSession(boolean create) {return request.getSession(create);}public void removeAttribute(String attribute) {request.removeAttribute(attribute);}@Overridepublic Locale getLocale() {return null;}@Overridepublic Enumeration<Locale> getLocales() {return null;}@Overridepublic boolean isSecure() {return false;}@Overridepublic RequestDispatcher getRequestDispatcher(String s) {return null;}@Overridepublic String getRealPath(String s) {return null;}@Overridepublic int getRemotePort() {return 0;}@Overridepublic String getLocalName() {return null;}@Overridepublic String getLocalAddr() {return null;}@Overridepublic int getLocalPort() {return 0;}@Overridepublic ServletContext getServletContext() {return null;}@Overridepublic AsyncContext startAsync() throws IllegalStateException {return null;}@Overridepublic AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException {return null;}@Overridepublic boolean isAsyncStarted() {return false;}@Overridepublic boolean isAsyncSupported() {return false;}@Overridepublic AsyncContext getAsyncContext() {return null;}@Overridepublic DispatcherType getDispatcherType() {return null;}public void setAttribute(String key, Object value) {request.setAttribute(key, value);}
}

public class HttpResponseFacade implements HttpServletResponse {private HttpServletResponse response;public HttpResponseFacade(JxdResponse response) {this.response = response;}@Overridepublic void addCookie(Cookie cookie) {response.addCookie(cookie);}@Overridepublic boolean containsHeader(String s) {return response.containsHeader(s);}@Overridepublic String encodeURL(String s) {return response.encodeURL(s);}@Overridepublic String encodeRedirectURL(String s) {return response.encodeRedirectURL(s);}@Overridepublic String encodeUrl(String s) {return response.encodeUrl(s);}@Overridepublic String encodeRedirectUrl(String s) {return response.encodeRedirectUrl(s);}@Overridepublic void sendError(int i, String s) throws IOException {response.sendError(i, s);}@Overridepublic void sendError(int i) throws IOException {response.sendError(i);}@Overridepublic void sendRedirect(String s) throws IOException {response.sendRedirect(s);}@Overridepublic void setDateHeader(String s, long l) {response.setDateHeader(s, l);}@Overridepublic void addDateHeader(String s, long l) {response.addDateHeader(s, l);}@Overridepublic void setHeader(String s, String s1) {response.setHeader(s, s1);}@Overridepublic void addHeader(String s, String s1) {response.addHeader(s, s1);}@Overridepublic void setIntHeader(String s, int i) {response.setIntHeader(s, i);}@Overridepublic void addIntHeader(String s, int i) {response.addIntHeader(s, i);}@Overridepublic void setStatus(int i) {response.setStatus(i);}@Overridepublic void setStatus(int i, String s) {response.setStatus(i, s);}@Overridepublic int getStatus() {return response.getStatus();}@Overridepublic String getHeader(String s) {return response.getHeader(s);}@Overridepublic Collection<String> getHeaders(String s) {return response.getHeaders(s);}@Overridepublic Collection<String> getHeaderNames() {return response.getHeaderNames();}@Overridepublic String getCharacterEncoding() {return response.getCharacterEncoding();}@Overridepublic String getContentType() {return response.getContentType();}@Overridepublic ServletOutputStream getOutputStream() throws IOException {return response.getOutputStream();}@Overridepublic PrintWriter getWriter() throws IOException {return response.getWriter();}@Overridepublic void setCharacterEncoding(String s) {response.setCharacterEncoding(s);}@Overridepublic void setContentLength(int i) {response.setContentLength(i);}@Overridepublic void setContentLengthLong(long l) {response.setContentLengthLong(l);}@Overridepublic void setContentType(String s) {response.setContentType(s);}@Overridepublic void setBufferSize(int i) {response.setBufferSize(i);}@Overridepublic int getBufferSize() {return response.getBufferSize();}@Overridepublic void flushBuffer() throws IOException {response.flushBuffer();}@Overridepublic void resetBuffer() {response.resetBuffer();}@Overridepublic boolean isCommitted() {return response.isCommitted();}@Overridepublic void reset() {response.reset();}@Overridepublic void setLocale(Locale locale) {response.setLocale(locale);}@Overridepublic Locale getLocale() {return response.getLocale();}
}

没什么难点,主要就是引入门面模式进行整理,之前都暴露着各种方法,用户在使用的时候会看到,同时 也避免 被更改 和强转的风险。


http://www.ppmy.cn/server/10401.html

相关文章

七月论文审稿GPT第4.5版:通过15K条paper-review数据微调Llama2 70B(含各种坑)

前言 当我们3月下旬微调完Mixtral 8x7B之后(更多详见&#xff1a;七月论文大模型&#xff1a;含论文的审稿、阅读、写作、修订 )&#xff0c;下一个想微调的就是llama2 70B 因为之前积攒了不少微调代码和微调经验&#xff0c;所以3月底apple便通过5K的paper-review数据集成功…

Java——类和对象

Java是一种面向对象的程序设计语言。面向对象的程序设计&#xff0c;以对象为核心&#xff0c;强调对象之间的交互与合作。对象由属性和方法组成&#xff0c;其中属性用于描述对象的状态&#xff0c;方法用于定义对象的行为。 在Java中&#xff0c;一切皆对象&#xff0c;对象…

【LeetCode热题100】【二分查找】搜索二维矩阵

题目链接&#xff1a;74. 搜索二维矩阵 - 力扣&#xff08;LeetCode&#xff09; 在一个有序二维数组里面查找元素&#xff0c;同【LeetCode热题100】【矩阵】搜索二维矩阵 II-CSDN博客 如果用二分查找&#xff0c;时间复杂度是log(mn)&#xff0c;但是可以实现时间复杂度为O…

如何用Python构建一个生产级别的电影推荐系统 - 机器学习手册

构建项目是彻底学习概念并发展必要技能的最有效方式之一。 项目使您沉浸在现实世界的问题解决中&#xff0c;巩固您的知识&#xff0c;并培养批判性思维、适应能力和项目管理专业知识。 本指南将带您逐步构建一个根据用户喜好量身定制的电影推荐系统。我们将利用一个庞大的包…

手撕红黑树(map和set底层结构)(2)

[TOC]红黑树 一 红黑树概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制&#xff0c;红黑树确保没有一条路径会比其他路径长出俩倍&…

软考 - 系统架构设计师 - ESB(企业服务总线)例题

问题 1&#xff1a; 根据描述 Ramp Control 是负责系统中相关各种业务活动的组件&#xff0c;根据题目描述&#xff0c;系统中包含检查机位环境&#xff0c;卸货&#xff0c;装货等业务活动&#xff0c;所以 Ramp Control 服务组件提供的服务名称就是 “负责检查机位环境&#…

编写一款2D CAD/CAM软件(十六)交互绘制图形

绘制步骤 以交互绘制圆形为例&#xff1a; 点击鼠标左键&#xff0c;确定圆心位置&#xff1b;抬起鼠标&#xff0c;移动鼠标&#xff0c;半径随鼠标位置变化&#xff1b;点击左键确定半径&#xff0c;完成圆的绘制。 绘制结果 Code /// j-operator-create-circle.h#pragma…

使用阿里云试用Elasticsearch学习:sentence-transformers 包使用

环境&#xff1a;centos8&#xff0c;windows坑太多。 一、检查linux环境openssl哪个版本&#xff08;如果是OpenSSL 1.1.1k 直接跳过&#xff09; [roothecs-334217 python39]# openssl version OpenSSL 1.0.2k-fips 26 Jan 2017原因后续会出麻烦&#xff0c;遇到这种情况最…