how2j.cn

-->
下载区
文件名 文件大小
请先登录 194k
增值内容 194k
194k
请先登录 11m
增值内容 11m
11m

解压rar如果失败,请用5.21版本或者更高版本的winrar

点击下载 winrar5.21

5分16秒
本视频采用html5方式播放,如无法正常播放,请将浏览器升级至最新版本,推荐火狐,chrome,360浏览器。 如果装有迅雷,播放视频呈现直接下载状态,请调整 迅雷系统设置-基本设置-启动-监视全部浏览器 (去掉这个选项)。 chrome 的 视频下载插件会影响播放,如 IDM 等,请关闭或者切换其他浏览器

步骤 1 : 拓扑图点亮   
步骤 2 : ApplicationFilterChain   
步骤 3 : HttpProcessor   
步骤 4 : 测试   
步骤 5 : 比较可运行项目,快速定位问题   

增值内容,请先登录
自己写一个Tomcat, 几乎使用到了除开框架外的所有Java 技术,如多线程,Socket, J2EE, 反射,Log4j, JSoup, JUnit, Html 等一整套技术栈, 从无到有,循序渐进涵盖全部74个知识点,549个开发步骤, 为竞争高薪资职位加上一个有吸引力的砝码.
增值内容,点击购买
使用爬虫已经被系统记录,请勿使用爬虫,增大封号风险。 如果是误封 ,请联系站长,谢谢
拓扑图点亮
步骤 2 :

ApplicationFilterChain

edit
增值内容,请先登录
自己写一个Tomcat, 几乎使用到了除开框架外的所有Java 技术,如多线程,Socket, J2EE, 反射,Log4j, JSoup, JUnit, Html 等一整套技术栈, 从无到有,循序渐进涵盖全部74个知识点,549个开发步骤, 为竞争高薪资职位加上一个有吸引力的砝码.
增值内容,点击购买
使用爬虫已经被系统记录,请勿使用爬虫,增大封号风险。 如果是误封 ,请联系站长,谢谢
package cn.how2j.diytomcat.catalina; import java.io.IOException; import java.util.List; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.Servlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import cn.hutool.core.util.ArrayUtil; public class ApplicationFilterChain implements FilterChain{ private Filter[] filters; private Servlet servlet; int pos; public ApplicationFilterChain(List<Filter> filterList,Servlet servlet){ this.filters = ArrayUtil.toArray(filterList,Filter.class); this.servlet = servlet; } @Override public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if(pos < filters.length) { Filter filter= filters[pos++]; filter.doFilter(request, response, this); } else { servlet.service(request, response); } } }
增值内容,请先登录
自己写一个Tomcat, 几乎使用到了除开框架外的所有Java 技术,如多线程,Socket, J2EE, 反射,Log4j, JSoup, JUnit, Html 等一整套技术栈, 从无到有,循序渐进涵盖全部74个知识点,549个开发步骤, 为竞争高薪资职位加上一个有吸引力的砝码.
增值内容,点击购买
使用爬虫已经被系统记录,请勿使用爬虫,增大封号风险。 如果是误封 ,请联系站长,谢谢
package cn.how2j.diytomcat.catalina; import cn.how2j.diytomcat.http.Request; import cn.how2j.diytomcat.http.Response; import cn.how2j.diytomcat.servlets.DefaultServlet; import cn.how2j.diytomcat.servlets.InvokerServlet; import cn.how2j.diytomcat.servlets.JspServlet; import cn.how2j.diytomcat.util.Constant; import cn.how2j.diytomcat.util.SessionManager; import cn.how2j.diytomcat.util.WebXMLUtil; import cn.hutool.core.util.*; import cn.hutool.log.LogFactory; import javax.servlet.Filter; import javax.servlet.Servlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpSession; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; import java.util.List; public class HttpProcessor { public void execute(Socket s, Request request, Response response){ try { String uri = request.getUri(); if(null==uri) return; prepareSession(request, response); Context context = request.getContext(); String servletClassName = context.getServletClassName(uri); HttpServlet workingServlet; if(null!=servletClassName) workingServlet = InvokerServlet.getInstance(); else if(uri.endsWith(".jsp")) workingServlet = JspServlet.getInstance(); else workingServlet = DefaultServlet.getInstance(); List<Filter> filters = request.getContext().getMatchedFilters(request.getRequestURI()); ApplicationFilterChain filterChain = new ApplicationFilterChain(filters, workingServlet); filterChain.doFilter(request, response); if(request.isForwarded()) return; if(Constant.CODE_200 == response.getStatus()){ handle200(s, request, response); return; } if(Constant.CODE_302 == response.getStatus()){ handle302(s, response); return; } if(Constant.CODE_404 == response.getStatus()){ handle404(s, uri); return; } } catch (Exception e) { LogFactory.get().error(e); handle500(s,e); } finally{ try { if(!s.isClosed()) s.close(); } catch (IOException e) { e.printStackTrace(); } } } private void handle200(Socket s, Request request, Response response) throws IOException { OutputStream os = s.getOutputStream(); String contentType = response.getContentType(); byte[] body = response.getBody(); String cookiesHeader = response.getCookiesHeader(); boolean gzip = isGzip(request, body, contentType); String headText; if (gzip) headText = Constant.response_head_200_gzip; else headText = Constant.response_head_200; headText = StrUtil.format(headText, contentType, cookiesHeader); if (gzip) body = ZipUtil.gzip(body); byte[] head = headText.getBytes(); byte[] responseBytes = new byte[head.length + body.length]; ArrayUtil.copy(head, 0, responseBytes, 0, head.length); ArrayUtil.copy(body, 0, responseBytes, head.length, body.length); os.write(responseBytes,0,responseBytes.length); os.flush(); os.close(); } private void handle404(Socket s, String uri) throws IOException { OutputStream os = s.getOutputStream(); String responseText = StrUtil.format(Constant.textFormat_404, uri, uri); responseText = Constant.response_head_404 + responseText; byte[] responseByte = responseText.getBytes("utf-8"); os.write(responseByte); } private void handle302(Socket s, Response response) throws IOException { OutputStream os = s.getOutputStream(); String redirectPath = response.getRedirectPath(); String head_text = Constant.response_head_302; String header = StrUtil.format(head_text, redirectPath); byte[] responseBytes = header.getBytes("utf-8"); os.write(responseBytes); } private void handle500(Socket s, Exception e) { try { OutputStream os = s.getOutputStream(); StackTraceElement stes[] = e.getStackTrace(); StringBuffer sb = new StringBuffer(); sb.append(e.toString()); sb.append("\r\n"); for (StackTraceElement ste : stes) { sb.append("\t"); sb.append(ste.toString()); sb.append("\r\n"); } String msg = e.getMessage(); if (null != msg && msg.length() > 20) msg = msg.substring(0, 19); String text = StrUtil.format(Constant.textFormat_500, msg, e.toString(), sb.toString()); text = Constant.response_head_500 + text; byte[] responseBytes = text.getBytes("utf-8"); os.write(responseBytes); } catch (IOException e1) { e1.printStackTrace(); } } public void prepareSession(Request request, Response response) { String jsessionid = request.getJSessionIdFromCookie(); HttpSession session = SessionManager.getSession(jsessionid, request, response); request.setSession(session); } private boolean isGzip(Request request, byte[] body, String mimeType) { String acceptEncodings= request.getHeader("Accept-Encoding"); if(!StrUtil.containsAny(acceptEncodings, "gzip")) return false; Connector connector = request.getConnector(); if (mimeType.contains(";")) mimeType = StrUtil.subBefore(mimeType, ";", false); if (!"on".equals(connector.getCompression())) return false; if (body.length < connector.getCompressionMinSize()) return false; String userAgents = connector.getNoCompressionUserAgents(); String[] eachUserAgents = userAgents.split(","); for (String eachUserAgent : eachUserAgents) { eachUserAgent = eachUserAgent.trim(); String userAgent = request.getHeader("User-Agent"); if (StrUtil.containsAny(userAgent, eachUserAgent)) return false; } String mimeTypes = connector.getCompressableMimeType(); String[] eachMimeTypes = mimeTypes.split(","); for (String eachMimeType : eachMimeTypes) { if (mimeType.equals(eachMimeType)) return true; } return false; } }
增值内容,请先登录
自己写一个Tomcat, 几乎使用到了除开框架外的所有Java 技术,如多线程,Socket, J2EE, 反射,Log4j, JSoup, JUnit, Html 等一整套技术栈, 从无到有,循序渐进涵盖全部74个知识点,549个开发步骤, 为竞争高薪资职位加上一个有吸引力的砝码.
增值内容,点击购买
使用爬虫已经被系统记录,请勿使用爬虫,增大封号风险。 如果是误封 ,请联系站长,谢谢
测试
步骤 5 :

比较可运行项目,快速定位问题

edit
增值内容,请先登录
自己写一个Tomcat, 几乎使用到了除开框架外的所有Java 技术,如多线程,Socket, J2EE, 反射,Log4j, JSoup, JUnit, Html 等一整套技术栈, 从无到有,循序渐进涵盖全部74个知识点,549个开发步骤, 为竞争高薪资职位加上一个有吸引力的砝码.
增值内容,点击购买
使用爬虫已经被系统记录,请勿使用爬虫,增大封号风险。 如果是误封 ,请联系站长,谢谢


HOW2J公众号,关注后实时获知最新的教程和优惠活动,谢谢。


问答区域    
2021-05-06 关于热加载的问题
打工人

在使用build的时候idea是先删除然后再创建.class文件,这样的话删除到创建这之间是有时间,删除触发的ContextFileChangeWatcher重新创建的context又监听到创建,又会触发一次ContextFileChangeWatcher,这样就又重新加载了一次context。逻辑应该是这样的,验证过多次了。所以每次我热加载都会看到加载了两次,本来想想算了,多加载一次应该不影响什么。到这里才发现问题很大。设置了filter之后,因为filter每次都要先初始化,所以如果删除触发的context重新加载,而context调用init时,idea还没生成.class文件,所以每次都会报错,像站长视频里也一样报错。目前我只想出一种方法,就是ContextFileChangeWatcher的dealWith里面加Thread.sleep()。让监听触发时等待一会再重新加载context。这方法不是百分百保险,不知道站长有什么更好的方法。




2 个答案

打工人
答案时间:2021-05-08
同步锁肯定不能解决,因为context是被移除再新建的,所以ContextFileChangeWatcher也会是新建的,同步锁不起作用啊

how2j
答案时间:2021-05-07
还有这个问题呢,加上同步锁能解决吗?



回答已经提交成功,正在审核。 请于 我的回答 处查看回答记录,谢谢
答案 或者 代码至少填写一项, 如果是自己有问题,请重新提问,否则站长有可能看不到








提问之前请登陆
提问已经提交成功,正在审核。 请于 我的提问 处查看提问记录,谢谢
关于 实践项目-DiyTomcat-Filter 责任链 的提问

尽量提供截图代码异常信息,有助于分析和解决问题。 也可进本站QQ群交流: 578362961
提问尽量提供完整的代码,环境描述,越是有利于问题的重现,您的问题越能更快得到解答。
对教程中代码有疑问,请提供是哪个步骤,哪一行有疑问,这样便于快速定位问题,提高问题得到解答的速度
在已经存在的几千个提问里,有相当大的比例,是因为使用了和站长不同版本的开发环境导致的,比如 jdk, eclpise, idea, mysql,tomcat 等等软件的版本不一致。
请使用和站长一样的版本,可以节约自己大量的学习时间。 站长把教学中用的软件版本整理了,都统一放在了这里, 方便大家下载: https://how2j.cn/k/helloworld/helloworld-version/1718.html

上传截图