• 欢迎光临flyzy小站!分享一些学习路上遇到的坑坑洼洼~

adad

SSM框架:详细整合教程

为什么要使用SSM(Spring+SpringMVC+MyBatis)框架呢?SSM框架是典型的MVC模式,将整个系统分为Controller,Service,DAO和界面层(即前台页面)。搭建了SSM后,会让项目的层次非常清晰,分工明确,让你迅速开启一个项目,并且后期维护起来也会方便很多。本文详细讲解了Spring的一些相关定义,也详细整合了3个框架,加入了Mybatis Generator自动生成bean和DAO,引入FreeMarker作为前台渲染引擎。文后附源码。

如果觉得配置文件繁多,可以直接跳到文后,在文后有一个整合好的模板源码。框架不难,重要的是在开发过程中感受这种开发思想~

 

SSM基本概念

SpringMVC是一个基于Spring的一个开源项目,一个MVC框架。MyBatis是一个优秀的基于Java的持久层框架,用来管理数据库。

主要讲一下SpringSpring是一个开源框架,是一个以简化Java开发的具有轻量级、非侵入式、一站式、模块化的开发应用框架。

为了降低Java开发的复杂性,Spring采取了以下4中关键策略:
1. 基于POJO的轻量级和最小侵入性编程
2. 通过控制反转(依赖注入)和面向接口实现松耦合
3. 基于切面和惯例进行声明式编程
4. 通过切面和模板减少样板式代码

很多框架通过强迫应用继承它们的类或者实现它们的接口从而导致应用与框架绑死。而基于Spring构建的应用中,它的类通常没有任何痕迹表明你使用了Spring,最坏的场景是,一个类或许会使用Spring注解,但它依然是POJO。Spring的非侵入编程模型意味着这个类在Spring应用和非Spring应用中都可以发挥同样的作用。

Spring中的IoC

为什么一些POJO就可以拥有这么大的魔力呢?答案就是Spring通过控制反转(Inversion of Control)来装配这些POJO。

一般翻译成控制反转,但其实它的意思是控制的反转,是面向对象编程中的一种设计原则,可以用来降低计算机代码之间的耦合度。通过控制反转,对象在被创建的时候,由Ioc容器将其所依赖的对象的引用传递给它。

一般来说,任何有实际意义的应用都会由两个或者更多的类组成,这些类相互之间互相协作来完成特定的业务逻辑。对象之间的耦合关系是无法避免的,也是必要的:

spring-introduction-no-IoC

可以从上图中形象的看出来各个类结合在一起,协同工作,完成某项任务。

但是这样的系统会导致高度耦合和难以测试,因此IoC理论应运而生,用来实现对象之间的解耦。

IoC理论简单来说就是把复杂系统分解成相互作用的对象,借助于第三方实现具有依赖关系的对象之间的解耦

spring-introduction-with-IoC

引入了IoC容器后,使得A、B、C、D这4个对象没有了耦合关系,齿轮之间的传动全部依靠“第三方”了,全部对象的控制权全部上缴给“第三方”IOC容器,所以,IOC容器成了整个系统的关键核心

通过前后的对比,我们不难看出:对象A获得依赖对象B的过程,由主动行为变为了被动行为,控制权颠倒过来了,这就是“控制反转”这个名称的由来

Spring中的DI

在Spring中控制反转还有另一个名字叫做依赖注入(Dependency Injection,DI),所谓依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。2004年,Martin Fowler探讨了同一个问题,既然IOC是控制反转,那么到底是“哪些方面的控制被反转了呢?”,经过详细地分析和论证后,他得出了答案:“获得依赖对象的过程被反转了”。

但其实依赖注入只是控制反转的一种实现方式,另一种主要实现方式是依赖查找(Dependency Lookup)。两者的区别在于,前者是被动的接收对象,在类A的实例创建过程中即创建了依赖的B对象,通过类型或名称来判断将不同的对象注入到不同的属性中,而后者是主动索取相应类型的对象,获得依赖对象的时间也可以在代码中自由控制。

依赖注入之所以更流行是因为它是一种更可取的方式:让容器全权负责依赖查询,受管组件只需要暴露JavaBean的setter方法或者带参数的构造子或者接口,使容器可以在初始化时组装对象的依赖关系。其与依赖查找方式相比,主要优势为:
1. 查找定位操作与应用代码完全无关
2. 不依赖于容器的API,可以很容易地在任何容器以外使用应用对象
3. 不需要特殊的接口,绝大多数对象可以做到完全不必依赖容器

依赖注入的实现方式
1. 基于接口。实现特定接口以供外部容器注入所依赖类型的对象。
2. 基于 set 方法。实现特定属性的public set方法,来让外部容器调用传入所依赖类型的对象。
3. 基于构造函数。实现特定参数的构造函数,在新建对象时传入所依赖类型的对象。
4. 基于注解。基于Java的注解功能,在私有变量前加“@Autowired”等注解,不需要显式的定义以上三种代码,便可以让外部容器传入对应的对象。该方案相当于定义了public的set方法,但是因为没有真正的set方法,从而不会为了实现依赖注入导致暴露了不该暴露的接口(因为set方法只想让容器访问来注入而并不希望其他依赖此类的对象访问)(Spring中采用的就是这种方式)。

Spring中的AOP

DI能够让互相协作的软件组件保持松散耦合,而面向切面编程(aspect-oriented programming,AOP)允许你把遍布应用各处的功能分离出来形成可重用的组件。

例如整个系统中,关注点(例如日志、安全事务管理等系统服务)的调用经常散布到各个模块中,而这些关注点并不是模块的核心业务,如果将这些关注点分散到多个组件中去,代码将变得非常复杂,不仅这些系统服务的代码将会出现在多个组件中,而且组件会因为这些与自身核心业务无关的代码变成混乱。

AOP能够使这些服务模块化,并以声明的方式将它们应用到它们需要影响的组件中去。所达到的效果就是这些组件会具有更高的内聚性并且会更加关注自身的业务,完全不需要了解涉及系统服务所带来的复杂性。借助AOP,可以使用各种功能层去包裹核心业务层,这些层以声明的方式灵活地应用到系统中,你的核心应用甚至根本不知道它们的存在。这是一个非常强大的理念,可以将安全、事务和日志关注点与核心业务逻辑相分离。总之,AOP能够确保POJO的简单性。

 

搭建SSM开发环境

使用的JetBrains开发的IntelliJ IDEA,下载地址:戳我下载。授权方法参考:IDEA License server搭建

搭建好后选择新建一个项目,File->New->Project

ssm-create

新建好package以及test目录,项目结构如图:

ssm-new-project-structure

配置pom.xml,下载需要的jar包

<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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>cn.flyzy2005</groupId>
  <artifactId>SSMTest</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>SSMTest Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.5.1</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
      <plugin>
        <!-- http://www.mybatis.org/generator/index.html -->
        <groupId>org.mybatis.generator</groupId>
        <artifactId>mybatis-generator-maven-plugin</artifactId>
        <version>1.3.5</version>
        <configuration>
          <!-- 	If true, then MBG will write progress messages to the build log.-->
          <verbose>true</verbose>
          <!--	If true, then existing Java files will be overwritten if an existing Java file if found with the same name as a generated file.
          If not specified, and a Java file already exists with the same name as a generated file,
          then MBG will write the newly generated Java file to the proper directory with a unique name (e.g. MyClass.java.1, MyClass.java.2, etc.).
          Important: MBG will always merge and overwrite XML files. -->
          <overwrite>true</overwrite>
          <configurationFile>src/main/resources/mybatis/generatorConfig.xml</configurationFile>
        </configuration>
        <dependencies>
          <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysqlversion}</version>
            <scope>runtime</scope>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
  </build>
  <properties>
    <springversion>4.3.9.RELEASE</springversion>
    <junitversion>4.12</junitversion>
    <logbackversion>1.1.1</logbackversion>
    <mysqlversion>5.1.37</mysqlversion>
    <mybatisversion>3.4.1</mybatisversion>
    <mybatisspingversion>1.3.0</mybatisspingversion>
    <c3p0version>0.9.1.2</c3p0version>
    <jstlversion>1.2</jstlversion>
    <commonsioversion>2.4</commonsioversion>
    <commonsfileuploadversion>1.3.1</commonsfileuploadversion>
    <commonscollectionsversion>3.2.2</commonscollectionsversion>
    <jsonlibversion>2.4</jsonlibversion>
    <fastjson>1.2.31</fastjson>
    <freemarkerversion>2.3.26-incubating</freemarkerversion>
  </properties>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>${junitversion}</version>
      <scope>test</scope>
    </dependency>

    <!-- 数据库 begin-->
    <!-- 这里用的是MySQL,如果要用Oracle,需要去
    http://www.oracle.com/technetwork/database/features/jdbc/jdbc-ucp-122-3110062.html
    官网下载相应的驱动jar包引到工程中去 -->
    <!-- 引用就只需要在WEB-INF下新建一个lib文件夹,拖进去后在Project Structure中选择Artifacts将jar包put到lib下-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>${mysqlversion}</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>${mybatisversion}</version>
    </dependency>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>${mybatisspingversion}</version>
    </dependency>
    <!-- 数据库 end-->

    <!-- 连接池 begin-->
    <dependency>
      <groupId>c3p0</groupId>
      <artifactId>c3p0</artifactId>
      <version>${c3p0version}</version>
    </dependency>
    <!-- 连接池 end-->

    <!-- 日志记录 begin-->
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>${logbackversion}</version>
    </dependency>
    <!-- 日志记录 end-->

    <!-- Spring start-->
    <!-- Spring核心 -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${springversion}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>${springversion}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${springversion}</version>
    </dependency>
    <!-- Spring dao-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>${springversion}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>${springversion}</version>
    </dependency>
    <!-- Spring web-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${springversion}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${springversion}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context-support</artifactId>
      <version>${springversion}</version>
    </dependency>
    <!-- Spring test-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${springversion}</version>
    </dependency>
    <!-- Spring end-->

    <!-- FreeMarker begin-->
    <dependency>
      <groupId>org.freemarker</groupId>
      <artifactId>freemarker</artifactId>
      <version>${freemarkerversion}</version>
    </dependency>
    <!-- FreeMarker end-->

    <!-- 其他常用jar包 begin-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>${jstlversion}</version>
      <type>jar</type>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
    </dependency>

    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>${commonsioversion}</version>
    </dependency>
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>${commonsfileuploadversion}</version>
    </dependency>
    <dependency>
      <groupId>commons-collections</groupId>
      <artifactId>commons-collections</artifactId>
      <version>${commonscollectionsversion}</version>
    </dependency>

    <dependency>
      <groupId>net.sf.json-lib</groupId>
      <artifactId>json-lib</artifactId>
      <version>${jsonlibversion}</version>
      <classifier>jdk15</classifier>
    </dependency>
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>${fastjson}</version>
    </dependency>
    <!-- 其他常用jar包 end-->

  </dependencies>
</project>

加入Spring的配置文件

包括spirng-dao.xml,spring-service.xml和spring-web.xml:
spring-dao.xml:

<?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:mybatis/jdbc.properties"/>

    <!-- 数据库连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!-- 配置连接池属性 -->
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>

        <!-- c3p0连接池的私有属性 -->
        <property name="maxPoolSize" value="30"/>
        <property name="minPoolSize" value="10"/>
        <!-- 关闭连接后不自动commit -->
        <property name="autoCommitOnClose" value="false"/>
        <!-- 获取连接超时时间 -->
        <property name="checkoutTimeout" value="10000"/>
        <!-- 当获取连接失败重试次数 -->
        <property name="acquireRetryAttempts" value="2"/>
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 配置SqlSessionFactory对象 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 注入数据库连接池 -->
        <property name="dataSource" ref="dataSource" />
        <!-- 配置MyBaties全局配置文件:mybatis-config.xml -->
        <property name="configLocation" value="classpath:mybatis/mybatis-config.xml" />
        <!-- 扫描entity包 使用别名 (多个则用,隔开)-->
        <property name="typeAliasesPackage" value="cn.flyzy2005.common.pojo" />
        <!-- 扫描sql配置文件:mapper需要的xml文件 -->
        <property name="mapperLocations" value="classpath:mybatis/mapper/*.xml" />
    </bean>

    <!-- 配置扫描Dao接口包,动态实现Dao接口,注入到spring容器中 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 注入sqlSessionFactory -->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
        <!-- 给出需要扫描Dao接口包 -->
        <property name="basePackage" value="cn.flyzy2005.common.dao" />
    </bean>
</beans>

spring-service.xml:

<?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"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!-- 扫描service包下所有使用注解的类型 -->
    <context:component-scan base-package="cn.flyzy2005.*.service"/>

    <!-- 配置事务管理器 -->
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!-- 注入数据库连接池 -->
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 配置基于注解的声明式事务 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

spring-web.xml:

<?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"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
	    http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd">
    <!-- 扫描web相关的bean -->
    <context:component-scan base-package="cn.flyzy2005.*.controller"/>

    <!-- 开启SpringMVC注解模式
        添加UTF8格式转码
    -->
    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>text/plain;charset=UTF-8</value>
                        <value>application/json;charset=UTF-8</value>
                        <value>text/html;charset=UTF-8</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

    <!-- 过滤静态资源 -->
    <!-- 也可以在web.xml里通过配置<servlet-mapping>来过滤静态文件 -->
    <!-- https://www.flyzy2005.cn/?p=notes/javaweb/ssm/springMVC/springmvc-static-resources.md -->
    <mvc:resources location="/static/" mapping="/static/**"/>

    <!-- 如果不想用FreeMarker,则注释此配置文件中关于FreeMarker的配置,并且取消这段关于ViewResolver的配置-->
    <!--&lt;!&ndash; 配置jsp 显示ViewResolver &ndash;&gt;-->
    <!--<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">-->
        <!--<property name="prefix" value="/views/"/>-->
        <!--<property name="suffix" value=".jsp"/>-->
    <!--</bean>-->

    <!-- 配置freeMarker视图解析器 -->
    <bean id="viewResolverFtl"
          class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
        <!-- 自定义FreeMarkerView 添加一些通用属性-->
        <property name="viewClass" value="cn.flyzy2005.core.freemarker.extend.FreeMarkerViewExtend" />
        <property name="contentType" value="text/html; charset=utf-8" />
        <property name="cache" value="true" />
        <property name="suffix" value=".ftl" />
    </bean>

    <!-- 配置freeMarker 拓展-->
    <bean id="freemarkerConfig"
          class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
        <property name="templateLoaderPath" value="/views/"/>
        <property name="defaultEncoding" value="utf-8"/>
        <property name="freemarkerSettings">
            <props><!-- 315360000 -->
                <prop key="template_update_delay">0</prop>
                <prop key="defaultEncoding">UTF-8</prop>
                <prop key="url_escaping_charset">UTF-8</prop>
                <prop key="locale">zh_CN</prop>
                <prop key="boolean_format">true,false</prop>
                <prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop>
                <prop key="date_format">yyyy-MM-dd</prop>
                <prop key="time_format">HH:mm:ss</prop>
                <prop key="number_format">#</prop>
            </props>
        </property>
    </bean>


    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="UTF-8" />
        <!-- 指定所上传文件的总大小,单位字节。注意maxUploadSize属性的限制不是针对单个文件,而是所有文件的容量之和 -->
        <property name="maxUploadSize" value="102400000" />
    </bean>
</beans>

配置MyBatis配置文件

包括mybaits-config.xml,generatorConfig.xml和jdbc.properties。

mybatis-config.xml,包括MyBatis的一些配置:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 官方参考 http://www.mybatis.org/mybatis-3/zh
        可以在这里设置别名,设置自己的handler等等-->
    <settings>
        <!-- 下划线与驼峰式命名规则的映射 -->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
</configuration>

generatorConfig.xml,包括对MyBatis Generator的一些配置:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
    <properties resource="mybatis/jdbc.properties"/>
    <!-- 数据库驱动-->
    <!--<classPathEntry  location="mysql-connector-java-5.1.37.jar"/>-->
    <context id="DB2Tables"  targetRuntime="MyBatis3">
        <commentGenerator>
            <property name="suppressDate" value="true"/>
            <!-- 是否去除自动生成的注释 true:是 : false:否 -->
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>
        <!--数据库链接URL,用户名、密码 -->
        <jdbcConnection driverClass="${jdbc.driver}" connectionURL="${jdbc.url}" userId="${jdbc.username}" password="${jdbc.password}">
        </jdbcConnection>
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>
        <!-- 生成模型的包名和位置-->
        <javaModelGenerator targetPackage="cn.flyzy2005.common.pojo"
                            targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>
        <!-- 生成映射文件的包名和位置-->
        <sqlMapGenerator targetPackage="mybatis.mapper"
                         targetProject="src/main/resources">
            <property name="enableSubPackages" value="true"/>
        </sqlMapGenerator>
        <!-- 生成DAO的包名和位置-->
        <javaClientGenerator type="XMLMAPPER" targetPackage="cn.flyzy2005.common.dao"
                             targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
        </javaClientGenerator>
        <!-- 要生成的表(多张就写多个table) tableName是数据库中的表名或视图名 domainObjectName是实体类名 enablexxxx可以指定不生成某些方法-->
        <table tableName="book" domainObjectName="Book" enableCountByExample="false"/>
    </context>
</generatorConfiguration>

jdbc.properties,包括数据库的一些信息:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=fly
jdbc.password=system

配置web.xml

<web-app>
  <welcome-file-list>
    <welcome-file>/</welcome-file>
  </welcome-file-list>

  <!-- 引入Spring配置 -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring/spring-*.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <servlet>
    <servlet-name>spring-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring/spring-*.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>spring-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <!-- 统一字符编码为UTF-8 -->
  <filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

配置logback

<?xml version="1.0"?>
<configuration>

    <!-- ch.qos.logback.core.ConsoleAppender 控制台输出 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>[%-5level] %d{HH:mm:ss.SSS} [%thread] %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- ch.qos.logback.core.rolling.RollingFileAppender 文件日志输出 -->
    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 绝对路径 按天存储log -->
            <fileNamePattern>E:/logs/ssm-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 最多存10天的 10天之前的删除 -->
            <maxHistory>10</maxHistory>
            <timeBasedFileNamingAndTriggeringPolicy
                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <!-- log多余5MB就会新建新的log-->
                <maxFileSize>5MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <encoder>
            <pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n</pattern>
        </encoder>
        <!-- 设置文件中记录的级别为error -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!-- 日志级别 -->
    <root>
        <level value="debug"/>
        <appender-ref ref="console"/>
        <appender-ref ref="file"/>
    </root>

</configuration>

至此,整个配置全部搞定,resources下面的结构如下图所示:
ssm-resources

 

利用MyBatis Generator自动生成表的pojo对象和DAO对象

点击右侧Maven Projects,选择Plugins下的mybatis-generator:generate,双击即可按照generatorConfig.xml中配置的那样生成对应的文件:
mybatis-generator

在控制台看到BUILD SUCCESS即可在指定文件夹下看到那些自动生成的文件~

 

编写SSM示例代码

后台目前分了3个package,common、core以及book。

其中,common中主要放一些全局会使用到的类,例如我会将工具类、默认的controller、pojo、dao放在里面;core中主要是放集成的工具,例如我这里放了对FreeMarkerView的扩展,可以将mybatis的相关类,或者以后集成更多的例如redis、shiro等相关的类放在其中;book是我写的一个测试模块,主要是写了查询书籍的测试代码,每一个模块主要写每一个模块对应的controller以及service,即控制层和业务层代码。

这样分类的好处是,在项目分完模块后,可以形成common+core+模块1+模块2+模块3,这样利于分工,整体结构也很清晰。
ssm-java

前台所有静态资源放在static目录下,包括css、js、img等,所有页面资源放在views目录下。

其中,配置了<mvc:resources location=”/static/” mapping=”/static/**”/>过滤了所有静态文件,并且指定了FreeMarker的templateLoaderPath为views目录<property name=”templateLoaderPath” value=”/views/”/>

ssm-views

至此,所有SSM配置已经结束~配置好服务器后运行即可看到自己的成果~

本文所用的例子源码:SSMTemplate

点赞