模拟Springboot一:(零xml配置搭建SSM项目)
在spring官网文档中无论是spring的基础文档,还是spring-mvc文档都推荐我们使用javaconfig的方式来搭建项目 间接说明
(优点:javaconfig配置>xml配置) 其实 springboot内部就是通过这种方式来做的而我们可以通过这种方式来搭一般的ssm项目,
甚至自己手动内嵌一个tomcat搭建一个简单的springboot项目都是可以的 。早在servlet3.0开始就能实现零xml配置搭建项目了
(现在最新servlet4.0,下面也会说到为什么从3.0开始可以实现springmvc的零xml配置),也就是说 通过xml搭建项目对于现在而言确实比较老了 。。。
1、首先创建一个maven的web项目
(1)、pom依赖 (后面需要其他的再加) :servlet依赖是用来使用servlet3.0 SCI新特性 实现 零xml 配置的

(2)目录结构

创建WebApplication 类 等于:web.xml
创建SpringApplicationContext类 等于spring-context.xml 容器
(3)首先通过javaconfig方式配置spring容器(为什么先配置spring容器就不再说了)

只需要 两个注解 就能实现对spring容器的配置 包括在启动容器时实例化对象、提供注解的支持、DI等
@Configuration:表示是一个spring容器
@ComponentScan("com.it") 包扫描 ,这里我只创建了com.it.controller(路径的颗粒度也是可以任意配置的,官网文档有介绍)
注意 : 从spring4.0 开始 ,就只需设置包扫描 就能完成对spring核心的配置了 ,无需额外打开 注解、驱动之类的设置
这些在spring-core源码包中都有体现 至此就完成了对spring最基本的配置。。。
(4)如果现在需要测试的话 , 以前是用ClassPathXmlApplicationContext 来加载xml 实例spring容器 ,
现在在main方法通过AnnotationConfigApplicationContext 加载spring容器就完事了 (这里就不测试了,整合完了SpringMVC再测试 )
(5) 配置spring-mvc ,官网文档中写的很清楚

web.xml主要配置包括两部分 配置spring容器和 配置speingMVC这里也是一样
A、在实例化 spring容器时使用AnnotationConfigWebApplicationContext的register方法来注册,而AnnotationConfigApplicationContext
通过构造器来实例化spring容器, 其实AnnotationConfigApplicationContext 的构造器(下图) 的源码中ClassPathXmlApplicationContext
都是 通过register()这种方法 ,然后refresh() 实例化spring的 容器的

B、spring整合springMVC无非就是 管理DispactcherServlet ,然后再将DispactcherServlet 对象放入tomcat容器,在tomcat启动的时候 加载
setOnStartUp(1) :在项目启动的时候就将dispatcherServlet加载
addMapping("/") : 拦截的请求
(6)、部署项目运行tomcat 就能从页面访问项目了(自己写controller测试) 访问:http://localhost:8080/项目名/RequestMapping

(7) 下面 来提一个问题 ,进而引入 servlet3.0 SCI 特性 ,我们知道 web.xml是项目的主入口 , 在tomcat启动的时候会加载项目的
WEB-INF/web.xml这个文件 。由于web.xml 配置配置了spring、springMVC 通过解析xml 和 反射技术就能打到对spring容器的创建
问题 :现在只是自己创建了一个WebApplication 类 ,tomcat 也不知道我们具体定义的是什么类放在什么地方,他是如何加载到的呢?
分析源码可以知晓 下图:

A、ServletContainerInitializer接口 简称 SCI :作用是 在tomcat启动容器阶段通过编程风格将filter、Servlet、Listener添加至servlet
容器从而取代web.xml中的filter、Servlet、Listener的配置
B、在tomcat启动阶段 ,来获取ServletContainerInitializer的实现类然后执行其onStartUp()方法 ,
spring的SpringServletContainerInitializer 实现了此方法并执行他的onStartUp()方法 ,那么问题来了
ServletAPI也不知道 spring 是用 哪个类 实现这个 ServletContainerInitializer接口的并且tomcat(tomcat中内嵌servlet)
和spring两个项目是分开的(没有耦合),那么tomcat是如何加载到 SpringServletContainerInitializer类的呢?
SCI规范在一个类型实现了ServletContainerInitializer时,项目启动的时候 会将实现这个接口的所有的实现类的 权限定的类名写到
META-INF/services/javax.servlet.ServletContainerInitializer文件中 ,maven依赖可以看到:
org.springframework.web.SpringServletContainerInitializer

SpringServletContainerInitializer类的实例是通过反射加载这个文件下的全限定类名得到的,根据上面的流程图
SpringServletContainerInitializer类中的onStartUp方法中 会执行WebApplicationInitializer接口的onStartUp()方法,
根据多态,我们自己项目中 定的WebApplication 类的 onStartUp方法执行 , 才能实现spring容器的初始化,然后管理springMVC
@HandlesTypes(WebApplicationInitializer.class)//注解用于注入实现WebApplicationInitializer接口的类的对象,
//放入onStartUp()方法的set集合中然后遍历执行实现类中的onStartUp()
public class SpringServletContainerInitializer implements ServletContainerInitializer {
@Override
public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
throws ServletException { List<WebApplicationInitializer> initializers = new LinkedList<>(); if (webAppInitializerClasses != null) {
for (Class<?> waiClass : webAppInitializerClasses) {
// Be defensive: Some servlet containers provide us with invalid classes,
// no matter what @HandlesTypes says...
if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
try {
initializers.add((WebApplicationInitializer)
ReflectionUtils.accessibleConstructor(waiClass).newInstance());
}
catch (Throwable ex) {
throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
}
}
}
} if (initializers.isEmpty()) {
servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
return;
} servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
AnnotationAwareOrderComparator.sort(initializers);
for (WebApplicationInitializer initializer : initializers) {
initializer.onStartup(servletContext);
}
}
@HandlesTypes(WebApplicationInitializer.clas)注解: 上面的一段代码是 SpringServletContainerInitializer类的源码 ,
当onStartUp执行的时候 会将实现WebApplicationInitializer接口的类也就是项目中中自定义的
WebApplication类 注入到当前类中并用Set参数接收
(8)整合Mybatis
(1)整合Mybatis相关依赖
<!-- 添加mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.</version>
</dependency> <!--mybatis-spring依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.</version>
</dependency>
<!-- mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0..RELEASE</version>
</dependency>
(2)、SpringApplicationContext.java 配置 (思路是跟.xml 一样的)
数据源的配置可以写到 .yml 文件中然后再写个工具类解析的,这里为了方便就直接硬编码带代码里了
。另外这里只配置了 最基本的需要,如果下配置如事物、aop、上传等 使用@Bean注入即可
@Configuration
@ComponentScan("com.it")
public class SpringApplicationContext { //创建数据源
@Bean("dataSource")
public DataSource getDataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/t1?useUnicode=true&characterEncoding=UTF-8");
dataSource.setUsername("root");
dataSource.setPassword("xxx"); dataSource.setInitialSize();
dataSource.setMaxIdle();
dataSource.setMaxWait();//最长等待时间
return dataSource;
} //管理mybatis的selSessionBean
@Bean("sqlSessionFactoryBean") //value :为创建的 bean取别名,默认是方法名首字母小写
//参数DataSource :sqlSessionFactoryBean 依赖参数DataSource
public SqlSessionFactoryBean getSqlSessionFactoryBean(DataSource dataSource) {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
//数据源
sqlSessionFactoryBean.setDataSource(dataSource);
//mapper配置 "classpath*:mapping/*Mapper.xml"
Resource[] resources = null;
try{
resources = new PathMatchingResourcePatternResolver().getResources("classpath*:com/it/dao/mapping/*Mapper.xml");
}catch (Exception e){
e.printStackTrace();
}
sqlSessionFactoryBean.setMapperLocations(resources);
return sqlSessionFactoryBean;
} //扫描mapper创建dao代理
@Bean
public MapperScannerConfigurer getMapperScannerConfigurer(){
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setBasePackage("com.it.dao");
mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactoryBean");
return mapperScannerConfigurer;
} }
下一篇:在此基础上 内置tomcat 来模仿 Springoot main方法启动web项目
模拟Springboot一:(零xml配置搭建SSM项目)的更多相关文章
- SpringBoot零XML配置的Spring Boot Application
Spring Boot 提供了一种统一的方式来管理应用的配置,允许开发人员使用属性properties文件.YAML 文件.环境变量和命令行参数来定义优先级不同的配置值.零XML配置的Spring B ...
- 这一次搞懂Spring Web零xml配置原理以及父子容器关系
前言 在使用Spring和SpringMVC的老版本进行开发时,我们需要配置很多的xml文件,非常的繁琐,总是让用户自行选择配置也是非常不好的.基于约定大于配置的规定,Spring提供了很多注解帮助我 ...
- Maven 搭建 SSM 项目 (oracle)
简单谈一下maven搭建 ssm 项目 (使用数据库oracle,比 mysql 难,所以这里谈一下) 在创建maven 的web项目时,常常会缺了main/java , main/test 两个文件 ...
- 自动搭建ssm项目
手把手教你搭建ssm项目 注意,必须修改:包名.数据库名称.账号.密码 注意:必须配置好第一次,“引入后”才能配置第二次 第一步:打开idea选择创建maven项目 import java.io.*; ...
- 搭建SSM项目时报错(org.springframework.jdbc.CannotGetJdbcConnectionException)
严重: Servlet.service() for servlet [SpringMVC] in context with path [/ssm] threw exception [Request p ...
- JBOSS安装与配置搭建本地项目环境(方便前端开发调式)
JBOSS安装与配置搭建本地项目环境 什么是JBOSS? JBOSS是EJB的服务器,就像Tomcat是JSP服务器一样,就是服务器的一种. 环境搭建如下: 一:首先安装JDK,配置环境变量(PAT ...
- 搭建ssm项目框架
[声明]转载注明链接,源码联系公众号:aandb7获取 [此处组织名groupId:com.dayuanit,可替换公司域名:项目名artifactid:...] 此处第二个配置文件选择maven安装 ...
- 用idea搭建SSM项目,原来这么简单
目录 前言 软件环境 创建项目 数据库文件 配置文件 pom.xml log4j.properties jdbc.properties applicationContext.xml spring-mv ...
- 记录搭建ssm项目
搞java也快3年了,搭建一个ssm居然有点吃力. 参考链接:https://blog.csdn.net/gebitan505/article/details/44455235/ 环境准备:jdk8. ...
随机推荐
- 实用的bash别名和函数
本文来自于:程序师 作为一个命令行探索者,你或许发现你自己一遍又一遍重复同样的命令.如果你总是用ssh进入到同一台电脑,如果你总是将一连串命令连接起来,如果你总是用同样的参数运行一个程序,你也许希望在 ...
- php数据库编程---mysql扩展库
1, Java有一种方式操作数据库, PHP有三种方式来操作mysql数据库.(1)mysql扩展库:(2)mysqli扩展库:(3)pdo: 2, mysql扩展库和mysql数据库区别 3, my ...
- 题目1016:火星A+B(字符串拆分)
问题来源 http://ac.jobdu.com/problem.php?pid=1016 问题描述 每次输入两个数,不同数位之间用逗号隔开,其中,第n位的进制就是第n个素数,即个位数是2进制的,十位 ...
- js中的substr和substring区别
js中的substr和substring区别 Substring: 该方法可以有一个参数也可以有两个参数. (1) 一个参数: 示例: var str=“Olive”: str.substring( ...
- CGLIB动态代理模式
概念: 第三方技术CGLIB动态代理和JDK代理不同的是,JDK代理需要提供接口,而CGLIB代理不需要: 它只需要一个非抽象类就能实现动态代理 例子: /** * 非抽象类 * @author Ad ...
- JAVA数据结构--AVL树的实现
AVL树的定义 在计算机科学中,AVL树是最先发明的自平衡二叉查找树.在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树.查找.插入和删除在平均和最坏情况下的时间复杂度都是.增 ...
- LOJ565. 「LibreOJ Round #10」mathematican 的二进制(NTT)
题目链接 https://loj.ac/problem/565 题解 首先,若进行所有操作之后成功执行的操作数为 \(m\),最终得到的数为 \(w\),那么发生改变的二进制位的数量之和(即代价之和) ...
- Codeforces - tag::flows 大合集 [完坑 x14]
589F 题意:给出n个时间区间,每个区间挑定长的非连续区间,求不同个区间不存在时间冲突的最大定长,输出乘上n 二分图模型+二分长度,左顶点集为区间编号,右顶点集为时间编号(1...10000),汇点 ...
- thinkphp5.1的安装
首先,下载composer.建议选择全屏安装.参考资料https://docs.phpcomposer.com/00-intro.html.安装到c盘.这个跟之前nodejs一样,都是装c盘.大概是全 ...
- Javascript 定时器的使用陷阱 (setInterval)
setTimeout(function(){ // 其他代码 setTimeout(arguments.callee, interval); }, interval); setInterval会产生回 ...