MVC
快来分享你的内容吧~
内嵌服务器
<html> <head></head> <body> <div class="content ql-editor"> <p><br></p> <h2 class="ql-align-justify"><span style="background-color: rgb(255, 255, 255); color: var(--primary-color);">创建项目</span></h2> <h2><br></h2> <p>打开idae</p> <p></p> <p><br></p> <p><span style="background-color: rgb(255, 255, 255); color: rgb(64, 70, 79);">创建项目</span></p> <p></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>等待项目构建成功后,我们来到<a href="http://Pom.xml" target="_blank">Pom.xml</a> 添加下方的Jar包</li> </ol> <p></p> <p></p> <h3 class="ql-align-justify"><span style="background-color: rgb(255, 255, 255); color: var(--primary-color);">配置类</span></h3> <div class="ql-code-block-container"> <div class="ql-code-block"><span class="ql-token hljs-comment">/**</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * @program: CXM-MVC-Framework</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * @description: Web默认配置信息类</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * @author: 程序梦</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * @create: 2024-05-13 15:28</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> **/</span> </div> <div class="ql-code-block"> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">public</span> <span class="ql-token hljs-keyword">class</span> <span class="ql-token hljs-title">ServerConfig</span> { </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">/**</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * 这里的所有的字段命名必须与yml中子节点名字相同</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> */</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">private</span> <span class="ql-token hljs-type">Integer</span> <span class="ql-token hljs-variable">port</span> <span class="ql-token hljs-operator">=</span> <span class="ql-token hljs-number">8080</span>; <span class="ql-token hljs-comment">// 端口号</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">private</span> <span class="ql-token hljs-type">String</span> <span class="ql-token hljs-variable">contextPath</span> <span class="ql-token hljs-operator">=</span> <span class="ql-token hljs-string">"/"</span> <span class="ql-token hljs-comment">//web服务器默认访问路径</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">private</span> <span class="ql-token hljs-type">String</span> <span class="ql-token hljs-variable">webRoot</span> <span class="ql-token hljs-operator">="src/main/webapp"</span> <span class="ql-token hljs-comment">// web项目静态资源目录 </span> </div> <div class="ql-code-block"> </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">/**</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> Get Set 方法</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> */</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">public</span> Integer <span class="ql-token hljs-title">getPort()</span> { </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">return</span> port; </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"><br> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">public</span> <span class="ql-token hljs-keyword">void</span> <span class="ql-token hljs-title">setPort(Integer port)</span> { </div> <div class="ql-code-block"> <span class="ql-token hljs-built_in">this</span>.port = port; </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"><br> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">public</span> String <span class="ql-token hljs-title">getContextPath()</span> { </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">return</span> contextPath; </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"><br> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">public</span> <span class="ql-token hljs-keyword">void</span> <span class="ql-token hljs-title">setContextPath(String contextPath)</span> { </div> <div class="ql-code-block"> <span class="ql-token hljs-built_in">this</span>.contextPath = contextPath; </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"><br> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">public</span> String <span class="ql-token hljs-title">getWebRoot()</span> { </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">return</span> webRoot; </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"><br> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">public</span> <span class="ql-token hljs-keyword">void</span> <span class="ql-token hljs-title">setWebRoot(String webRoot)</span> { </div> <div class="ql-code-block"> <span class="ql-token hljs-built_in">this</span>.webRoot = webRoot; </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"><br> </div> </div> <ol> <li data-list="bullet"><span class="ql-ui"></span>上面的是 Web 服务器默认配置信息类</li> <li data-list="bullet"><span class="ql-ui"></span>本类只对Web服务器配置一些信息类</li> </ol> <p>----手动分割线</p> <h5 class="ql-align-justify"><span style="background-color: rgb(255, 255, 255); color: var(--primary-color);">Configure</span></h5> <div class="ql-code-block-container"> <div class="ql-code-block"><span class="ql-token hljs-comment">/**</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * @program: CXM-MVC-Framework</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * @description: 配置对象(也是所有配置的根)</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * @author: 程序梦</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * @create: 2024-05-13 15:28</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * 作用是将yml解析的数据封装到这个对象中</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> **/</span> </div> <div class="ql-code-block"><span class="ql-token hljs-keyword">public</span> <span class="ql-token hljs-keyword">class</span> <span class="ql-token hljs-title">Configure</span> { </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 这里字段命名不需要与yml文件中的字段一致</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">private</span> <span class="ql-token hljs-type">ServerConfig</span> <span class="ql-token hljs-variable">server</span> <span class="ql-token hljs-operator">=</span> <span class="ql-token hljs-keyword">new</span> <span class="ql-token hljs-title">ServerConfig</span>(); </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 扫描控制的Class集合,使用 set 集合 不允许重复</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">private</span> Set<Class<?>> classes; </div> <div class="ql-code-block"> </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 设置路径的Set方法</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">public</span> <span class="ql-token hljs-keyword">void</span> <span class="ql-token hljs-title">setClasses(Set<Class<?>> classes)</span> { </div> <div class="ql-code-block"> <span class="ql-token hljs-built_in">this</span>.classes = classes; </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">/**</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * 执行扫描,根据启动类所在包以及所有的子包开始扫描</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> *</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * @param mianClass</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> */</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">public</span> <span class="ql-token hljs-keyword">void</span> <span class="ql-token hljs-title">scan(Class<?> mianClass)</span> { </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">/**</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * 使用 hutool工具包中的ClassUtil工具类中的scanPackage方法去扫描启动类所在包以及所有的子包</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> */</span> </div> <div class="ql-code-block"> classes = ClassUtil.scanPackage(mianClass.getPackageName()); </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 开始过滤,只要Controller注解的类</span> </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// get set 方法</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">public</span> ServerConfig <span class="ql-token hljs-title">getServer()</span> { </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">return</span> server; </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"><br> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">public</span> <span class="ql-token hljs-keyword">void</span> <span class="ql-token hljs-title">setServer(ServerConfig server)</span> { </div> <div class="ql-code-block"> <span class="ql-token hljs-built_in">this</span>.server = server; </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">public</span> Set<Class<?>> getClasses() { </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">return</span> classes; </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"><br> </div> <div class="ql-code-block"> } </div> </div> <p><br></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>上面是配置对象是所有配置的根,可以不止配置这些类,还可以配置其他信息</li> <li data-list="bullet"><span class="ql-ui"></span>作用是将yml解析的数据封装到这个对象中。</li> </ol> <p><br></p> <h4 class="ql-align-justify"><span style="background-color: rgb(255, 255, 255); color: var(--primary-color);">内嵌容器</span></h4> <div class="ql-code-block-container"> <div class="ql-code-block"><span class="ql-token hljs-comment">/**</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * @description: 抽象的容器接口</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * @author: 程序梦</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * @create: 2024-05-14 08:38</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> **/</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">public</span> <span class="ql-token hljs-keyword">interface</span> <span class="ql-token hljs-title">WebServer</span> { </div> <div class="ql-code-block"><br> </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">/**</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * 抽象的启动方法,不同的容器有不同启动方法</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * @param mainClass</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * @throws Exception</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> */</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">void</span> <span class="ql-token hljs-title">runServer(Class<?> mainClass)throws</span> Exception </div> <div class="ql-code-block"> } </div> </div> <ol> <li data-list="bullet"><span class="ql-ui"></span>一、之前第一版的时候,我们是直接在 TomCatServer 当中写启动方法,为什么要抽象一个抽象接口呢,因为 Web 服务器不止一个如:<strong style="color: var(--primary-color);">Jetty WildFly</strong> 等服务器,他们的启动方法式并不相同</li> <li data-list="bullet"><span class="ql-ui"></span>二、定义接口目的: 定义一个统一的接口,可以为很多 Web服务器实现统一的标准的规范</li> <li data-list="bullet"><span class="ql-ui"></span>三、五大设计原则</li> <li data-list="bullet" class="ql-indent-1"><span class="ql-ui"></span>单一职责:接口只有一个 runServer 方法,表明了这个方法值做启动Web服务器</li> <li data-list="bullet" class="ql-indent-1"><span class="ql-ui"></span>依赖倒置: runServer 方法只接收一个Class<?>参数,而不是具体服务器实现类,使用实现此接口的类没有直接和WebServer直接产生依赖,通过抽象来进行依赖。</li> <li data-list="bullet" class="ql-indent-1"><span class="ql-ui"></span>开辟原则: 接口对扩展是开方法的,因为可以有很多种 Web 服务器可以实现扩展此接口,不用去修改WebServer</li> <li data-list="bullet" class="ql-indent-1"><span class="ql-ui"></span>接口隔离: 此接口只有一个 RunServer 提供启动服务器的抽象方法</li> <li data-list="bullet" class="ql-indent-1"><span class="ql-ui"></span>里氏替换: 实现 WebServer 的接口必须遵守约定,在使用 WebServer 的方法都可以直接替换。</li> <li data-list="bullet"><span class="ql-ui"></span>四、使用策略模式</li> <li data-list="bullet" class="ql-indent-1"><span class="ql-ui"></span>因为不同 Web 服务器启动方式不一样,但是此接口提供了启动方法,tomcat 实现了WebServer 去覆写 它的策略启动类就好了,jetty 去复写runServer就好了</li> </ol> <p>-------- 分割线</p> <p><br></p> <h5 class="ql-align-justify"><span style="background-color: rgb(255, 255, 255); color: var(--primary-color);">AbstractWebServer</span></h5> <div class="ql-code-block-container"> <div class="ql-code-block"><span class="ql-token hljs-comment">/**</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * @program: CXM-MVC-Framework</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * @description: 模版方法, 抽象类, 实现WebServer接口, 实现runServer方法, 解析yml文件, 启动容器, 不同容器有不同的实现</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * @author: 程序梦</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * @create: 2024-05-14 08:41</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * 模版方法</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> **/</span> </div> <div class="ql-code-block"><span class="ql-token hljs-keyword">public</span> <span class="ql-token hljs-keyword">abstract</span> <span class="ql-token hljs-keyword">class</span> <span class="ql-token hljs-title">AbstractWebServer</span> <span class="ql-token hljs-keyword">implements</span> <span class="ql-token hljs-title">WebServer</span> { </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">/**</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * 模版方法</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * 做扫描用户给的包路径</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> *</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * @throws Exception</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> */</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">public</span> <span class="ql-token hljs-keyword">void</span> <span class="ql-token hljs-title">RunServer(Class<?> mainClass)</span> { </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 1.解析 yml 文件返回Configure对象</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-type">Configure</span> <span class="ql-token hljs-variable">configure</span> <span class="ql-token hljs-operator">=</span> initConfigure(mainClass); </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 启动容器</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">try</span> { </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 符合依赖倒置、里氏替换,</span> </div> <div class="ql-code-block"> strataServer(configure) </div> <div class="ql-code-block"> } <span class="ql-token hljs-keyword">catch</span> (Exception e) { </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 降级重抛异常</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">throw</span> <span class="ql-token hljs-keyword">new</span> <span class="ql-token hljs-title">ExecutionException</span>(<span class="ql-token hljs-string">"启动容器失败"</span>,e); </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">/**</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> *</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * 解析 yml 文件</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * 为什么要解析 yml 文件 因为用户在yml文件填写了Web服务器基本配置信息,我们要通过yml 解析工具去获取基本配置,因为Web服务器的配置基本一致</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> */</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">private</span> Configure <span class="ql-token hljs-title">initConfigure(Class<?> mianClass)</span> { </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 获取用户填写yml文件的绝对路径</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 我们去读用户的项目的 编译后的clases下的yml文件</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-type">String</span> <span class="ql-token hljs-variable">configFilePath</span> <span class="ql-token hljs-operator">=</span> ClassUtil.getClassPath() +<span class="ql-token hljs-string">"application.yml"</span>; </div> <div class="ql-code-block"> System.out.println(configFilePath + <span class="ql-token hljs-string">"yml绝对路径"</span>); </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 创建配置对象为局部变量</span> </div> <div class="ql-code-block"> Configure configure </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 判断 yml 文件是否存在,如果不存在直接创默认的配置</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">if</span>(FileUtil.exist(configFilePath)) { </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 解析 yml 并赋值</span> </div> <div class="ql-code-block"> configure = YamlUtil.loadByPath(<span class="ql-token hljs-string">"application.yml"</span>,Configure.class); </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 判断 configure 上面内容是否为空,如果为空,则使用默认的配置</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">if</span>(configure == <span class="ql-token hljs-literal">null</span>) { </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 创建默认的配置 </span> </div> <div class="ql-code-block"> configure = <span class="ql-token hljs-keyword">new</span> <span class="ql-token hljs-title">Configure</span>(); </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> }<span class="ql-token hljs-keyword">else</span> { </div> <div class="ql-code-block"> Configure =<span class="ql-token hljs-keyword">new</span> <span class="ql-token hljs-title">Configure</span>(); </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 执行扫描(读取完 yml文件后,开始扫描使用该框架的项目所有包)</span> </div> <div class="ql-code-block"> configure.scan(mainCalss); </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 返回配置</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">return</span> configure; </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"><br> </div> <div class="ql-code-block"><span class="ql-token hljs-comment">/**</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * 抽象的启动方法,让子类去实现此方法(不同Web服务器启动方式不同)</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * Params: configure -- 配置类</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> */</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">public</span> <span class="ql-token hljs-keyword">abstract</span> <span class="ql-token hljs-keyword">void</span> <span class="ql-token hljs-title">strataServer(Configure configure)</span>; </div> <div class="ql-code-block"><br> </div> </div> <ol> <li data-list="bullet"><span class="ql-ui"></span><strong style="color: var(--primary-color);">代码解释</strong> :</li> <li data-list="bullet" class="ql-indent-1"><span class="ql-ui"></span><strong style="color: var(--primary-color);">runServer</strong> 方法解析: 此方法调用 initConfigure方法对 yml 文件进行解析, 并调用strataServer 方法去启动容器。</li> <li data-list="bullet" class="ql-indent-1"><span class="ql-ui"></span><strong style="color: var(--primary-color);">initConfigure</strong> 方法解析:此方法接收启动类的 class, 获取到用户项目的 <strong style="color: var(--primary-color);">yml</strong> 的绝对路径,创建Configure 配置类的成员变量,然后判断用户的 yml 是否存在</li> <li data-list="bullet" class="ql-indent-2"><span class="ql-ui"></span>存在:使用 yml解析工具库对yml进行解析,并将yml填写的配置信息赋值给我们的 Configure 对象,然后判断 Configure 是否为空</li> <li data-list="bullet" class="ql-indent-3"><span class="ql-ui"></span>为空: 创建 Configure 对象</li> <li data-list="bullet" class="ql-indent-3"><span class="ql-ui"></span>不为空: 执行对用户所有项目目录进行扫包存入我们的 Configure 对象里面的Set集合,</li> <li data-list="bullet" class="ql-indent-3"><span class="ql-ui"></span>返回配置给到 runServer 方法</li> <li data-list="bullet" class="ql-indent-2"><span class="ql-ui"></span>不存在:则创建默认的 Configure 配置对象赋值给我们之前创建的成员变量 Configure</li> <li data-list="bullet" class="ql-indent-1"><span class="ql-ui"></span><strong style="color: var(--primary-color);">总结</strong>: 本类实现了 WebServer 并覆写 RunServer 这个方法用做Web服务器一些基本步骤RunServer 这个方法是启动Web服务器的方法,但是不同 Web 服务器有着不同的启动方式,所以这里将 RunServer 当作模版方法,将Web服务器相同的工作进行封装,如解析 yml 文件读取配置、和全局扫包 strataServer 方法让子类实现此方法做自己启动方式。</li> <li data-list="bullet"><span class="ql-ui"></span><strong style="color: var(--primary-color);">设计模式</strong>: 使用 模版方法模式:在 AbstractWebServer 抽象类中,定义了模版方法,将一些通用的步骤封装起来,留下一些不同步骤给子类去实现,具体 Web 服务器 通过 strataServer 这个抽象方来实现具体 Web 服务器去实现,可以不违反开辟原则下去进行扩展。</li> <li data-list="bullet"><span class="ql-ui"></span><strong style="color: var(--primary-color);">总结</strong>: 这个抽象类实现了一个通用的 Web 服务器框架,并将一些通用的功能使用模板方法设计模式进行了封装,以便子类可以根据具体的需要进行扩展和实现。未来可以根据需求扩展新的 Web 服务器实现,并且通过模板方法模式,保证了代码的可扩展性和可维护性。</li> </ol> <p>------------</p> <p><br></p> <h5 class="ql-align-justify"><span style="background-color: rgb(255, 255, 255); color: var(--primary-color);">TomCatServer</span></h5> <div class="ql-code-block-container"> <div class="ql-code-block"><span class="ql-token hljs-comment">/**</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * @program: CXM-MVC-Framework</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * @description: TomCat容器</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * @author: 程序梦</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> * @create: 2024-05-13 11:32</span> </div> <div class="ql-code-block"><span class="ql-token hljs-comment"> **/</span> </div> <div class="ql-code-block"><br> </div> <div class="ql-code-block"><span class="ql-token hljs-keyword">public</span> <span class="ql-token hljs-keyword">class</span> <span class="ql-token hljs-title">TomCatServer</span> <span class="ql-token hljs-keyword">extends</span> <span class="ql-token hljs-title">AbstractWebServer</span> { </div> <div class="ql-code-block"> <span class="ql-token hljs-meta">@Override</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">public</span> <span class="ql-token hljs-keyword">void</span> <span class="ql-token hljs-title">strataServer(Configure configure)</span> { </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 实例化 TomCat</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-type">Tomcat</span> <span class="ql-token hljs-variable">tomcat</span> <span class="ql-token hljs-operator">=</span> <span class="ql-token hljs-keyword">new</span> <span class="ql-token hljs-title">Tomcat</span>(); </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 设置端口</span> </div> <div class="ql-code-block"> tomcat.setPort(configure.getServer().getPort()); </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 将静态资源目录构成绝对路径</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-type">String</span> <span class="ql-token hljs-variable">WebRoot</span> <span class="ql-token hljs-operator">=</span> Configure.getServer().getWebRoot(); </div> <div class="ql-code-block"> System.out.println(WebRoot + <span class="ql-token hljs-string">"静态资源目录绝对路径"</span>); </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 获取项目的绝对路径</span> </div> <div class="ql-code-block"> WebRoot = FileUtil.getWebRoot().getAbsoultePath()+ File.separator+WebRoot; </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 设置 contextPath和web资源目录,返回一个Context上下文对像 添加一个Web应用程序</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-type">Context</span> <span class="ql-token hljs-variable">context</span> <span class="ql-token hljs-operator">=</span> tomcat.addWebapp(configure.getServer().getContextPath(),WebRoot); </div> <div class="ql-code-block"> System.out.println(<span class="ql-token hljs-string">"上下文对象"</span> + context); </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 设置应用程序的编译路径,这样容器启动时会从classPath下查找带有Servlet注解的组件</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 列如:@WebServlet @WebFilter @WebListener</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 我们可以把WebResourceRoot 当作一个容器,这里存放成所有资源</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-type">WebResoutecRoot</span> <span class="ql-token hljs-variable">resourceRoot</span> <span class="ql-token hljs-operator">=</span> <span class="ql-token hljs-keyword">new</span> <span class="ql-token hljs-title">StandardRoot</span>(context); </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 构建DirResourceSet 对象 这个对象要负责将资源分类:列如查找@WebServlet @WebFilter @WebListener,处理完后,赋值给 resourceRoot</span> </div> <div class="ql-code-block"> <span class="ql-token hljs-type">DirResourceSet</span> <span class="ql-token hljs-variable">resourceSet</span> <span class="ql-token hljs-operator">=</span> <span class="ql-token hljs-keyword">new</span> <span class="ql-token hljs-title">DirResourceSet</span>(resourceRoot,<span class="ql-token hljs-string">"/WEB-INF/classes"</span>,ClassUtil.getClassPath(),<span class="ql-token hljs-string">"</span> </div> <div class="ql-code-block"><span class="ql-token hljs-string">/"</span>); </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 将资源放回容器中</span> </div> <div class="ql-code-block"> resourceRoot.addPostResources(resourceSet); </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 将 ResourceRoot 设置到Tomcat上下文对象的context 中,Tomcat 会根据这些资源查照找 @WebServlet @WebFilter @WebListener 的组件,也会去加载一些其他操作</span> </div> <div class="ql-code-block"> context.setResources(resourceRoot); </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 获取 Servlet 上下文路径,并配置对象保存到上下文对象中便于在DispatcherServlet中获取</span> </div> <div class="ql-code-block"> context.getServletContext().setAttribute(<span class="ql-token hljs-string">"configure"</span>, configure); </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 获取 tomcat 连接</span> </div> <div class="ql-code-block"> tomcat.getConnector(); </div> <div class="ql-code-block"> <span class="ql-token hljs-keyword">try</span> { </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 启动 Tomcat</span> </div> <div class="ql-code-block"> tomcat.start(); </div> <div class="ql-code-block"> <span class="ql-token hljs-comment">// 阻塞 Tomcat,保存运行状态</span> </div> <div class="ql-code-block"> tomcat.getServer().await(); </div> <div class="ql-code-block"> } <span class="ql-token hljs-keyword">catch</span> (Exception e) { </div> <div class="ql-code-block"> e.printStackTrace(); </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> </div> <ol> <li data-list="bullet"><span class="ql-ui"></span>代码解释:上面代码只做四件事情</li> <li data-list="bullet" class="ql-indent-1"><span class="ql-ui"></span>1、设置 contextPath和Web资源路径</li> <li data-list="bullet" class="ql-indent-1"><span class="ql-ui"></span>2、设置应用程序的编译路径,这样容器启动时会从classPath下查找带有Servlet注解的组件</li> <li data-list="bullet" class="ql-indent-1"><span class="ql-ui"></span>3、将配置类设置到我们的作用域给 SpringMvc 的 重要组件DispatcherServlet使用</li> <li data-list="bullet" class="ql-indent-1"><span class="ql-ui"></span>4、启动Tomcat服务器</li> <li data-list="bullet"><span class="ql-ui"></span>问题</li> <li data-list="bullet" class="ql-indent-1"><span class="ql-ui"></span>为什么不直接实现WebServer去实现AbstractWebServer服务器呢?</li> <li data-list="bullet" class="ql-indent-2"><span class="ql-ui"></span>1、不同的容器有不同的方法</li> <li data-list="bullet" class="ql-indent-2"><span class="ql-ui"></span>2、其他服务器可以直接实现此接口来进行扩展,也满足于策略模式</li> <li data-list="bullet" class="ql-indent-2"><span class="ql-ui"></span>3、因为不同服务器的前期准备工作不同,所以AbstractWebServer有一个模版方法去将相同封装在一起,不同交给子类实现</li> <li data-list="bullet" class="ql-indent-2"><span class="ql-ui"></span>4、因为不符合五依赖倒置原则,因抽象不应该依赖细节,细节应该依赖抽象</li> <li data-list="bullet" class="ql-indent-1"><span class="ql-ui"></span>设计模式</li> <li data-list="bullet" class="ql-indent-2"><span class="ql-ui"></span>模版方法:对不同服务器要做相同的事情进行封装,将不同事情使用一个抽象方法,然后交给子类进行实现</li> <li data-list="bullet" class="ql-indent-2"><span class="ql-ui"></span>策略模式:因为不同服务器有不同启动方式,所以交给其他服务器去实现去扩展</li> </ol> <p>我们内嵌容器已经搞定,接下来就是实现SpringMvc啦!</p> <p><br></p> <p>等待更新大家如果觉得样式觉得变扭我把pdf发出来</p> </div> </body> </html>
