尚筹网项目环境搭建(ssm整合)

从单一架构阶段到分布式架构阶段的过渡。后台管理员系统使用单一架构ssm开发。前台会员系统使用分布式架构SpringBoot+SpringCloud开发。

前置要求:Spring、SpringMVC、MyBatis、Maven

第三方接口:短信、蚂蚁金服、OSS对象存储服务

中间件:Redis、SpringSession

目的:从学习具体技术的语法转变为思考如何实现业务功能需求。


1.项目架构

2.环境搭建总体目标

3.创建工程,搭建环境

3.1项目架构图

3.2工程创建计划

#at代表尚硅谷,crowd众筹的众,funding众筹的筹,连起来就是尚硅谷的众筹的项目:尚筹网
#admin代表后台管理员系统,parent代表父工程
atcrowdfunding01-admin-parent
    groupId:com.atguigu.crowd
    artifactId:atcrowdfunding01-admin-parent
    packaging:pom
atcrowdfunding02-admin-webui
    groupId:com.atguigu.crowd
    artifactId:atcrowdfunding02-admin-webui
    packaging:war
atcrowdfunding03-admin-component
    groupId:com.atguigu.crowd
    artifactId:atcrowdfunding03-admin-component
    packaging:jar
atcrowdfunding04-admin-entity
    groupId:com.atguigu.crowd
    artifactId:atcrowdfunding04-admin-entity
    packaging:jar
atcrowdfunding05-common-util
    groupId:com.atguigu.crowd
    artifactId:atcrowdfunding05-common-util
    packaging:jar
atcrowdfunding06-common-reverse
    groupId:com.atguigu.crowd
    artifactId:atcrowdfunding06-common-reverse
    packaging:jar

 3.3工程结构图

 3.4建立工程之间的依赖关系

#工程:atcrowdfunding02-admin-webui中的依赖  
   <dependencies>
        <dependency>
            <groupId>com.atguigu.crowd</groupId>
            <artifactId>atcrowdfunding03-admin-component</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>   
#工程:atcrowdfunding03-admin-component中的依赖 
    <dependencies>
        <dependency>
            <groupId>com.atguigu.crowd</groupId>
            <artifactId>atcrowdfunding04-admin-entity</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.atguigu.crowd</groupId>
            <artifactId>atcrowdfunding05-common-util</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

4.创建数据库和数据库表 

4.1物理建模

①.数据库建表的原则:(三范式)

  • 第一范式:数据库表中的每一列都不可再分,也就是原子性
  • 第二范式:在满足第一范式基础上要求每个字段都和主键完整相关,而不是仅和主键部分相关(主要针对联合主键而言)
  • 第三范式:表中的非主键字段和主键字段直接相关,不允许间接相关

4.2创建数据库project_crowd以及管理员数据库表 t_admin

CREATE DATABASE `project_crowd` CHARACTER SET utf8;
use project_crowd;
drop table if exists t_admin;
create table t_admin
(
    id int not null auto_increment, # 主键
    login_acct varchar(255) not null, # 登录账号
    user_pswd char(32) not null, # 登录密码
    user_name varchar(255) not null, # 昵称
    email varchar(255) not null, # 邮件地址
    create_time char(19), # 创建时间
    primary key (id)
);

5.基于Maven的Mybatis逆向工程

①在reverse中配置pom

    <dependencies>
        <!--Mybatis依赖的核心包-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.9</version>
        </dependency>
        <!-- MySQL 驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
    </dependencies>

    <!-- 控制 Maven 在构建过程中相关配置 -->
    <build>
        <!-- 构建过程中用到的插件 -->
        <plugins>
            <!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 -->
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.0</version>
                <!-- 插件的依赖 -->
                <dependencies>
                    <!-- 逆向工程的核心依赖 -->
                    <dependency>
                        <groupId>org.mybatis.generator</groupId>
                        <artifactId>mybatis-generator-core</artifactId>
                        <version>1.3.2</version>
                    </dependency>
                    <!-- 数据库连接池 -->
                    <dependency>
                        <groupId>com.mchange</groupId>
                        <artifactId>c3p0</artifactId>
                        <version>0.9.2</version>
                    </dependency>
                    <!-- MySQL 驱动 -->
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>8.0.28</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>

 ②在Resource下创建generatorConfig.xml文件

<?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>
    <!--
        mybatis-generator:generate
        targetRuntime: 用于选择执行生成的逆向工程的版本
        MyBatis3Simple: 生成基本的CRUD(清新简洁版)
        MyBatis3: 生成带条件的CRUD(奢华尊享版)
    -->
    <context id="atguiguTables" targetRuntime="MyBatis3">
        <commentGenerator>
            <!-- 是否去除自动生成的注释 true:是;false:否 -->
            <property name="suppressAllComments" value="true" />
        </commentGenerator>
        <!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
        <jdbcConnection
                driverClass="com.mysql.cj.jdbc.Driver"
                connectionURL="jdbc:mysql://localhost:3306/project_crowd?serverTimezone=UTC"
                userId="root"
                password="abc123">
        </jdbcConnection>
        <!--
            默认false,把JDBC DECIMAL和NUMERIC 类型解析为 Integer,
            为true时把JDBC DECIMAL和NUMERIC 类型解析为 java.math.BigDecimal
        -->
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>
        <!-- targetProject:生成 Entity 类的路径 -->
        <javaModelGenerator targetProject=".\src\main\java" targetPackage="com.atguigu.crowd.entity">
            <!-- enableSubPackages:是否让 schema 作为包的后缀 -->
            <property name="enableSubPackages" value="false" />
            <!-- 从数据库返回的值被清理前后的空格 -->
            <property name="trimStrings" value="true" />
        </javaModelGenerator>
        <!-- SQL映射文件的生成策略,targetProject:XxxMapper.xml 映射文件生成的路径 -->
        <sqlMapGenerator targetProject=".\src\main\java"
                         targetPackage="com.atguigu.crowd.mapper">
            <!-- enableSubPackages:是否让 schema 作为包的后缀 -->
            <property name="enableSubPackages" value="false" />
        </sqlMapGenerator>
        <!-- Mapper接口的生成策略,targetPackage:Mapper 接口生成的位置 -->
        <javaClientGenerator type="XMLMAPPER"
                             targetProject=".\src\main\java"
                             targetPackage="com.atguigu.crowd.mapper">
            <!-- enableSubPackages:是否让 schema 作为包的后缀 -->
            <property name="enableSubPackages" value="false" />
        </javaClientGenerator>
        <!-- 逆向分析的表 -->
        <!-- tableName设置为*号,可以对应所有表,此时不写domainObjectName -->
        <!-- domainObjectName属性指定生成出来的实体类的类名 -->
        <table tableName="t_admin" domainObjectName="Admin" />
    </context>
</generatorConfiguration>

③.执行逆向生成操作的 Maven 命令:mybatis-generator:generate 

④.逆向工程生成的资源各归各位

 6.父工程依赖管理

    <dependencyManagement>
        <dependencies>
            <!-- Spring 依赖 -->
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-orm -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-orm</artifactId>
                <version>5.3.17</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>5.3.17</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
                <version>5.3.17</version>
            </dependency>
            <!--Spring-->

            <!--Spring的AOP方面相关的依赖-->
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
            <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.6</version>
        </dependency>
            <!-- https://mvnrepository.com/artifact/cglib/cglib -->
            <dependency>
                <groupId>cglib</groupId>
                <artifactId>cglib</artifactId>
                <version>3.3.0</version>
            </dependency>

            <!-- 数据库依赖 -->
            <!-- MySQL 驱动 -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.28</version>
            </dependency>
            <!-- 数据源 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.2.8</version>
            </dependency>
            <!-- MyBatis -->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.5.9</version>
            </dependency>
            <!-- MyBatis 与 Spring 整合 -->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis-spring</artifactId>
                <version>1.3.2</version>
            </dependency>
            <!-- MyBatis 分页插件 -->
            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper</artifactId>
                <version>5.2.0</version>
            </dependency>
            <!-- 日志 -->
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>1.7.7</version>
            </dependency>
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-classic</artifactId>
                <version>1.2.3</version>
            </dependency>
            <!-- 其他日志框架的中间转换包 -->
            <!--使用jcl-over-slf4j,把spring自带的日志包Commons-logging转换成slf4j-->
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>jcl-over-slf4j</artifactId>
                <version>1.7.25</version>
            </dependency>
            <!--使用jcl-over-slf4j,把jdk自带的日志包java.util.logging转换成slf4j-->
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>jul-to-slf4j</artifactId>
                <version>1.7.25</version>
            </dependency>
            <!-- Spring 进行 JSON 数据转换依赖 -->
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-core</artifactId>
                <version>2.9.8</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>2.9.8</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
            <dependency>
                <groupId>com.google.code.gson</groupId>
                <artifactId>gson</artifactId>
                <version>2.8.5</version>
            </dependency>
            <!-- junit 测试 -->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>3.1.0</version>
                <scope>provided</scope>
            </dependency>
            <!-- Spring5和Thymeleaf整合包 -->
            <dependency>
                <groupId>org.thymeleaf</groupId>
                <artifactId>thymeleaf-spring5</artifactId>
                <version>3.0.12.RELEASE</version>
            </dependency>
            <!-- SpringSecurity 对 Web 应用进行权限管理 -->
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-web</artifactId>
                <version>5.4.5</version>
            </dependency>
            <!-- SpringSecurity 配置 -->
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-config</artifactId>
                <version>5.4.5</version>
            </dependency>
            <!-- SpringSecurity 标签库 -->
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-taglibs</artifactId>
                <version>5.4.5</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
#SpringMVC 需要 jackson 的支持,来处理 JSON 数据。但是 SpringMVC 并没有依赖 jackson。所以需要我们自己保证 jar 包之间的兼容性。

7.Spring整合Mybatis

7.1思路

7.2操作清单

  • 在子工程中加入搭建环境所需要的具体的依赖
  • 准备jdbc.properties
  • 创建Spring配置文件专门配置Spring和Mybatis整合相关
  • 在Spring的配置文件中加载jdbc.properties属性文件
  • 配置数据源
  • 测试从数据源中获取数据库连接
  • 配置SqlSessionFactoryBean(动态的得到Mapper接口对应的类)
  •         装配数据源
  •         指定XxxMapper.xml配置文件的位置
  •         指定Mybatis全局配置文件的位置(可选)
  • 配置MapperScannerConfigurer 
  • 测试是否可以装配XxxMapper接口并通过这个接口操作数据库

 7.3操作步骤(配置文件统一放在webui下的Resource下)

①在子工程中加入搭建环境所需的具体的依赖,子工程选择compoment工程

    <dependencies>
        <!-- Spring 依赖 -->
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-orm -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
        </dependency>
        <!--Spring-->

        <!--Spring的AOP方面相关的依赖-->
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/cglib/cglib -->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
        </dependency>

        <!-- 数据库依赖 -->
        <!-- MySQL 驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- 数据源 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
        <!-- MyBatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
        </dependency>
        <!-- MyBatis 与 Spring 整合 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
        </dependency>
        <!-- MyBatis 分页插件 -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
        </dependency>
        <!-- 日志 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
        </dependency>
        <!-- 其他日志框架的中间转换包 -->
        <!--使用jcl-over-slf4j,把spring自带的日志包Commons-logging转换成slf4j-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
        </dependency>
        <!--使用jcl-over-slf4j,把jdk自带的日志包java.util.logging转换成slf4j-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jul-to-slf4j</artifactId>
        </dependency>
        <!-- Spring 进行 JSON 数据转换依赖 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
        </dependency>
    </dependencies>

②.准备jdbc.properties,在webui工程的Resource下创建

jdbc.user=root
jdbc.password=abc123
jdbc.url=jdbc:mysql://localhost:3306/project_crowd?serverTimezone=UTC&?useUnicode=true&characterEncoding=UTF-8
jdbc.driver=com.mysql.cj.jdbc.Driver

③.创建Spring配置文件spring-persist-mybatis.xml(专门配置Spring和Mybatis整合相关)

  • 在Spring的配置文件中加载jdbc.properties属性文件
  • 配置数据源
  • 配置SqlSessionFactoryBean(可动态的得到Mapper接口对应的类)
    • 装配数据源
    • 指定XxxMapper.xml配置文件的位置
    • 指定Mybatis全局配置文件的位置(可选)
  • 配置MapperScannerConfigurer 
<?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">
    <!--引入外部属性文件,加载 jdbc.properties-->
    <context:property-placeholder location ="classpath:jdbc.properties"/>
    <!--配置数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.user}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <!--配置SqlSessionFactoryBean整合Mybatis-->
    <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--指定mybatis全局配置文件的位置-->
        <property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>
        <!--指定XxxMapper.xml配置文件的位置-->
        <property name="mapperLocations" value="classpath:mybatis/mapper/*Mapper.xml"/>
        <!--装配数据源-->
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--配置MapperScannerConfigurer来扫描Mapper接口所在的包-->
    <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.atguigu.crowd.mapper"/>
    </bean>
</beans>

④.测试从数据源中获取数据库连接,测试是否可以装配XxxMapper接口并通过该接口操作数据库

创建 Spring 的 Junit 测试类
// 指定 Spring 给 Junit 提供的运行器类
@RunWith(SpringJUnit4ClassRunner.class)
// 加载 Spring 配置文件的注解
@ContextConfiguration(locations = {"classpath:spring-persist-mybatis.xml"})
public class CrowdSpringTest {
    @Autowired
    private DataSource dataSource;
    @Autowired
    private AdminMapper adminMapper;
    @Test
    public void testInsertAdmin(){
        Admin admin = new Admin(null, "tom", "123123", "汤姆", "tom@qq.com", null);
        int insert = adminMapper.insert(admin);
        System.out.println("受影响的行数:"+insert);
    }
    @Test
    public void testDataSource() throws SQLException {
        // 1.通过数据源对象获取数据源连接
        Connection connection = dataSource.getConnection();
        // 2.打印数据库连接
        System.out.println(connection);
    }
}
#注:为了能够在webui工程中执行Junit,需要把spring-test和junit依赖转移到webui这个工程,score是test

8.日志系统

如果在实际开发中,所有想查看数值的地方都使用sysout方式打印,会给项目上线运行带来问题!
sysout本质上是一个IO操作,通常IO的操作是比较消耗性能的,如果项目中sysout很多,那么对性能的影响就比较大了。即使上线前专门花时间删除代码中的sysout,也可能有遗漏,而且很繁琐,而如果使用日志系统,那么通过日志级别就可以批量的控制信息的打印。

①引入slf4j+logback的日志依赖:

<!-- 日志 -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
</dependency>
<!-- 其他日志框架的中间转换包 -->
<!--使用jcl-over-slf4j,把spring自带的日志包Commons-logging转换成slf4j-->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jcl-over-slf4j</artifactId>
</dependency>
<!--使用jcl-over-slf4j,把jdk自带的日志包java.util.logging转换成slf4j-->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jul-to-slf4j</artifactId>
</dependency>

②logback 配置文件,logback工作时的具体细节可以通过 logback.xml 来配置

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
    <!-- 指定日志输出的位置 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!-- 日志输出的格式 -->
            <!-- 按照顺序分别是:时间、日志级别、线程名称、打印日志的类、日志主体内容、换行 -->
            <pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n</pattern>
        </encoder>
    </appender>
    <!-- 设置全局日志级别。日志级别按顺序分别是:DEBUG、INFO、WARN、ERROR -->
    <!-- 指定任何一个日志级别都只打印当前级别和后面级别的日志。 -->
    <root level="INFO">
        <!-- 指定打印日志的 appender,这里通过“STDOUT”引用了前面配置的 appender -->
        <appender-ref ref="STDOUT" />
    </root>
    <!-- 根据特殊需求指定局部日志级别 -->
    <logger name="com.atguigu.crowd.mapper" level="DEBUG"/>
</configuration>

9.声明式事务

事务:声明式事务和编程式事务

9.1编程式事务:

try{
    //开启事务(关闭自动提交)
    connection.setAutoCommit(false);
    //核心操作
    adminService.saveAdmin(admin);
    //提交事务
    connection.commit();
}catch(Exception e){
    //回滚事务
    connection.rollBack();
}finally{
    //释放数据库连接
    connection.close();
}

9.2声明式事务:在框架环境下通过一系列的配置由spring来管理事务操作,然后让我们写的代码能够享受框架提供的服务。

9.3配置的思路

9.4代码步骤(可以配置到上面的spring配置文件中,也可以新建一个,为了防止过长,我们新建)

  • 配置事务管理器
  • 配置aop
  • 配置事务属性
<?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:aop="http://www.springframework.org/schema/aop"
       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/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!--配置自动扫描的包:主要是为了把Service扫描到ioc容器中-->
    <context:component-scan base-package="com.atguigu.crowd.service"/>
    <!--配置事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--装配数据源,报错不影响,因为另一个配置文件中有数据源,且会加载到IOC容器中-->
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--配置事务通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--配置事务的属性-->
        <tx:attributes>
            <!--查询方法:配置只读属性,让数据库知道这是一个查询操作,能够进行一定优化-->
            <tx:method name="get*" read-only="true"/>
            <tx:method name="find*" read-only="true"/>
            <tx:method name="query*" read-only="true"/>
            <tx:method name="count*" read-only="true"/>
            <!--增删改方法:配置事务的传播行为、回滚异常-->
            <!--
                propagation属性:
                    REQUIRED:默认值,表示当前方法必须工作在事务中,如果当前线程上没有已经开启的事务,则开自己的事务。如果已经有事务,就使用这个已有的事务。
                    顾虑:用别人的事务有可能“被”回滚
                    REQUIRES_NEW:建议使用的值,表示当前方法必须工作在事务中,且必须启动新事务,并在他自己的事务中运行,如果有事务在运行,就挂起。
                    好处:不会受到其他事务回滚的影响
                rollback-for属性:配置事务方法针对什么样的异常进行回滚
                    默认:运行时异常回滚
                    建议:编译时异常和运行时异常都回滚——java.lang.Exception
            -->
            <tx:method name="save*" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception"/>
            <tx:method name="update*" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception"/>
            <tx:method name="remove*" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception"/>
            <tx:method name="batch*" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception"/>
        </tx:attributes>
    </tx:advice>
    <!--配置切入点和切面-->
    <aop:config>
        <!--配置切入点表达式,就是要声明事务的方法-->
        <aop:pointcut id="txPointcut" expression="execution(* *..*ServiceImpl.*(..))"/>
        <!--切面:将切入点表达式和事务通知关联起来-->
        <aop:advisor advice-ref="" pointcut-ref="txPointcut"/>
    </aop:config>
</beans>

9.5测试

@Service
public class AdminServiceImpl implements AdminService {

    @Autowired
    private AdminMapper adminMapper;

    @Override
    public void saveAdmin(Admin admin) {
        adminMapper.insert(admin);
        throw new RuntimeException();
    }
}

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring-persist-mybatis.xml","classpath:spring-persist-tx.xml"})
public class CrowdTest {

    @Autowired
    private AdminService adminService;

    @Test
    public void testTx(){
        Admin admin = new Admin(null, "jerry", "123456", "杰瑞", "jerry@qq.com", null);
        adminService.saveAdmin(admin);
    }
}

注意:在基于xml的声明式事务中,事务属性的tx:method是必须配置的,如果某个方法没有配置对应的tx:method,那么事务对这个方法就不生效。

10.表述层

10.1表述层工作机制(web.xml和spring配置文件关系)

  • spring的ioc容器中有:service(带事务)、mapper
  • springmvc的ioc容器中有:controller、interceptor(拦截器)、异常映射机制
  • 装配的关系:service装配mapper;controller装配service

10.2表述层环境搭建

  • 目标一:controller中装配service
  • 目标二:页面能够访问到controller
  • 页面→controller(@RequestMapping)→service→mapper→数据库

①.web.xml配置文件

  • 配置ContextLoaderListener加载Spring的配置文件:spring-persist-mybatis.xml和spring-persist-tx.xml,根据 Spring 的配置文件初始化 IOC 容器
  • 配置CharacterEncodingFilter,解决 POST 请求的字符乱码问题。需要注意的是:在 web.xml 中存在多个 Filter时,让这个 Filter 作为过滤器链中的第一个 Filter。
  • 配置HiddenHttpMethodFilter,遵循 RESTFUL 风格将 POST 请求转换为 PUT 请求、DELETE 请求时使用。
  • 配置前端控制器DispatcherServlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!--配置ContextLoaderListener加载Spring的配置文件:spring-persist-mybatis.xml和spring-persist-tx.xml-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-persist-*.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!-- 配置CharacterEncodingFilter解决POST请求的字符乱码问题 -->
    <filter>
        <filter-name>CharacterEncodingFilter</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>forceRequestEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
        <!-- 强制响应进行编码 -->
        <init-param>
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!--配置HiddenHttpMethodFilter编码过滤器,遵循RESTFUL风格将POST请求转换为PUT请求、DELETE请求时使用-->
    <filter>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>HiddenHttpMethodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!--注册前端控制器DispatcherServlet-->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-web-mvc.xml</param-value>
        </init-param>
        <!--
            servlet默认生命周期中,创建对象是在第一次接收到请求时,而dispatcherServlet作为框架的核心组件,
            在启动过程中有大量的初始化操作要做,而这些操作放在第一次请求时才执行会严重影响访问速度
            因此需要通过此标签将启动控制DispatcherServlet的初始化时间提前到服务器启动时
        -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!--
        设置springMVC的核心控制器所能处理的请求的请求路径:
            /所匹配的请求可以是/login或.html或.js或.css方式的请求路径
            但是/不能匹配.jsp请求路径的请求
    -->
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
<!--        <url-pattern>*.html</url-pattern>;使用此方式,在spring-web-mvc中就不需要配置default-servlet-handler了-->
<!--        <url-pattern>*.json</url-pattern>-->
    </servlet-mapping>
</web-app>

②.spring-web-mvc.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.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--组件扫描,自动扫描包-->
    <context:component-scan base-package="com.atguigu.crowd.mvc"/>
    <!--开启mvc注解驱动 -->
    <mvc:annotation-driven/>
    <!--配置Thymeleaf视图解析器-->
    <bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
        <!--设置视图解析器的优先级-->
        <property name="order" value="1"/>
        <!--视图解析器所用的编码-->
        <property name="characterEncoding" value="UTF-8"/>
        <!--视图解析器的模板-->
        <property name="templateEngine">
            <!--内部bean,为templateEngine赋值-->
            <bean class="org.thymeleaf.spring5.SpringTemplateEngine">
                <property name="templateResolver">
                    <!--内部bean,为templateResolver赋值-->
                    <bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
                        <!--视图前缀-->
                        <property name="prefix" value="/WEB-INF/templates/"/>
                        <!--视图后缀-->
                        <property name="suffix" value=".html"/>
                        <!--模板的模型:HTML5-->
                        <property name="templateMode" value="HTML5"/>
                        <property name="characterEncoding" value="UTF-8"/>
                    </bean>
                </property>
            </bean>
        </property>
    </bean>
    <!--
        处理静态资源,例如html、js、css、jpg
        若只设置该标签,则只能访问静态资源,其他请求则无法访问
        此时必须设置<mvc:annotation-driven/>解决问题
    -->
    <mvc:default-servlet-handler/>
</beans>

​

③.引入依赖

    <!-- 引入 Servlet 容器中相关依赖 -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <scope>provided</scope>
    </dependency>
    <!-- Spring5和Thymeleaf整合包 -->
    <dependency>
        <groupId>org.thymeleaf</groupId>
        <artifactId>thymeleaf-spring5</artifactId>
    </dependency>

11.SpringMVC 环境下的 Ajax 请求

  • 前端发送过来,后端要处理的请求有两种:
  • 普通请求:后端处理完成后返回 页面,浏览器使用使用页面替换整个窗口中的内容
  • Ajax 请求:后端处理完后通常返回 JSON 数据,jQuery 代码使用 JSON 数据对页面局部更新

常用注解:@RequestBody和@ResponseBody

12.异常映射

①.基于xml的异常机制

<!--配置基于XML的异常机制-->
    <bean id="simpleMappingExceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <!--配置异常的类型和具体视图页面的对应关系-->
        <property name="exceptionMappings">
            <props>
                <!--
                    properties的键表示处理器方法执行过程中出现的异常
                    properties的值表示若出现指定异常时,设置一个新的视图名称,跳转到指定页面,这个值要拼前后缀得到具体的路径
                -->
                <prop key="java.lang.Exception">system-error</prop>
            </props>
        </property>
        <!--
            exceptionAttribute属性设置一个属性名,将出现的异常信息存储到请求域中,键为ex,异常信息为值
         -->
        <property name="exceptionAttribute" value="ex"/>
    </bean>

②.判断请求类型的工具方法

//判断请求类型的工具类
public class CrowdUtil {
    public static boolean judgeRequestType(HttpServletRequest request){
        //请求类型(普通请求或者是Ajax请求)的判断依据是:
        //1.获取请求消息头
        String acceptHeader = request.getHeader("Accept");
        String xRequestHeader = request.getHeader("X-Requested-With");
        //2.判断
        if(
           (acceptHeader != null && acceptHeader.contains("application/json"))
            ||
           (xRequestHeader != null && xRequestHeader.equals("XMLHttpRequest"))
        ){  
            //Ajax请求
            return true;    
        }
        return false; //普通请求
    }
}

③.基于注解的异常机制

//@ControllerAdvice将当前类标识为一个基于注解的异常处理器类
@ControllerAdvice
public class CrowdExceptionResolver {
    //把异常类型和方法关联起来
    @ExceptionHandler(NullPointerException.class)
    public ModelAndView resolverNullPointerException(
            //1.实际捕获到的异常类型
            Exception exception,
            //当前请求的对象
            HttpServletRequest request,
            HttpServletResponse response) throws IOException {
        //1.判断请求类型
        boolean judgeRequestType = CrowdUtil.judgeRequestType(request);
        //2.如果是ajax请求
        if(judgeRequestType){
            //3.获取异常信息
            String message = exception.getMessage();
            //4.创建Gson对象
            Gson gson = new Gson();
            //5.将异常信息转换为Json字符串
            String json = gson.toJson(message);
            //6.将JSON字符串作为响应体返回给浏览器
            response.getWriter().write(json);
            //7.由于上面已经通过原生的response对象返回了响应,所以不提供ModelAndView对象
            return null;
        }
        //8.如果不是Ajax请求则创建ModelAndView对象
        ModelAndView modelAndView = new ModelAndView();
        //9.将Exception对象存入模型
        modelAndView.addObject("ex",exception);
        //10.设置对应的视图
        modelAndView.setViewName("system-error");
        return modelAndView;
    }
}

13.layer弹层组件

①.加入layer库文件和样式文件

②在页面上引入layer环境

<script type="text/javascript" src="jquery/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="layer/layer.js"></script>

③.layer的使用:弹层提示框

layer.msg("这里是 layer 弹出的消息!");

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SSM框架学习宝典:入门、进阶、精通,全方位代码项目资 一、探索SSM的无限可能 SSM(Spring + Spring MVC + MyBatis)框架作为Java开发中的黄金组合,为开发者提供了强大的技术支持和丰富的功能。本系列资料将带您从零基础开始,逐步掌握SSM的核心技术和最佳实践,助您在Java Web开发领域更上一层楼。 二、资料亮点 基础教程与练习项目:从基础知识讲起,结合实际练习项目,让您轻松上手SSM开发。 进阶技术与案例分析:针对进阶开发者,提供深入的技术探讨和案例分析,助您深入理解SSM的高级特性。 实战项目与经验分享:通过实际项目实战,让您在实践中掌握SSM的运用,同时分享经验与心得,让您少走弯路。 三、适用人群与场景 无论您是初学者还是资深开发者,无论您是在校学生还是职场人士,本系列资料都将是您学习SSM的得力助手。适用于Java Web开发、企业级应用开发、个人项目实践等多个领域。 四、使用建议 系统学习:按照资料提供的顺序进行系统学习,确保知识体系的完整性。 实践为王:在学习过程中注重实践操作,通过实际项目加深理解。 持续反馈与调整:根据学习进度和反馈,适时调整学习策略,提高学习效果。 五、安全与责任 在使用SSM框架进行开发时,请确保遵循最佳实践和安全准则,以保障系统的稳定性和安全性。在使用提供的资料时,请遵守版权法规,尊重原作者的权益。让我们共同为推动SSM技术的发展而努力!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值