一  前 言

  本来是为了探究一些功能性问题,需要一套完整的项目架构,本以为SSM用过那么多了,轻松搭建不在话下,但是过程中还是遇到一些问题,踩到一些未曾料想的坑。博文以搭建极简架构为目的,附带一些关键阐述,既是备忘,也是分享。

二  Maven奠基

  IDEA中用 Maven 的方式搭建 web 项目的时候如果你选择了 web 项目骨架,那么最终生成的项目目录结构是很不标准的一个目录结构,而如果不选择 web 项目骨架,产生的项目目录标准但却少了 web 目录。当然,基于IDEA的强大,肯定不至于让你手动去整理包结构,请按以下简单步骤操作即可:

  没有选择骨架的Maven项目结构如下——

  然后项目右键 Add Frameworks Support 添加 web 支持——

三  Java 配置集成 Spring+Spring MVC

  通常的做法是需要在 web.xml 中配置 Spring 初始化上下文的监听器 ContextLoaderListener 和 Spring MVC的核心 DispatcherServlet,它们会加载各自路径中的xml配置文件来产生各自的上下文对象。不过博主并不想这么做,而是采用纯 Java 配置的方式,所以本项目示例中没有 web.xml的存在。通过Java配置的方式,我们需要两个配置类,一个配置类扩展 WebApplicationInitializer 接口的派生类 AbstractAnnotationConfigDispatcherServletInitializer ,其会同时创建 ContextLoaderListener 和 DispatcherServlet 的上下文,并根据需要配置 DispatcherServlet 的映射路径和相关配置类:

public class BluesInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
//给定的Java 配置类将定义 ContextLoaderListener 上下文中的 bean 实例 本示例中没有给出根配置类
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
} // 给定的Java 配置类将定义 DispatcherServlet 上下文的bean 实例
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
} // 配置一个或多个 映射路径
protected String[] getServletMappings() {
return new String[]{"/"};
}
}

  另一个就是MVC的基础配置类——

@Configuration
@ComponentScan(basePackages = {"net"})
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter { //配置视图解析器
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/pages/");
resolver.setSuffix(".jsp");
return resolver;
} /**
* 通过继承 WebMvcConfigurerAdapter 类的方式配置静态资源请求
* 将对静态资源的访问交由容器中默认的 Servlet 处理
*/
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
/** 相当于 xml 配置中的 <mvc:default-servlet-handler /> 配置 */
configurer.enable();
}
}

  完成两个配置类后其实Spring和Spring MVC就已经配置完了,你可以编写控制器做页面跳转测试,这里限于篇幅博主不再贴出。想要知道为什么能用以上的Java配置取代经常用的 web.xml中的配置 ,首先你必须得清楚 web.xml 中的 ContextLoaderListener 和 DispatcherServlet 的作用。关于这两者的深层理解,可参考一位博友的源码分析,这里博主还是按照己的理解来叙述:      

  ContextLoaderListener 是Spring的一个监听器,当其监听到容器启动会根据定义文件(可以理解为创建 bean 实例及维护bean依赖关系的图纸,默认是WEB-INF下的applicationContext.xml文件)创建Spring的上行下对象,也即容器对象,有了该容器对象程序运行时才能从容器中获取到bean; DispatcherServlet 本质就是一个Servlet ,所以,Servlet容器启动时自然会将其初始化(<load-on-startup>配置为正数),关键这家伙是 Spring 的,功能很强大,也能够根据自己的 xml定义文件(默认 WEB-INF下的【servlet-name】-servlet.xml)产生一个上下文对象,这个上下文容器对象负责管理维护Spring MVC生态体系中的 控制器啊,视图解析器,处理映射器等bean;这两个容器对象有关系吗,当然有关系,可以粗浅的理解为父子关系,前者是整个应用的根容器对象,是全局的,后者只是管理应用于Servlet相关组件。

    而为什么扩展了AbstractAnnotationConfigDispatcherServletInitializer 类就能完成上述相同的功能呢?因为在Servlet 3.0 规范中,为第三方组件提供了一个叫 ServletContainerInitializer 的接口用来做一些初始化相关的工作,第三方组件只要实现此接口就可以完成自己的一些初始化操作。在Spring中提供的实现类叫 SpringServletContainerInitializer ,追踪源码,你可以发现,真正的初始化配置其实是交给 WebApplicationInitializer 接口的子类来完成的,而上面代码中的 AbstractAnnotationConfigDispatcherServletInitializer 就是WebApplicationInitializer 接口的子类,所以,我们可以继承该类,根据业务需求重写相应的方法,来完成我们初始化Spring 和Spring MVC 上下文的相关配置。至此,我想你应该能看懂上面的配置是什么意思以及和web.xml中的配置的对应关系了。

四  整合Mybatis

  持久层的整合无需多说,在资源文件夹下新建 spring-mybatis.xml 和 db.properties文件,依次配置连接数据库的数据源(应该从 db.properties中获取数据库连接信息 )、生成SqlSession 的 SqlSessionFactory定义(其依赖于数据源和mapper.xml文件路径)以及映射器配置类 MapperScannerConfigurer。db.propertie和spring-mybatis.xml 配置文件如下:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/sql_eve?useUnicode=true&characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd "> <!--加载数据库配置文件 -->
<context:property-placeholder location="classpath:db.properties"/> <!--配置数据源 这里是配置的druid 连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!-- 配置初始化连接池大小设置 -->
<property name="initialSize" value="1" />
<!--最小空闲连接数量,设 0 没有限制 -->
<property name="minIdle" value="1" />
<!--最大活动连接数量,设 0 没有限制-->
<property name="maxActive" value="5" />
<!--从池中获取连接的最大等待时间,单位ms-->
<property name="maxWait" value="10000" />
</bean> <!--配置 SqlSessionFactory 全局单例 一个数据库应该只对应一个 SqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
</bean>
<!--配置 MapperScannerConfigurer 来配置映射器,通过扫描相应包下的接口生成动态代理对象交由Spring 管理-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="net.dao"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
</beans>

  现在这个配置文件Spring容器是不知道的,需要在上面的Java配置类WebConfig上标注 @ImportResource("classpath:spring-mybatis.xml") 进行引入。然后,来一个mapper.xml配置示例:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="net.dao.ProductDao">
<select id="queryProducts" resultType="net.entity.Product">
select * from products
</select>
</mapper>

五  避坑指南

  ① IDEA编译问题

  有时候我们可能会将mapper.xml文件写在dao下面的mapper包里,但是在IDEA的Maven项目中,编译器只会对java包下面.java文件进行编译处理,而忽略掉其中的资源文件,在运行时就会找不到相应的配置文件。所以资源文件最好直接放在resources目录中,如果确实需要放在java目录中,需在pom.xml中配置(配置链接)。

  ② 缺少 jdbc 支持异常

  ③ 返回参数类型错误

附 pom.xml 依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.buyi</groupId>
<artifactId>blues</artifactId>
<version>1.0-SNAPSHOT</version> <properties>
<spring.version>4.3.7.RELEASE</spring.version>
</properties> <dependencies>
<!--spring mvc 依赖引入,因为相互依赖的关系,实际上也就引入了 Spring 的几大核心包,不需要单独的引入 core beans之类的依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency> <!--spring-jdbc 支持-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency> <!--json支持 缺少会导致返回前端json格式数据的时候出错 java.lang.IllegalArgumentException: No converter found for return value of type: class ...-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.5.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.4</version>
</dependency> <!--Mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
<!--spring-mybatis整合包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency> <!--数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.25</version>
<scope>runtime</scope>
</dependency>
<!--数据库连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.12</version>
</dependency> <!--测试支持-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency> <!--websocket 支持-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
</project>
												

SSM项目整合纪实的更多相关文章

  1. SSM项目整合基本步骤

    SSM项目整合 1.基本概念 1.1.Spring Spring 是一个开源框架, Spring 是于 2003  年兴起的一个轻量级的 Java  开发框架,由 Rod Johnson  在其著作  ...

  2. SSM项目整合第一步 注册登陆实现

    SSM项目整合第一步  注册: 项目目录: 一.数据库建表: 源码: ; -- ---------------------------- -- Table structure for t_user - ...

  3. SSM项目整合Quartz

    一.背景 SSM项目中要用到定时器,初期使用Timer,后来用spring 的schedule,都比较简单,所以功能比较单一而且他们不能动态的配置时间.后来就研究quartz,准备整合到项目中.Qua ...

  4. SSM 项目整合

    SSM整合:spring + springmvc + mybatis 1.1 生成Maven项目:ar_ssm 1.2 添加jar包 <dependencies> <!-- 单元测试 ...

  5. Solr专题(三)SSM项目整合Solr

    一.环境配置 所需要的jar包: org.apache.solr.solr-solrj maven依赖: <!-- https://mvnrepository.com/artifact/org. ...

  6. ssm项目整合shiro

    pom.xml <properties> <shiro.version>1.2.2</shiro.version> </properties> < ...

  7. SpringMVC详解及SSM框架整合项目

    SpringMVC ssm : mybatis + Spring + SpringMVC MVC三层架构 JavaSE:认真学习,老师带,入门快 JavaWeb:认真学习,老师带,入门快 SSM框架: ...

  8. SSM框架整合项目 :租房管理系统

    使用ssm框架整合,oracle数据库 框架: Spring SpringMVC MyBatis 导包: 1, spring 2, MyBatis 3, mybatis-spring 4, fastj ...

  9. SSM 框架 ---项目整合

    一.SSM框架理解 Spring(业务层) Spring就像是整个项目中装配bean的大工厂,在配置文件中可以指定使用特定的参数去调用实体类的构造方法来实例化对象. Spring的核心思想是IoC(控 ...

随机推荐

  1. 推荐收藏系列:一文理解JVM虚拟机(内存、垃圾回收、性能优化)解决面试中遇到问题(图解版)

    欢迎一起学习 <提升能力,涨薪可待篇> <面试知识,工作可待篇 > <实战演练,拒绝996篇 > 欢迎关注我博客 也欢迎关注公 众 号[Ccww笔记],原创技术文章 ...

  2. leetcode105 从前序与中序遍历序列构造二叉树

    如何遍历一棵树 有两种通用的遍历树的策略: 宽度优先搜索(BFS) 我们按照高度顺序一层一层的访问整棵树,高层次的节点将会比低层次的节点先被访问到. 深度优先搜索(DFS) 在这个策略中,我们采用深度 ...

  3. java中sleep()和wait()区别

    1,sleep方法是Thread类的静态方法,wait()是Object超类的成员方法 2,sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时 ...

  4. python模块2

    python模块2 相关概念 模块名是标识符(需要按照标识符的写法编写) Pyc文件 在使用模块的项目中会生成一个_pycache_文件,里面存放着编译过的(模块的)字节码缓存文件(因为模块一般很少有 ...

  5. list列表操作

    li = [1,2,3,4,'4','456'] print(li.index('4')) # print(li.index('45')) l_a = ['1234567','7890'] l_b = ...

  6. 了解 MongoDB 看这一篇就够了【华为云技术分享】

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/devcloud/article/detai ...

  7. Python一秒搭建ftp服务器,帮助你在局域网共享文件【华为云技术分享】

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/devcloud/article/detai ...

  8. mysql数据库命令

    删除一个表: drop table if exists 表名; 在表中插入行: Insert into 表名 values(, , ,) 创建表: Create table 表名( Id int(10 ...

  9. 自学python中的心得

    以后的日子里我将与可爱的亲们一起度过我自学python的岁月,请博客园里的大佬们监督与见证.

  10. Spring Boot整合Servlet、Filter、Listener

    整合 Servlet   方式一:   编写 servlet package com.bjsxt.controller; import javax.servlet.ServletException; ...