• 第1章 需求分析与ssm环境准备


    目录

    1-1 课程介绍与项目演示

     1-2 SSM整合的意义

     1-3 Spring与Spring MVC环境配置

     1-4 解决请求与响应乱码问题

     1-5 介绍Spring与MyBatis整合配置

     1-6 Spring与MyBatis整合过程

     1-7 继承Junit单元测试与Logback日志

     1-8 集成声明式事务

     1-9 整合MyBatis-Plus

    1-10 MyBatis Plus快速实现CRUD(上)

     1-11 MyBatis Plus快速实现CRUD(下)


    1-1 课程介绍与项目演示

     

     主要知识点

    此项目是一个基于移动端的html5应用,因此不仅可以在pc上也可以在手机上使用

     

     打开浏览器按f12弹出控制台,点击

     模拟手机型号

     访问本地端口

     下方会有加载更多,点击以后会持续的进行加载

     在上方也可以根据图书类别进行筛选

     点击后端就会筛选出后端的专栏了

    在页面最上方还有一个排序的功能 

    将最高分的图书专栏放到第一位上依次递减

     

     点击任意一本书,就可以看到详细专栏和内容了

     中下部分会有短评,如果登陆了的话就可以评价发表一下自己的看法,也可以在右侧进行点赞

     因为没有登陆所以会提示登录

     跳转登陆页面

     没有账号可以点击右上角

     

     输入后就可以完成会员的注册工作

     注册成功后跳转,登录页面

     输入已有的用户,密码验证码错误则提示,验证码也会刷新

     只有输入正确的才可以,回到默认首页上 ,显示登录人的昵称

    登录状态下查看某一本书就可以对原有的图书运行状态进行调整

     可以进行评价

     

     输入进入后台图书管理界面

     

     可以通过这里对前端进行管理

     点击新增图书

     

     

     这里就会出现新增的数据

     在前端的书评往上也是可以看到的

    筛选到测试

     

     后台管理功能就是对前台数据进行管理和组织的

    回到管理点击修改

     可以对里面的信息或者图文混排的顺序进行调整

     更改标题后就会发生变化

     发现某一本图书不需要了就点击,便可以实现删除的功能

     1-2 SSM整合的意义

     什么是整合

    springmvc提供了控制器基于springweb交互的能力

    spring本意是对应用程序的创建和管理,其他所有框架的对象都是由spring进行统筹协调的

    mybatis完成了与底层数据库增删改查的操作

     

     1-3 Spring与Spring MVC环境配置

     创建全新工程

     

     

    创建好后增加对于web模块的支持

     

    配置webapp目录

     

     

     

     

     进行代码的编译测试

    创建测试类

     

     

     测试app资源能否正式发布

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>Titletitle>
    6. head>
    7. <body>
    8. I'm index page
    9. body>
    10. html>

     在web中对其配置

    1. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    4. version="3.1">
    5. <welcome-file-list>
    6. <welcome-file>index.htmlwelcome-file>
    7. welcome-file-list>
    8. web-app>

    配置tomcat

     

     上下文设置为/

     运行,发布成功

     说明应用部署是成功的

     

    准备工作完成

    进行spring与springmvc的配置工作

    打开pom.xml

    1. <project xmlns="http://maven.apache.org/POM/4.0.0"
    2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    4. <modelVersion>4.0.0modelVersion>
    5. <groupId>com.imoocgroupId>
    6. <artifactId>imooc-readerartifactId>
    7. <version>1.0-SNAPSHOTversion>
    8. <properties>
    9. <maven.compiler.source>8maven.compiler.source>
    10. <maven.compiler.target>8maven.compiler.target>
    11. properties>
    12. <repositories>
    13. <repository>
    14. <id>aliyunid>
    15. <name>aliyunname>
    16. <url>https://maven.aliyun.com/repository/publicurl>
    17. repository>
    18. repositories>
    19. <dependencies>
    20. //spring框架
    21. <dependency>
    22. <groupId>org.springframeworkgroupId>
    23. <artifactId>spring-webmvcartifactId>
    24. <version>5.3.8version>
    25. dependency>
    26. //把对象转化成json字符串进行输出
    27. <dependency>
    28. <groupId>com.fasterxml.jackson.coregroupId>
    29. <artifactId>jackson-databindartifactId>
    30. <version>2.12.3version>
    31. dependency>
    32. dependencies>
    33. project>

    springmvc底层是要基于dispatcherservlet来进行请求的拦截和转发,因此要在web.xml进行配置

    1. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    4. version="3.1">
    5. <welcome-file-list>
    6. <welcome-file>index.htmlwelcome-file>
    7. welcome-file-list>
    8. <servlet>
    9. <servlet-name>spring-mvcservlet-name>
    10. <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
    11. <init-param>
    12. //启动的时候自动就会在当前的类路径下以applicationContext开头的文件并对其进行
    13. 加载
    14. <param-name>contextConfigLocationparam-name>
    15. <param-value>classpath:applicationContext*.xmlparam-value>
    16. init-param>
    17. //再应用启动过程中自动完成DispatcherServlet初始化过程
    18. <load-on-startup>0load-on-startup>
    19. servlet>
    20. <servlet-mapping>
    21. <servlet-name>spring-mvcservlet-name>
    22. <url-pattern>/url-pattern>
    23. servlet-mapping>
    24. web-app>

    增加applicationContext.xml文件

    1. <beans xmlns="http://www.springframework.org/schema/beans"
    2. xmlns:mvc="http://www.springframework.org/schema/mvc"
    3. xmlns:context="http://www.springframework.org/schema/context"
    4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    5. xmlns:task="http://www.springframework.org/schema/task"
    6. xsi:schemaLocation="
    7. http://www.springframework.org/schema/beans
    8. http://www.springframework.org/schema/beans/spring-beans.xsd
    9. http://www.springframework.org/schema/context
    10. http://www.springframework.org/schema/context/spring-context.xsd
    11. http://www.springframework.org/schema/task
    12. http://www.springframework.org/schema/task/spring-task.xsd
    13. http://www.springframework.org/schema/mvc
    14. http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    15. //配置组件扫描
    16. <context:component-scan base-package="com.imooc"/>
    17. //开启springmvc的注解模式
    18. <mvc:annotation-driven/>
    19. //把静态资源排除在外
    20. <mvc:default-servlet-handler/>
    21. beans>

    测试能否正常启动

    不要忘记发布新依赖的组件

    没有异常说明配置正确

     

     1-4 解决请求与响应乱码问题

    首先解决请求中的中文乱码问题

    在web.xml中增加过滤器

    
        characterFilter
        org.springframework.web.filter.CharacterEncodingFilter
        
            //设置初始化参数
            encoding
            UTF-8
        
    
    //设置映射器拦截
    
        characterFilter
        /*
    

    这个过滤器的作用就是当前post请求体中的中文乱码自动转化为utf-8

    那么get请求需要额外设置吗?答案是否定的。默认对get请求时就进行了utf-8代码的转换,所以针对get请求无需额外的设置。

    与之对应的相应问题该怎么解决呢?

    回到applicationContext.xml上。增加消息转换器

    
        
            
                
                    
                        application/json;charset=utf-8
                    
                
            
        
    

    为什么在这里只保留一项?

     因为前端的url都是基于view通过ajax请求向后端进行数据处理,而后端controller返回的所有数据都是json字符串,所以只保留这一项就可以了。

    进行测试

    创建测试类

    @Controller
    public class TestController {
        @PostMapping("/t/test1")
        @ResponseBody
        public Map test1(String content){
            Map result = new HashMap();
            result.put("test", "测试:" + content);
            return result;
        }
    }
    

    当前是一个post请求,如何对post请求进行测试呢?

    内置了 http客户端帮助我们进行测试

     

     如何设置请求体?

     

    自动出现post请求数据结构

     只需要进行局部调整就可以了

     

     

     

     出现第一个测试案例

    从服务器生成的test的map被进行json序列化 内容和我们预期是相符的 测试文本来自于参数说明请求体中的中文可以正确的被接收

      响应码200代表处理成功,处理时间和内容长度

     http测试工具放在哪儿呢?

     1-5 介绍Spring与MyBatis整合配置

    sqlsessionFactory对象是通过我们程序来创建的和spring没有任何的关系,因为使我们自己创建spring也不会管理它,这样的缺点很明显,mybatis无法享受到Spring为原始程序提供的扩展功能

    在springioc容器中进行简单的配置来让springioc容器在初始化的时候自动创建sqlsessionfactory对象,同时被ioc进行管理

     

     1-6 Spring与MyBatis整合过程

    在pom.xml中引入依赖

     
            org.springframework
            spring-jdbc
            5.3.8
        
        
            org.mybatis
            mybatis
            3.5.7
        
        
        
            org.mybatis
            mybatis-spring
            2.0.6
        
        
            //mysql的jdbc驱动
            mysql
            mysql-connector-java
            8.0.16
        
        
            com.alibaba
            druid
            1.2.6
        
    

    打开applicationContext.xml完成spring与mybatis的整合过程

    
    
    
        
        
        
        
        
        
    
    
    
    //sessionfactory就是用于创建mybatis的session对象 是mybatis最核心的一个对象
    
        //连接数据源
        
        //自动扫描哪一个目录下的那些文件 保存sql文件的xml放在哪里
        
        //配置文件路径 mybatis框架本身所依赖的文件是哪个
        
    
    
    //通知mybatis扫描哪一个目录下的接口
    
        
    

    配置mybatis-config.xml

     

    
    
    
        
            //开启驼峰命名转换
            
        
    

    创建mappers目录 mapper包

     

     

     1-7 继承Junit单元测试与Logback日志

     增加对junit的支持 spring提供的测试组件

    
        junit
        junit
        4.12
        test
    
    
        org.springframework
        spring-test
        5.3.8
    
    

     如何进行spring-test单元测试?

    新建mapper接口

     

    public interface TestMapper {
        public void insertSample();
    }

     新建test.xml

    会自动被扫描mappers下的所有文件

     

    
    
    
        
            insert into test(content) values('测试内容')
        
    

     还需要在mybatis-config去额外注册xml吗?答案是否定的。他会自动注册和加载

    生成测试用例类

     

     把springioc容器以及相关的初始化工作都做好,才可以进行后续的测试

    //将spring和junit测试框架整合在一起
    @RunWith(SpringJUnit4ClassRunner.class)
    //指明上下文配置文件
    @ContextConfiguration(locations = {"classpath:applicationContext.xml"})
    public class TestMapperTestor {
        @Resource
        private TestMapper testMapper;
        @Test
        public void insertSample() {
            testMapper.insertSample();
        }
    }
    

    运行 出现报错

     servelt包不存在

    spring和mybatis之间的整合测试为什么还要跟javax Servlet包产生关系呢?

    springmvc底层运行的依赖就是javax.servelt,所以还要在pom.xml中进行引入

    
        javax.servlet
        javax.servlet-api
        3.1.0
        //只有在我们测试运行的过程中才会进行加载
        provided
    

     运行时可以不发布servlet-api的jar包因为tomcat中这个包已经自带了,没有必要重复发布

    重新运行,执行成功

     

    再次运行

    但是控制台中能够为我们提供的信息还是太少了,我们想知道sql到底执行了什么参数有哪些,以及在ioc容器初始化时做了什么事情。

    引入logback日志依赖

    
        ch.qos.logback
        logback-classic
        1.2.3
    

     再次运行

     可以十分清晰的掌握到程序执行的过程

    对这些日志文件的格式自定义

    
    
        
            
                //到秒的时间显示 输出级别 线程 输出的对象 日志的消息
                %d{HH:mm:ss} %-5level [%thread] %logger{30} - %msg%n
                UTF-8
            
        
        // 最低输出级别
        
            
        
    

     

     1-8 集成声明式事务

     基于注解或者配置的方式自动帮助我们进行数据库事务的提交或者回滚

    增加service业务逻辑包

     新增 测试声明式事务类

    @Service
    public class TestService {
        @Resource
        private TestMapper testMapper;
        //增加批量导入功能,验证声明式事务能否正常运行
        public void batchImport(){
            for(int i = 0 ; i < 5 ;i++){
                testMapper.insertSample();
            }
        }
    }

    测试能否一次性全部回滚 ,生成测试用例类

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = {"classpath:applicationContext.xml"})
    public class TestServiceTestor {
        @Resource
        private TestService testService;
        @Test
        public void batchImport() {
            testService.batchImport();
            System.out.println("批量导入成功");
        }
    }

     运行执行成功

     模拟一种异常的情况,代码的数据完整性还能保障吗?

    @Service
    public class TestService {
        @Resource
        private TestMapper testMapper;
        public void batchImport(){
            for(int i = 0 ; i < 5 ;i++){
                /*if(i==2){
                    throw new RuntimeException("未处理异常");
                }*/
                testMapper.insertSample();
            }
        }
    }

    运行

     没产生后面的三条,要保证数据提交的完整性

    spring-jdbc里自带了针对声明式事务的底层支持,要确保他的存在

    在applicationContext.xml里增加与声明式事务相关的命名空间

    
    

     这样就可以进行声明式事务的配置

    
    
        
    
    //开启注解模式的声明式事务
    

     在开发中如何使用呢?

    @Service
    public class TestService {
        @Resource
        private TestMapper testMapper;
        //代表执行当前方法时开启声明式事务 执行成功则自动进行实物的提交,抛出运行时异常则自动进行事务的回滚
        //扩大回滚范围
        @Transactional(rollbackFor = Exception.class)
        public void batchImport(){
            for(int i = 0 ; i < 5 ;i++){
                /*if(i==2){
                    throw new RuntimeException("未处理异常");
                }*/
                testMapper.insertSample();
            }
        }
    }

    再次执行 爆出异常

    创建对象

     开启事务

     事务释放

    回滚

     

    不会出现数据

     

    正常运行

    事务提交 

    写入数据

     

     1-9 整合MyBatis-Plus

     

     

     

     

     POM.xml中

    注释掉

     因为引入mybatis-plus后就会自动对mybatis进行加载

    
        com.baomidou
        mybatis-plus
        3.4.3.1
    

    出现依赖

     

     调整applicationContext.xml的信息

    
        

     sessionfactory初始化的工作就不需要mybatis-spring这个组件来进行而是用

    来进行初始化 

    注释掉

     最后调整mybatis-config 根据版本配置不同

    分页插件配置

    3.4以前

    
    

    3.4版本以后就不需要在mybatis-config中进行配置了

    转换到applicationContext.xml

    
        
        
        
        
        
            
                //插件容器
                
                    //进行指定
                    
                        
                            
                        
                    
                
            
        
    

    1-10 MyBatis Plus快速实现CRUD(上)

     

     打开tsetmapper接口,此时如何实现增删改查?

    在test.xml中书写sql语句

     但是太麻烦了,假如有100张表就要写至少400个sql语句。

    通过mybatis-plus自动生成这些sql语句

    生成实体包和一个实体类

    //表明
    @TableName("test")
    public class TestTable {
        //说明id字段是表的主键,同时数据新增时使用表自带的自增主键生成编号
        @TableId(type = IdType.AUTO)
        @TableField("id") //说明属性对应哪个字段
        private Integer id;
        @TableField("content") //如果字段名与属性名相同时@TableField可以忽略
        private String content;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getContent() {
            return content;
        }
    
        public void setContent(String content) {
            this.content = content;
        }
    }

     描述了表和字段与类的对应关系

    回到接口继承父接口传入泛型

    public interface TestMapper extends BaseMapper {
        public void insertSample();
    }

    查看一下这个父接口中包含了哪些方法

    1. public interface BaseMapper extends Mapper {
    2. /**
    3. * 插入一条记录
    4. *
    5. * @param entity 实体对象
    6. */
    7. int insert(T entity);
    8. /**
    9. * 根据 ID 删除
    10. *
    11. * @param id 主键ID
    12. */
    13. int deleteById(Serializable id);
    14. /**
    15. * 根据 columnMap 条件,删除记录
    16. *
    17. * @param columnMap 表字段 map 对象
    18. */
    19. int deleteByMap(@Param(Constants.COLUMN_MAP) Map columnMap);
    20. /**
    21. * 根据 entity 条件,删除记录
    22. *
    23. * @param queryWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
    24. */
    25. int delete(@Param(Constants.WRAPPER) Wrapper queryWrapper);
    26. /**
    27. * 删除(根据ID 批量删除)
    28. *
    29. * @param idList 主键ID列表(不能为 null 以及 empty)
    30. */
    31. int deleteBatchIds(@Param(Constants.COLLECTION) Collection idList);
    32. /**
    33. * 根据 ID 修改
    34. *
    35. * @param entity 实体对象
    36. */
    37. int updateById(@Param(Constants.ENTITY) T entity);
    38. /**
    39. * 根据 whereEntity 条件,更新记录
    40. *
    41. * @param entity 实体对象 (set 条件值,可以为 null)
    42. * @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
    43. */
    44. int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper updateWrapper);
    45. /**
    46. * 根据 ID 查询
    47. *
    48. * @param id 主键ID
    49. */
    50. T selectById(Serializable id);
    51. /**
    52. * 查询(根据ID 批量查询)
    53. *
    54. * @param idList 主键ID列表(不能为 null 以及 empty)
    55. */
    56. List selectBatchIds(@Param(Constants.COLLECTION) Collection idList);
    57. /**
    58. * 查询(根据 columnMap 条件)
    59. *
    60. * @param columnMap 表字段 map 对象
    61. */
    62. List selectByMap(@Param(Constants.COLUMN_MAP) Map columnMap);
    63. /**
    64. * 根据 entity 条件,查询一条记录
    65. *
    66. * @param queryWrapper 实体对象封装操作类(可以为 null)
    67. */
    68. T selectOne(@Param(Constants.WRAPPER) Wrapper queryWrapper);
    69. /**
    70. * 根据 Wrapper 条件,查询总记录数
    71. *
    72. * @param queryWrapper 实体对象封装操作类(可以为 null)
    73. */
    74. Integer selectCount(@Param(Constants.WRAPPER) Wrapper queryWrapper);
    75. /**
    76. * 根据 entity 条件,查询全部记录
    77. *
    78. * @param queryWrapper 实体对象封装操作类(可以为 null)
    79. */
    80. List selectList(@Param(Constants.WRAPPER) Wrapper queryWrapper);
    81. /**
    82. * 根据 Wrapper 条件,查询全部记录
    83. *
    84. * @param queryWrapper 实体对象封装操作类(可以为 null)
    85. */
    86. List> selectMaps(@Param(Constants.WRAPPER) Wrapper queryWrapper);
    87. /**
    88. * 根据 Wrapper 条件,查询全部记录
    89. *

      注意: 只返回第一个字段的值

    90. *
    91. * @param queryWrapper 实体对象封装操作类(可以为 null)
    92. */
    93. List selectObjs(@Param(Constants.WRAPPER) Wrapper queryWrapper);
    94. /**
    95. * 根据 entity 条件,查询全部记录(并翻页)
    96. *
    97. * @param page 分页查询条件(可以为 RowBounds.DEFAULT)
    98. * @param queryWrapper 实体对象封装操作类(可以为 null)
    99. */
    100. extends IPage> P selectPage(P page, @Param(Constants.WRAPPER) Wrapper queryWrapper);

    101. /**
    102. * 根据 Wrapper 条件,查询全部记录(并翻页)
    103. *
    104. * @param page 分页查询条件
    105. * @param queryWrapper 实体对象封装操作类
    106. */
    107. extends IPage>> P selectMapsPage(P page, @Param(Constants.WRAPPER) Wrapper queryWrapper);

    108. }
    109. 回到测试用例类

       利用basemapper中的方法完成数据交互的操作

       执行insert

      @Test
      public void testInsert(){
          TestTable test = new TestTable();
          test.setContent("XXXXX");
          int count = testMapper.insert(test);
          System.out.println("本次新增" + count + "条数据");
      }

       basemapper自动生成sql语句

      content就是在实体类定义的

       

       

       根据属性和字段的对应关系来生成sql语句的

       update方法

      @Test
      public void testUpdate(){
          TestTable test = new TestTable();
          test.setId(20);
          test.setContent("XXXX1");
          testMapper.updateById(test);
      }

       自动将id主键带入其中

       1-11 MyBatis Plus快速实现CRUD(下)

       删除操作delete

      @Test
      public void testDelete(){
          testMapper.deleteById(20);
      }

      只需要id号

       

       删除后再次执行,update为0 

       查询select

      @Test
      public void testSelectById(){
          TestTable test = testMapper.selectById(21);
          System.out.println(test.getContent());
      }

       

       批量查询selectlist

      @Test
      public void testSelectList(){
          QueryWrapper wrapper = new QueryWrapper();
          //gt大于的意思
          wrapper.gt("id", 21);
          //多条件查询,精准匹配
          wrapper.eq("content", "测试内容");
          List list = testMapper.selectList(wrapper);
          System.out.println(list.size());
      } 

       但是复杂的比如说包含左关联右关联或者一系列聚合筛选的sql该怎么做呢?

      和以前一样在xml中去定义select标签 手写复杂的sql语句

      如果要进行数据分页该怎么写呢?

      @Test
      public void testPagination(){
          //增加ipage接口 实例化 查询第几页 每页有多少条记录
          IPage page = new Page(2, 2);
          QueryWrapper wrapper = new QueryWrapper();
          wrapper.gt("id", 21);
          wrapper.eq("content", "测试内容");
          page = testMapper.selectPage(page, wrapper);
          System.out.println("总页数:" + page.getPages());
          System.out.println("总记录数:" + page.getTotal());
          System.out.println("当前页数据:" + page.getRecords());
      }

      运行方法

       limit代表截取数据的范围

       第2页只有1条数据

    110. 相关阅读:
      剑指offer---Day5
      氨基苯酚/多巴胺仿生修饰碳纳米管/α-氧化铝/ CNTs-Ag纳米复合材料
      如何快速上手一个新项目?
      踩了个DNS解析的坑,但我还是没想通
      动态规划:01背包(Dynamic Programming)
      让数据“动”起来:Python动态图表制作详解
      android studio 移植工程
      AVS3中的intra string copy(ISC)
      16:00面试,16:06就出来了,问的问题有点变态。。。
      QQ2 微信红包
    111. 原文地址:https://blog.csdn.net/lonelyneet/article/details/125988292