• SSM(Spring-Mybatis-SpringMVC)


    1. 介绍

    1.1 概念介绍

    SSM项目是指基于Spring+SpringMVC+MyBatis框架搭建的Java Web项目。

    • Spring是负责管理和组织项目的IOC容器和AOP功能
    • SpringMVC是一个轻量级的MVC框架,用于处理Web请求和响应
    • MyBatis是一种持久化框架,用于进行数据库操作的ORM框架。

    学习笔记:
    Spring:https://blog.csdn.net/meini32/article/details/132474555
    SpringMVC:https://blog.csdn.net/meini32/article/details/132545058
    Mybatis:https://blog.csdn.net/meini32/article/details/132068955
    Mybatis商品增删改查案例:https://blog.csdn.net/meini32/article/details/132095237

    2 SSM整合框架

    关键内容

    Spring

    • SpringConfig

    SpringMVC

    • SpringMvcConfig
    • ServletConfig

    Mybatis

    • MyBatisConfig
    • JdbcConfig
    • jdbc.properties

    MyBatis
    jdbc.properties

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/db1
    jdbc.username=root
    jdbc.password=123456
    
    • 1
    • 2
    • 3
    • 4
    package com.it.config;
    
    import javax.sql.DataSource;
    import com.alibaba.druid.pool.DruidDataSource;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    //jdbcConfig
    
    public class jdbcConfig {
    
        @Value("${jdbc.driver}")
        private String driver;
        @Value("${jdbc.url}")
        private String url;
        @Value("${jdbc.username}")
        private String username;
        @Value("${jdbc.password}")
        private String password;
    
        //数据源
        @Bean
        public DataSource dataSource(){
            DruidDataSource druidDataSource = new DruidDataSource();
            druidDataSource.setDriverClassName(driver);
            druidDataSource.setUrl(url);
            druidDataSource.setUsername(username);
            druidDataSource.setPassword(password);
            return druidDataSource;
        }
    }
    -----------------------------------------------------
    package com.it.config;
    
    
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.mybatis.spring.mapper.MapperScannerConfigurer;
    import org.springframework.context.annotation.Bean;
    import javax.sql.DataSource;
    
    //MyBatisConfig
    public class MybatisConfig {
    
        //创建和管理数据库会话
        @Bean
        public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
            SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
            factoryBean.setDataSource(dataSource);
            factoryBean.setTypeAliasesPackage("com.it.domain");
            return factoryBean;
        }
    
        @Bean
        //创建并配置MapperScannerConfigurer对象
        public MapperScannerConfigurer mapperScannerConfigurer(){
            MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
            mapperScannerConfigurer.setBasePackage("com.it.dao");
            return mapperScannerConfigurer;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    web容器配置类

    SpringMVC

    • SpringMvcConfig
    • ServletConfig
    //ServletConfig
    @Configuration
    public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
        @Override
        protected Class<?>[] getRootConfigClasses() {
            return new Class[]{SpringConfig.class};
        }
    
        @Override
        protected Class<?>[] getServletConfigClasses() {
            return new Class[]{SpringMvcConfig.class};
        }
    
        @Override
        protected String[] getServletMappings() {
            return new String[]{"/"};
        }
    }
    
    ----------------------------------------------------------------------
    //SpringMvcConfig
    @Configuration
    @ComponentScan("com.it.controller")
    @EnableWebMvc
    public class SpringMvcConfig {
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    Spring

    • SpringConfig
    //整合Spring应用程序,实现对组件和属性的管理和使用
    @Configuration
    @ComponentScan({"com.it.service"})
    @PropertySource("jdbc.properties")
    @Import({jdbcConfig.class, MybatisConfig.class})
    public class SpringConfig {
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3. SSM功能模块开发

    内容

    • 表与实体类;
    • dao(接口+自动代理)
    • service(接口+实现类)
    • controller

    在这里插入图片描述

    添加相关依赖

    <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.0modelVersion>
      <groupId>org.examplegroupId>
      <artifactId>spring-ssmartifactId>
      <packaging>warpackaging>
      <version>1.0-SNAPSHOTversion>
    
      <dependencies>
        <dependency>
          <groupId>org.springframeworkgroupId>
          <artifactId>spring-webmvcartifactId>
          <version>5.2.9.RELEASEversion>
        dependency>
    
        <dependency>
          <groupId>com.fasterxml.jackson.coregroupId>
          <artifactId>jackson-databindartifactId>
          <version>2.9.0version>
        dependency>
    
        <dependency>
          <groupId>org.mybatisgroupId>
          <artifactId>mybatisartifactId>
          <version>3.5.5version>
        dependency>
    
        <dependency>
          <groupId>org.mybatisgroupId>
          <artifactId>mybatis-springartifactId>
          <version>1.3.0version>
        dependency>
    
        <dependency>
          <groupId>mysqlgroupId>
          <artifactId>mysql-connector-javaartifactId>
          <version>5.1.32version>
        dependency>
        <dependency>
          <groupId>org.springframeworkgroupId>
          <artifactId>spring-jdbcartifactId>
          <version>5.3.13version>
        dependency>
    
        <dependency>
          <groupId>org.springframeworkgroupId>
          <artifactId>spring-testartifactId>
          <version>5.3.13version>
        dependency>
    
    
        <dependency>
          <groupId>com.alibabagroupId>
          <artifactId>druidartifactId>
          <version>1.2.6version>
        dependency>
    
        <dependency>
          <groupId>org.projectlombokgroupId>
          <artifactId>lombokartifactId>
          <version>1.18.28version>
        dependency>
    
        <dependency>
          <groupId>javax.servletgroupId>
          <artifactId>javax.servlet-apiartifactId>
          <version>3.1.0version>
          <scope>providedscope>
        dependency>
    
      dependencies>
    
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.tomcat.mavengroupId>
            <artifactId>tomcat7-maven-pluginartifactId>
            <version>2.2version>
            <configuration>
              <port>81port>
              <path>path>
            configuration>
          plugin>
        plugins>
      build>
    project>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    import lombok.Data;
    
    @Data
    public class User {
        private int id;
        private String username;
        private String password;
    }
    
    ------------------------------------------------------------------------
    package com.it.dao;
    
    import com.it.domain.User;
    import org.apache.ibatis.annotations.Delete;
    import org.apache.ibatis.annotations.Insert;
    import org.apache.ibatis.annotations.Select;
    import org.apache.ibatis.annotations.Update;
    
    import java.util.List;
    
    //用户增删改查接口
    public interface UserDao {
    
        @Insert("INSERT INTO tb_user values (null,#{name},#{password}}})")
        public void save(User user);
    
        @Update("UPDATE tb_user set name=#{id},password=#{password} where id=#{id}}")
        public void update(User user);
    
        @Delete("DELETE from tb_user where id = #{id}}")
        public void delete(Integer id);
    
        @Select("SELECT * FROM tb_user")
        public List<User> selectAll();
    
        @Select("SELECT * FROM tb_user WHERE id=#{id}")
        public User selectById(Integer id);
    
    }
    
    ----------------------------------------------------------------------
    package com.it.service;
    
    import com.it.domain.User;
    import org.apache.ibatis.annotations.Delete;
    import org.apache.ibatis.annotations.Insert;
    import org.apache.ibatis.annotations.Select;
    import org.apache.ibatis.annotations.Update;
    
    import java.util.List;
    
    public interface UserService {
        /**
         * 保存
         * @param user
         * @return
         */
        public boolean save(User user);
    
        /**
         * 修改
         * @param user
         * @return
         */
        public boolean update(User user);
    
        /**
         * 删除
         * @param id
         * @return
         */
        public boolean delete(Integer id);
    
        /**
         * 查全部
         * @return
         */
        public List<User> selectAll();
    
        /**
         * 按id查找
         * @param id
         * @return
         */
        public User selectById(Integer id);
    }
    
    ---------------------------------------------------------------------------
    package com.it.service.impl;
    
    import com.it.dao.UserDao;
    import com.it.domain.User;
    import com.it.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    
    @Service
    public class UserServiceImpl implements UserService {
        @Autowired //自动装配
        private UserDao userDao;
    
        public boolean save(User user) {
            userDao.save(user);
            return true;
        }
    
        public boolean update(User user) {
            userDao.update(user);
            return true;
        }
    
        public boolean delete(Integer id) {
            userDao.delete(id);
            return true;
        }
    
        public List<User> selectAll() {
            return userDao.selectAll();
        }
    
        public User selectById(Integer id) {
            return userDao.selectById(id);
        }
    }
    
    ------------------------------------------------------------------------
    package com.it.controller;
    
    
    import com.it.domain.User;
    import com.it.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.List;
    
    @RestController
    @RequestMapping("/user")
    public class UserController {
    
        @Autowired
        private UserService userService;
    
        @PostMapping
        public boolean save(@RequestBody User user) {
            return userService.save(user);
        }
    
        @PutMapping
        public boolean update(@RequestBody User user) {
            return userService.update(user);
    
        }
    
        @DeleteMapping("/{id}")
        public boolean delete(@PathVariable Integer id) {
            System.out.println(userService.delete(id));
            return userService.delete(id);
        }
    
        @GetMapping
        public List<User> selectAll() {
    
            System.out.println(userService.selectAll());
            return userService.selectAll();
        }
    
        @GetMapping("/{id}")
        public User selectById(@PathVariable Integer id) {
            return userService.selectById(id);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175

    4 测试

    4.1 业务层接口测试

    在这里插入图片描述

    4.2 表现层接口测试

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    5.优化 -表现层数据封装

    • 前端接受数据格式封装到code属性用于区分操作
    • 将特殊消息封装到message(msg)属性中
    public class Result{
    	private Object data;
    	private Integer code;
    	private String msg;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    package com.it.controller;
    
    public class Code {
    
        //成功
        public static final Integer SAVE_OK = 20011;
        public static final Integer DELETE_OK = 20021;
        public static final Integer UPDATE_OK = 20031;
        public static final Integer GET_OK = 20041;
        public static final Integer PUT_OK = 20051;
    
    
        //失败
        public static final Integer SAVE_ERR = 20010;
        public static final Integer DELETE_ERR = 20020;
        public static final Integer UPDATE_ERR = 20030;
        public static final Integer GET_ERR = 20040;
        public static final Integer PUT_ERR = 20050;
    }
    ----------------------------------------------------------------------------
    package com.it.controller;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    
    public class Result {
        private Object data;
        private Integer code;
        private String msg;
    
        public Result(Integer code, String msg) {
            this.code = code;
            this.msg = msg;
        }
    
        public Result(Object data, Integer code) {
            this.data = data;
            this.code = code;
        }
    
        public Result(Object data, Integer code, String msg) {
            this.data = data;
            this.code = code;
            this.msg = msg;
        }
    }
    ---------------------------------------------------------------------------
    import java.util.List;
    
    @RestController
    @RequestMapping("/user")
    public class UserController {
    
        @Autowired
        private UserService userService;
    
        @PostMapping
        public Result save(@RequestBody User user) {
            boolean save = userService.save(user);
            return new Result(save,save?Code.SAVE_OK:Code.SAVE_ERR);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    在这里插入图片描述

    6.异常处理

    出现异常位置及原因

    • 框架内部抛出异常:不合规使用
    • 数据层抛出异常:外边服务器故障(超时访问)
    • 业务层抛出异常:业务逻辑书写错误(遍历业务书写操作等)
    • 表现层抛出异常:数据收集、校验等规则导致
    • 工具类抛出异常:工具书写不严谨不健壮

    项目异常分类

    1. 业务异常
      • 原因:用户行为导致
      • 解决:发送相应的信息传递给用户,提醒规范操作。
    2. 系统异常
      • 原因:项目运行时可预计但无法避免的异常
      • 解决:发送固定消息安抚用户;发送消息给处理人员;记录日志;
    3. 其他异常
      • 原因:未预期的异常
      • 解决:同上

    解决:集中统一处理项目中出现的异常(异常处理器

    @RestControllerAdvice
    作用:为Rest风格开发的控制器类做增强
    .
    @ExceptionHandler
    作用:位于方法上方,设置指定异常处理方案,出现异常后终止原始控制器,转入当前方法执行。

    package com.it.controller;
    
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class ProjectExceptionAdvice {
        @ExceptionHandler(Exception.class)
        public Result doException(Exception e){
            System.out.println("出现异常");
            return new Result(500,"出错");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    步骤

    1. 自定义项目系统级异常
    2. 自定义业务级异常;
    3. 自定义异常编码;
    4. 触发自定义异常(模拟异常操作);
    5. 拦截异常并处理异常;
    6. 测试结果
    package com.it.controller;
    
    import lombok.Data;
    
    //自定义项目级异常
    @Data
    public class SystemException extends RuntimeException{
        private Integer code;
    
        public SystemException(String message, Throwable cause, Integer code) {
            super(message);
            this.code = code;
        }
        
        
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    package com.it.controller;
    
    import lombok.Data;
    
    //自定义项目业务级异常
    @Data
    public class BusinessException extends RuntimeException{
        private Integer code;
    
    
        public BusinessException(String message, Integer code) {
            super(message);
            this.code = code;
        }
        public BusinessException(String message, Throwable cause, Integer code) {
            super(message,cause);
            this.code = code;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    //异常编码
        public static final Integer SYSTEM_UNKNOW_ERROR = 50001;
        public static final Integer SYSTEM_TIMEOUT_ERROR = 50002;
        public static final Integer PROJECT_VALIDATE_ERROR = 60001;
        public static final Integer PROJECT_BUSINESS_ERROR = 60002;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    package com.it.service.impl;
    
    import com.it.controller.BusinessException;
    import com.it.controller.Code;
    import com.it.dao.UserDao;
    import com.it.domain.User;
    import com.it.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    
    @Service
    public class UserServiceImpl implements UserService {
        @Autowired //自动装配
        private UserDao userDao;
    
       
        //自定义异常
        public User selectById(Integer id) {
            if(id<0){
                throw new BusinessException("请输入正确的id",Code.PROJECT_BUSINESS_ERROR);
            }
            return userDao.selectById(id);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    package com.it.controller;
    
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.bind.annotation.RestControllerAdvice;
    
    //拦截并处理异常
    @RestControllerAdvice
    public class ProjectExceptionAdvice {
        @ExceptionHandler(Exception.class)
        public Result doException(Exception e){
            System.out.println("出现异常");
            return new Result(500,"出错");
        }
    
        @ExceptionHandler(BusinessException.class)
        public Result doBussinessException(Exception e){
            System.out.println("出现业务异常");
            return new Result(501,null,"出错");
        }
    
        @ExceptionHandler(SystemException.class)
        public Result doSystemException(Exception e){
            System.out.println("出现系统异常");
            return new Result(500,"出错");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    测试结果
    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    Vue路由嵌套详解
    掌握键盘快捷键,在没有鼠标的情况下,也还是可以做到游刃有余,甚至可以用数字键来代替鼠标
    在Linux终端中查找域名对应的IP地址
    java-net-php-python-ssm高校建党管理信息系统计算机毕业设计程序
    数千 npm 账号使用域名过期的邮箱,涉及 8494 个包
    搭建DNS服务器
    1. XAML简单的划分区域
    vuex状态管理(二)超级详细使用教程(包含辅助函数map的使用),一看就会,一学就懂
    FastAPI+Pydantic使用自定义参数校验+自定义异常+全局异常捕获
    Linux 内存管理 概述与深入理解
  • 原文地址:https://blog.csdn.net/meini32/article/details/132569931