在开始我们手写SpringBoot框架之前,我们还是先来好好的了解下,什么是SpringBoot。
相信有很多小伙伴,从SSM项目到SpringBoot(使用Mybatis)项目发现,编写代码的方式,好像没有什么改变,唯一改变好像就是没有了以前的那一堆Spring配置,当然也发现怎么连web.xml也不见了?
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/92c5aa6057686dcf102eaa060b5b4f6e.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/47222b2af4c30c5b19cbd82427927982.png)
总之就是在SpringBoot中,这些东西全不见。通过学习这篇文章,我们就知道为什么不见了。
1.什么是SpringBoot?
SpringBoot 是一个快速开整合第三方框架的框架,全部采用注解形式替代原来的XML形式,内置Tomcat容器。
换句话来说,SpringBoot并不是一个严格的开发框架,而是快速整合框架的框架。例如SpringBoot整合Spring、SpringMVC、MyBatis后,此项目的使用方式和使用maven的SSM框架几乎完全一致,最大的改变是,没了那一堆Spring的配置,以及web.xml配置。
如果我们现在来手写一套SpringBoot,我们需要做什么工作?
2.手写SpringBoot需要什么来支撑?
2.1.怎么整合其他框架?
这个比较简单,maven依赖就能实现了。所以创建一个maven项目就gameover了。
2.2.怎么构建一个Http服务器(tomcat)?
之前的文章已经着重讲述了构建一个tomcat服务,这里不在重复。
2.3.怎么使用注解代替XML?
之前的文章中,我们讲了SpringBoot怎么启动的,在这篇文章中,我们介绍了@SpringBootApplication的核心组建之一有@SpringBootConfiguration。
这个注解干嘛用的, 如果没有看过这篇文章,或者忘记了,我们先回顾下
SpringBoot中的@SpringBootConfiguration和Spring3.0版本中发布的Configuration作用完全一致。
@Configuration作用:配置Spring容器,使用 Java代码形式来配置Spring上下文中的bean。当我们把@Configuration标注在类上,相当于把该类作为spring的xml配置文件中的,作用为:配置spring容器(应用上下文)
例如如下配置中的bean可以用java类来配置。
现在,有了上述三个知识点的支撑,离我们手写SpringBoot框架就不远了。
3.手写我们的SpringBoot框架
3.1.创建maven项目,引入对应依赖
<!--Java语言操作tomcat -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>8.5.16</version>
</dependency>
<!-- tomcat对jsp支持 -->
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jasper</artifactId>
<version>8.5.16</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.4.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.4.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.1</version>
</dependency>
3.2.编写Http服务器(tomcat)
这里跟我们之前的文章:教你用Java的方式创建一个自己的Tomcat容器,功能几乎一致,唯一区别,就是这里我们不是配置servlet,而是将提供的web应用资源添加到此Web应用程序,这种方式比较灵活,毕竟应该是资源文件有什么,我们加什么,总不能一个一个资源用手动的方式去加载吧。
/**
* @Description:内置tomcat
* @author hutao
* @mail:hutao_2017@aliyun.com
* @date 2020年8月10日
*/
public class AppTomcat {
private static int PORT = 8081;
private static String WEB_APP_PATH = "src/main";
private static String WEB_INF_CLASSES_PATH = "target/classes";
private static String RESOURCES_PATH = "/WEB-INF/classes";
public static void main(String[] args) throws ServletException, LifecycleException {
start();
}
public static void start() throws ServletException, LifecycleException {
System.out.println("开始启动tomcat");
//创建tomcat服务
Tomcat tomcat = new Tomcat();
//指定端口
tomcat.setPort(PORT);
//添加webapp
Context webapp = tomcat.addWebapp("", new File(WEB_APP_PATH).getAbsolutePath());
//webapp禁止重载入
webapp.setReloadable(false);
//加载静态资源文件
File additionWebInfClasses = new File(WEB_INF_CLASSES_PATH);
//创建web应用资源
WebResourceRoot resources = new StandardRoot(webapp);
//tomcat将提供的web应用资源添加到此Web应用程序。
resources.addPreResources(new DirResourceSet(resources,RESOURCES_PATH, additionWebInfClasses.getAbsolutePath(), "/"));
//启动tomcat
tomcat.start();
System.out.println("启动tomcat完毕");
//开启异步接收http请求接入
tomcat.getServer().await();
}
}
3.3.用注解的方式配置Spring
@Configuration注解声明它是配置类,@ComponentScan指定扫包的范围。
/**
* @Description:Spring上下文注解配置
* @author hutao
* @mail:hutao_2017@aliyun.com
* @date 2020年8月11日
*/
@Configuration
@ComponentScan("com.hutao.springboot.write")
public class SpringApplicationConfig {
}
3.4.用注解的方式配置视图解析器
/**
* @Description:SpringMVC注解配置,视图解析器
* @author hutao
* @mail:hutao_2017@aliyun.com
* @date 2020年8月11日
*/
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.hutao.springboot.write.controller" })
public class SpringMvcConfig extends WebMvcConfigurationSupport {
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/page/");
viewResolver.setSuffix(".jsp");
viewResolver.setExposeContextBeansAsAttributes(true);
return viewResolver;
}
}
3.5.注册DispatcherServlet,以及Spring托管
通过实现org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer这个接口,来完成托管和注册
/**
* @Description:注册DispatcherServlet,以及Spring托管
* @author hutao
* @mail:hutao_2017@aliyun.com
* @date 2020年8月10日
*/
public class AnnotationConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
/**
* @Description:Spring上下文配置:从跟目录去获取上下文应用
* @author hutao
* @mail:hutao_2017@aliyun.com
* @date 2020年8月10日
*/
protected Class<?>[] getRootConfigClasses() {
return new Class[] { SpringApplicationConfig.class };
}
/**
* @Description:SpringMVC配置,本质就是Servlet应用程序上下文的配置
* @author hutao
* @mail:hutao_2017@aliyun.com
* @date 2020年8月10日
*/
protected Class<?>[] getServletConfigClasses() {
return new Class[] { SpringMvcConfig.class };
}
/**
* @Description:Servlet映射
* @author hutao
* @mail:hutao_2017@aliyun.com
* @date 2020年8月10日
*/
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
3.6.设置controller返回值
/**
* @Description:格式化返回JSON
* @author hutao
* @mail:hutao_2017@aliyun.com
* @date 2020年8月12日
*/
public class ResultData implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private int resultCode;
private String resultInfo;
public Object data;
//省略get set
}
@Configuration
public class ResultConfig {
@Bean
public ResultData getResultData() {
return new ResultData();
}
}
3.7.使用示例:restful接口
3.7.1.RestController
@RestController
@RequestMapping("/demo")
public class DemoController {
@Autowired
private HelloService helloService;
@Autowired
private ResultData result;
@RequestMapping("/hello/{userName}")
public ResultData hello(@PathVariable String userName) {
result.setResultCode(200);
result.setResultInfo("SUCC");
result.setData(helloService.hello(userName));
return result;
}
}
3.7.2.HelloService
public interface HelloService {
String hello(String userName);
}
@Service
public class HelloServiceImpl implements HelloService{
public String hello(String userName) {
return userName+"手写SpringBoot集成SpringMVC和Spring";
}
}
3.7.3.启动Http服务器(tomcat)
启动tomcat以后,我们看到我们的controller被扫描并且注册了
3.7.4.restful调用演示效果
接下来我们访问下这个接口
3.8.使用示例:返回到页面
创建返回页面的controller
3.8.1.PageController
@Controller
@RequestMapping("/page")
public class PageController {
@RequestMapping("/pageIndex")
public String pageIndex() {
return "pageIndex";
}
}
3.8.2.pageIndex
在WEB-INF目录下,创建一个pageIndex页面
<%@ page language="java" pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>主页面</title>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/bootstrap-table/1.17.1/bootstrap-table.min.js"></script>
</head>
<body>
<table class="table">
<thead>
<tr>
<th style="width:10%">序号</th>
<th style="width:90%">内容</th>
</tr>
</thead>
<tbody>
<tr class="active">
<td>1</td>
<td><a href="https://blog.csdn.net/m0_37892044/article/details/106643842">深入SpringIOC原理解析,带你实现一个SpringIOC框架</a></td>
</tr>
<tr class="success">
<td>2</td>
<td><a href="https://blog.csdn.net/m0_37892044/article/details/106976372">深入SpringMVC原理解析,带你实现一个SpringMVC框架</a></td>
</tr>
<tr class="warning">
<td>3</td>
<td><a href="https://blog.csdn.net/m0_37892044/article/details/107239656">深入数据库连接池原理解析,带你实现一个连接池框架</a></td>
</tr>
<tr class="danger">
<td>4</td>
<td><a href="https://blog.csdn.net/m0_37892044/article/details/107314371">深入MyBatis原理解析,带你实现一个MyBatis框架</a></td>
</tr>
<tr class="success">
<td>5</td>
<td><a href="https://blog.csdn.net/m0_37892044/article/details/103915284">使用SpringToolSuite快速构建一个SpringBoot项目</a></td>
</tr>
<tr class="active">
<td>6</td>
<td><a href="https://blog.csdn.net/m0_37892044/article/details/107576920">深入SpringBoot启动原理</a></td>
</tr>
<tr class="active">
<td>7</td>
<td><a href="https://blog.csdn.net/m0_37892044/article/details/107887911">SpringBoot使用Atomikos实现分布式事务管理</a></td>
</tr>
<tr class="success">
<td>8</td>
<td><a href="">深入SpringBoot核心原理,带你实现一个SpringBoot框架</a></td>
</tr>
</tbody>
</table>
</body>
</html>
3.8.3.演示效果
通过访问我们的pageController,实现访问我们的页面