实现SpringMVC框架
一、依赖管理工具
优点:
- 自动化管理依赖
- 解决依赖冲突
- 能监管项目
三种
-
Ant
-
Maven
-
Gradle
- 发扬了Maven的约定大于配置的优点
- 使用DSL语言提倡函数支持
- 方便性上:Json,免安装
Spring模块划分
core(核心层)
Beans
Core
Context
SpEL
应用层
Data:JDBC、ORM。
Web:Mvc,Servlet
我们需要实现Core模块,包括core、beans、context包
实现web功能,集成web和webmvc
添加,starter,实现spring1-boot的启动方式
使用
建立四个两个模块,删除主项目的src目录,分别是framework和test,建立两个模块之间的练习,之后直接从test模块中测试。创建五个包,分别是Beans 、Core、Context、starter、web。
在测试模板中放入一个核心启动类这里叫Application.java。里面编写主方法。
模块间的联系:
package com.sang.sdg;
import com.sang.sdg.starter.MiniApplication;
public class Application {
public static void main(String[] args) {
System.out.println("Hello World!");
MiniApplication.run(Application.class,args);
}
}
配置:text模块中的test.gradle文件
plugins {
id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
compile(project(':framework'))
}
jar{
manifest {
attributes "Main-Class" : "com.sang.sdg.Application"
}
from{
configurations.compile.collect{
it.isDirectory() ? it : zipTree(it)
}
}
}
这样就建立了两个联系,可以在text的jar文件中对jar包进行测试
web模型
web服务器
-
监听一个tcp端口
-
转发请求,回收响应
-
本身没有业务逻辑,连接操作系统和应用程序代码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CliY03SN-1627543787658)(image-20210722092546090.png)]
servlet
-
一种规范:约束了java服务器与业务类的通信方式
-
一个接口:javax.servlet.Servlet
-
一种java类:实现了Servlet接口的应用程序类
tomcat
- 原生java语言开发,运行在JVM上
- 多种并发模型,高性能
- 支持嵌入应用程序
扩展:
Tomcat容器等级:Tomcat容器分为四个等级
1. Container 容器,集装箱
2.Engine 引擎容器
3.Host 主机()
4.Servlet容器(tomcat最低级别的容器)里面包含了一个或多个Context
—— Context (上下文,背景,环境) 一个context对应一个web项目
—— Wrapper 容器里的封装部分
Engine:Servlet 的顶层容器,包含一 个或多个 Host 子容器;
Host:虚拟主机,负责 web 应用的部 署和 Context 的创建;
Context:Web 应用上下文,包含多个 Wrapper,负责 web 配置的解析、管 理所有的 Web 资源;
Wrapper:最底层的容器,是对 Servlet 的封装,负责 Servlet 实例的创 建、执行和销毁。
Container是容器的父接口,该容器的设计用的是典型的责任链的设计模式,它由四个自容器组件构成,分别是Engine、Host、Context、Wrapper。这四个组件是负责关系,存在包含关系。通常一个Servlet class对应一个Wrapper,如果有多个Servlet定义多个Wrapper,如果有多个Wrapper就要定义一个更高的Container,如Context。
Tomcat中的文件作用
bin: 启动和关闭tomcat的bat文件
conf: 配置文件
-->server.xml : 该文件用于配置和 server 相关的信息, 比如 tomcat启动端口后,配置Host, 配置Context 即web应用
-->web.xml : 该文件配置与 web应用(web应用就相当于是一个 web站点)
-->tomcat-users.xml: 该文件用户配置tomcat 的用户密码 和 权限
lib 目录: 该目录放置运行tomcat 运行需要的jar包
logs 目录:存放日志, 当我们需要去查看日志的时候,很有用!,当我们启动tomcat错误时候,可以查询信息.
webapps 目录: 该目录下,放置我们的web应用(web 站点), 比如:
建立 web1 目录 下面放置我们的html 文件 jsp 文件..图片... 则 web1就被当做一个web应用管理起来(特别说明tomcat 6.0 以后支持 tomcat 5 版本 还有别的设置)
work: 工作目录: 该目录用于存放jsp被访问后 生成的对应的 server文件 和.class文件
执行流程
1.请求被发送到本机端口8080,被在那里侦听的CoyoteHTTP/1.1 Connector获得
2.Connector把请求交给他所在的Service的Engine来处理,并等待Engine的回应
3.Engine获取请求localhost:8080/test/index.jsp,匹配它所有虚拟主机Host
4.Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该host处理,因为该Host被定为Engine默认主机)
5.localhost Host获得请求/test/index.jsp,匹配它所拥有的Context
6.Host匹配到路径为/test的Context(如果匹配不到就把请求交给路径为“”的Context去处理)
7.path="test"的Context获取请求/index.jsp,在他的mapping table中寻找对应的servlet
8.Context匹配到URL PATTERN为*。jsp的servlet,对应与JspServlet类
9.构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet或doPost方法。
10.Context把执行完了之后的HttpServletResponse对象返回给Host
11.Host把HttpServletResponse对象返回给Engine
12.Engine把HttpServletResponse对象返回给Connector
13.Connector把HttpServletResponse对象返回给客户browser
内部组成
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Nsj8lpHi-1627543787661)(1484390-20190305164203128-1958072095.png)]
Tomcat 组成如下图:
主要有 Container 和 Connector 以及相关组件构成。
Server:指的就是整个 Tomcat 服 务器,包含多组服务,负责管理和 启动各个 Service,同时监听 8005 端口发过来的 shutdown 命令,用 于关闭整个容器 ;
Service:Tomcat 封装的、对外提 供完整的、基于组件的 web 服务, 包含 Connectors、Container 两个 核心组件,以及多个功能组件,各 个 Service 之间是独立的,但是共享 同一 JVM 的资源 ;
Connector:Tomcat 与外部世界的连接器,监听固定端口接收外部请求,传递给 Container,并 将 Container 处理的结果返回给外部;
Container:Catalina,Servlet 容器,内部有多层容器组成,用于管理 Servlet 生命周期,调用 servlet 相关方法。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Doi2gTH0-1627543787664)(1484390-20190305164122581-2069214907.jpg)]
演示:
第一步:
首先选择tomcat服务器,在maven仓库里下载tomcat核心包
第二步:
编写tomcat服务类,tomcatServer.java
package com.sang.sdg.web.server;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.startup.Tomcat;
public class TomcatServer {
private Tomcat tomcat;
private String[] args;
TomcatServer(String[] args){
this.args = args;
}
public void startServer() throws LifecycleException {
tomcat = new Tomcat();//新建tomcat
tomcat.setPort(6699);//设置端口
tomcat.start();//开启tomcat服务
//防止服务器中途退出,添加常驻线程
Thread awaitThread = new Thread("tomcat_await_Thread"){
@Override
public void run() {
TomcatServer.this.tomcat.getServer().await();//使线程一直等待
}
};
awaitThread.setDaemon(false);//设置线程为非守护线程
awaitThread.start();
}
}
第三步
启动tomcatServer,在主类中
package com.sang.sdg.starter;
import com.sang.sdg.web.server.TomcatServer;
import org.apache.catalina.LifecycleException;
public class MiniApplication {
public static void run(Class<?> cla,String[] args){
System.out.println("Hello Mini-Application");
//开启tomcat服务
TomcatServer tomcatServer = new TomcatServer(args);
try {
tomcatServer.startServer();
} catch (LifecycleException e) {
e.printStackTrace();
}
}
}
重新打包然后运行测试。
第四步
现在服务器中什么都没有,在浏览器中访问本地tomcat服务器什么都没有,找不到要显示的页面。
所以现在,新建一个servlet类,使tomcat能够显示,因为tomcat本身就是一个servlet类
新建一个TestTomcat.java,实现Servlet接口,在service简单写点代码
package com.sang.sdg.web.servlet;
import javax.servlet.*;
import java.io.IOException;
public class TestServlet implements Servlet {
@Override
public void init(ServletConfig config) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
res.getWriter().println("Hello SpringMVC!");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
在tomcat服务类中配置Context容器
Context context = new StandardContext();//new一个标准Context容器
context.setPath("");//设置访问路径
context.addLifecycleListener(new Tomcat.FixContextListener());//添加context生命周期,这里使用默认
Tomcat.addServlet(context,"testServlet",new TestServlet()).setAsyncSupported(true);//添加servlet
context.addServletMappingDecoded("/t","testServlet");//设置路径映射
tomcat.getHost().addChild(context);//获得tomcat的虚拟主机,将context容器添加进去
重新打包,测试,注意这里的端口号为6699,项目名为空
Servlet维护
请求分发
最初的使用:
- 由服务器进行配置,将写好的Servlet配置在其他容器中,然后配置在服务器中统一进行查找
- 使用web.xml 中心化配置,将写好的Servlet配置在xml里通过添加映射来进行管理,发送来的路径在xml里逐一进行查找有部分问题。每种业务添加一个Servlet,对应一个URI .
问题:
- 配置集中,大而杂,不易管理
- 多次实现Servlet接口,造成代码重复
SpringMVC
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-swBcZCAK-1627543787667)(image-20210725173046581.png)]
优势:
- 使用注解,实现简单,按需实现
- 配置分散,不杂乱
- 容器内实现,更简单
所以我们采用SpringMVC的框架模式
Spring框架模式仿写实现
第一步
将以上写好的TestServlet改名为DispatcherServlet或者从新定义一个dispatcherServlet,之后再修改TomcatServer中的Servlet的联系方式
Context context = new StandardContext();
context.setPath("");
context.addLifecycleListener(new Tomcat.FixContextListener());
Tomcat.addServlet