SSM后端整合(纯注解)

1 准备工作

  • 第一步:导包

    • <dependencies>
      ​
      <!--加入slf4j+logback日志包-->
              <dependency>
                  <!-- 日志核心包 -->
                  <groupId>ch.qos.logback</groupId>
                  <artifactId>logback-classic</artifactId>
                  <version>1.2.3</version>
              </dependency>
      ​
              <dependency>
                  <!-- 日志中保存有spring信息,如果不需要可不加 -->
                  <groupId>org.logback-extensions</groupId>
                  <artifactId>logback-ext-spring</artifactId>
                  <version>0.1.5</version>
              </dependency>
      ​
              <dependency>
                  <groupId>org.projectlombok</groupId>
                  <artifactId>lombok</artifactId>
                  <version>1.16.22</version>
              </dependency>
              <!--SLF4J转化包 可以打印spring框架的日志-->
              <dependency>
                  <groupId>org.slf4j</groupId>
                  <artifactId>jcl-over-slf4j</artifactId>
                  <version>1.7.25</version>
              </dependency>
      ​
      <!--Mybatis的依赖-->
              <dependency>
                  <!-- 这是mybatis核心包 -->
                  <groupId>org.mybatis</groupId>
                  <artifactId>mybatis</artifactId>
                  <version>3.5.7</version>
              </dependency>
      ​
              <!-- MyBatis第三方分页,如果添加了mybatisplus就把这个去掉 -->
              <dependency>
                  <groupId>com.github.pagehelper</groupId>
                  <artifactId>pagehelper</artifactId>
                  <version>5.2.1</version>
              </dependency>
      ​
      <!-- 数据库连接包 -->
              <dependency>
                  <!-- 数据库连接包 -->
                  <groupId>mysql</groupId>
                  <artifactId>mysql-connector-java</artifactId>
                  <version>8.0.32</version>
              </dependency>
      ​
              <dependency>
                  <!-- 这是数据库连接池包 -->
                  <groupId>com.alibaba</groupId>
                  <artifactId>druid</artifactId>
                  <version>1.2.16</version>
              </dependency>
      ​
      <!--测试包-->
              <dependency>
                  <!-- 普通测试包 -->
                  <groupId>junit</groupId>
                  <artifactId>junit</artifactId>
                  <version>4.13</version>
                  <scope>test</scope>
              </dependency>
      ​
              <dependency>
                  <!-- 这是spring整合junit测试包 -->
                  <groupId>org.springframework</groupId>
                  <artifactId>spring-test</artifactId>
                  <version>5.2.10.RELEASE</version>
                  <scope>test</scope>
              </dependency>
      ​
      <!--以下是spring的依赖-->
      ​
              <dependency>
                  <!-- 这是spring整合jdbc连接的包,包含context和core包 -->
                  <groupId>org.springframework</groupId>
                  <artifactId>spring-jdbc</artifactId>
                  <version>5.2.10.RELEASE</version>
              </dependency>
      ​
      <!-- 这是mybatis整合spring的包 -->
              <dependency>
                  <groupId>org.mybatis</groupId>
                  <artifactId>mybatis-spring</artifactId>
                  <version>1.3.0</version>
              </dependency>
      ​
      <!-- 以下是springMVC的依赖 -->
              <dependency>
                  <groupId>org.springframework</groupId>
                  <artifactId>spring-webmvc</artifactId>
                  <version>5.2.10.RELEASE</version>
              </dependency>
      ​
              <dependency>
                  <groupId>javax.servlet</groupId>
                  <artifactId>servlet-api</artifactId>
                  <version>2.5</version>
              </dependency>
      ​
              <dependency>
                  <groupId>com.fasterxml.jackson.core</groupId>
                  <artifactId>jackson-databind</artifactId>
                  <version>2.12.0</version>
              </dependency>
      </dependencies>

  • 第二步:(mybatis配置)jdbc.properties和JdbcConfig配置类和MybatisConfig配置类

    • jdbc.driver=com.mysql.cj.jdbc.Driver
      jdbc.url=jdbc:mysql://localhost:3306/user?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
      jdbc.username=root
      jdbc.password=123456

    • 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 ds = new DruidDataSource();
              ds.setDriverClassName(driver);
              ds.setUrl(url);
              ds.setUsername(username);
              ds.setPassword(password);
              return ds;
          }
      ​
          @Bean
          public DataSourceTransactionManager transactionManager(DataSource dataSource){
              DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
              transactionManager.setDataSource(dataSource);
              return transactionManager;
          }
      }

    • public class MybatisConfig {
      ​
          @Bean
          public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
              //快速定义工厂类
              SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
              //定义别名
              ssfb.setTypeAliasesPackage("com.gnozt.pojo");
              //将数据源放入工厂
              ssfb.setDataSource(dataSource);
              return ssfb;
          }
      ​
          @Bean
          //定义映射接口和映射文件,接口和文件必须在同一个包下,但是通常我们将文件放在resource下
          public MapperScannerConfigurer mapperScannerConfigurer(){
              MapperScannerConfigurer msc = new MapperScannerConfigurer();
              //读取映射文件
              msc.setBasePackage("com.gnozt.dao");
              return msc;
          }
      }

  • 第三步:(spring配置)SpringConfig配置类

    • @Configuration
      @ComponentScan({"com.gnozt.dao","com.gnozt.service"})
      @PropertySource("classpath:jdbc.properties")
      @Import({JdbcConfig.class, MybatisConfig.class})
      public class SpringConfig {
      }

  • 第四步:(springmvc配置)ServletConfig配置类和SpringMvcConfig配置类

    • 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[]{"/"};
          }
      }

    • @Configuration
      @ComponentScan("com.gnozt.controller")
      @EnableWebMvc
      public class SpringMvcConfig extends WebMvcConfiguration{
          @Override
          public void addResourceHandlers(ResourceHandlerRegistry registry){
              //对静态资源的放行,是以webapp目录为基础,如不需要可将此方法去掉,也不用继承类了
              registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
          }
      }

  • 第五步:pojo类准备

    • @Data
      @AllArgsConstructor
      @NoArgsConstructor
      public class User {
          private Integer id;
          private String username;
          private String password;
      }

2 功能操作

  • 第一步:编写UserMapper接口和UserMapper.xml映射文件

    • public interface UserMapper {
          //添加数据
          Integer addUser(User user);
          //查询所有
          List<User> selectAll();
          //通过id查询
          User selectById(Integer id);
          //动态修改数据
          Integer updateById(User user);
          //删除数据
          Integer deleteById(Integer id);
          //批量删除 (@Param("usernames")可以写在参数前面,指定数组名称)
          Integer deleteByIds(int[] ids);
      }

    • <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
      ​
      <!-- 映射的接口 -->
      <mapper namespace="com.gnozt.dao.UserMapper">
      ​
          <insert id="addUser">
              insert into t_user values(#{id},#{username},#{password});
          </insert>
      ​
          <select id="selectAll" resultType="com.gnozt.pojo.User">
              select * from t_user;
          </select>
      ​
          <select id="selectById" resultType="com.gnozt.pojo.User">
              select * from t_user where id=#{id};
          </select>
      ​
          <update id="updateById">
              update t_user
              <set>
                  <if test="username != null and username != ''">
                      username = #{username},
                  </if>
                  <if test="password != null and password != ''">
                      password = #{password}
                  </if>
              </set>
              where id = #{id}
          </update>
      ​
          <delete id="deleteById">
              delete from t_user where id = #{id};
          </delete>
      ​
          <!--
              mybatis会将数组参数,封装为一个Map集合
                  * 默认:array = 数组
                  * 使用 @Param注解改变map集合的默认key的名称
                  * item参数值要和定义的 #{} 中的变量相同,不然没办法循环遍历的元素
          -->
          <delete id="deleteByIds">
              delete from t_user where id in
                <foreach collection="array" item="id" separator="," open="(" close=")">
                    #{id}
                </foreach>
              ;
          </delete>
      </mapper>

  • 第二步:UserService接口和UserServiceImpl实现类

    • public interface UserService {
          //添加数据
          Boolean addUser(User user);
          //查询所有
          List<User> selectAll();
          //通过id查询
          User selectById(Integer id);
          //动态修改数据
          Boolean updateById(User user);
          //删除数据
          Boolean deleteById(Integer id);
          //批量删除 (@Param("usernames")可以写在参数前面,指定数组名称)
          Boolean deleteByIds(int[] ids);
      }

    • UserServiceImpl实现类

    • @Service
      public class UserServiceImpl implements UserService {
        
          @Resource
          private UserMapper userMapper;
        
          @Override
          public Boolean addUser(User user) {
              Integer integer = userMapper.addUser(user);
              if (integer>0){
                  return true;
              }
              return false;
          }
        
          @Override
          public List<User> selectAll() {
              return userMapper.selectAll();
          }
        
          @Override
          public User selectById(Integer id) {
              return userMapper.selectById(id);
          }
        
          @Override
          public Boolean updateById(User user) {
              Integer integer = userMapper.updateById(user);
              if (integer>0){
                  return true;
              }
              return false;
          }
        
          @Override
          public Boolean deleteById(Integer id) {
              Integer integer = userMapper.deleteById(id);
              if (integer>0){
                  return true;
              }
              return false;
          }
        
          @Override
          public Boolean deleteByIds(int[] ids) {
              Integer integer = userMapper.deleteByIds(ids);
              if (integer>0){
                  return true;
              }
              return false;
          }
      }

  • 第三步:UserController控制器

    • @RestController
      @RequestMapping("/users")
      public class UserController {
          @Resource
          private UserService userService;
        
          @PostMapping
          public boolean addUser(@RequestBody User user) {
              return userService.addUser(user);
          }
        
          @GetMapping
          public List<User> selectAll() {
              return userService.selectAll();
          }
        
          @GetMapping("/{id}")
          public User selectById(@PathVariable Integer id) {
              return userService.selectById(id);
          }
        
          @PutMapping
          public boolean updateById(@RequestBody User user) {
              return userService.updateById(user);
          }
        
          @DeleteMapping("/{id}")   //路径上的id跟形参中id连接 ----  形参中的id又与代码中的调用方法中的id连接
          public boolean deleteById(@PathVariable Integer id) {
              return userService.deleteById(id);
          }
        
          @DeleteMapping
          public boolean deleteByIds(@RequestParam int[] ids) {
              return userService.deleteByIds(ids);
          }
      }

  • 第四步:测试

    • 测试分为service层测试和controller层测试

      • service层测试用代码测试

      • controller层测试使用postman工具,按照请求路径和方式携带参数测试

  • service层测试

    • @RunWith(SpringJUnit4ClassRunner.class)
      @ContextConfiguration(classes = SpringConfig.class)
      public class Test02 {
        
          @Autowired
          private UserService userService;
        
          @Test
          public void addtest01() throws IOException {
        
              User user = new User();
              user.setUsername("武先生");
              user.setPassword("521");
        
              boolean insert = userService.addUser(user);
              System.out.println(insert);
          }
        
          @Test
          public void selectalltest() throws IOException {
              List<User> users = userService.selectAll();
              System.out.println(users);
          }
        
          @Test
          public void selectByIdtest() throws IOException {
              User user = userService.selectById(1);
              System.out.println(user);
          }
        
          @Test
          public void updateByIdtest() throws IOException {
              User user = new User();
              user.setId(10);
              user.setUsername("武先生");
              user.setPassword("666");
        
              boolean integer = userService.updateById(user);
              System.out.println(integer);
          }
        
          @Test
          public void deleteByIdtest() throws IOException {
              boolean integer = userService.deleteById(22);
              System.out.println(integer);
          }
        
          @Test
          public void deleteByIdstest() throws IOException {
              int[] ids = {20,21};
        
              boolean integer = userService.deleteByIds(ids);
              System.out.println(integer);
          }
      }

  • controller层测试

    • 查询所有

      •  

    • 根据id查询

      •  

    • 新增

      •  

    • 修改

      •  

    • 批量删除

      •  

         

    • 根据id删除

      •  

3 前后端交互格式

  • 第一步:定义与前端沟通好的增删改查成功或者失败的码值

    • 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 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 SYSTEM_ERR = 50001; //系统异常
           public static final Integer SYSTEM_NUKNOW_ERR = 59999; //系统未知异常
      ​
      }

  • 第二步:定义一个返回给前端统一格式的实体类

    • @Data
      @AllArgsConstructor  //所有参构造
      @NoArgsConstructor   //无参构造
      public class ResultMsg {
          private Integer code;
          private Object data;
          private String msg;
      }

  • 第三步:修改你的controller类增删改查的返回值

    • @RestController
      @RequestMapping("/users")
      public class UserController {
          @Resource
          private UserService userService;
      ​
          @PostMapping
          public ResultMsg addUser(@RequestBody User user) {
              Boolean flag = userService.addUser(user);
              Integer code = flag ? Code.SAVE_OK : Code.SAVE_ERR;
              String msg = flag ? "数据添加成功" : "数据添加失败";
              return new ResultMsg(code,flag,msg);
          }
      ​
          @GetMapping
          public ResultMsg selectAll() {
              List<User> users = userService.selectAll();
              Integer code = users != null ? Code.GET_OK : Code.GET_ERR;
              String msg = users != null ? "数据查询成功" : "数据查询失败";
              return new ResultMsg(code,users,msg);
          }
      ​
          @GetMapping("/{id}")
          public ResultMsg selectById(@PathVariable Integer id) {
              User user = userService.selectById(id);
              Integer code = user !=  null ? Code.GET_OK : Code.GET_ERR;
              String msg = user != null ? "数据查询成功" : "数据查询失败";
              return new ResultMsg(code,user,msg);
          }
      ​
          @PutMapping
          public ResultMsg updateById(@RequestBody User user) {
              Boolean flag = userService.updateById(user);
              Integer code = flag ? Code.UPDATE_OK : Code.UPDATE_ERR;
              String msg = flag ? "数据修改成功" : "数据修改失败";
              return new ResultMsg(code,flag,msg);
          }
      ​
          @DeleteMapping("/{id}")   //路径上的id跟形参中id连接 ----  形参中的id又与代码中的调用方法中的id连接
          public ResultMsg deleteById(@PathVariable Integer id) {
              Boolean flag = userService.deleteById(id);
              Integer code = flag ? Code.DELETE_OK : Code.DELETE_ERR;
              String msg = flag ? "数据删除成功" : "数据删除失败";
              return new ResultMsg(code,flag,msg);
          }
      ​
          @DeleteMapping
          public ResultMsg deleteByIds(@RequestParam int[] ids) {
              Boolean flag = userService.deleteByIds(ids);
              Integer code = flag ? Code.DELETE_OK : Code.DELETE_ERR;
              String msg = flag ? "数据删除成功" : "数据删除失败";
              return new ResultMsg(code,flag,msg);
          }
      }

4 异常处理

  • 项目异常分类

    • 业务异常

      • 指的是用户输入年龄等信息的时候,填写的不是整数,而是字符串等

    • 系统异常

      • 项目运行过程中可预计且无法避免的异常

        • 比如:你获取的数据为空,

    • 其他异常

      • 变成人员未预期到的异常

  • 处理方式

    • 业务异常

      • 提醒用户规范操作

    • 系统异常

      • 发送固定消息传递给用户,安抚用户(比如网络繁忙,请稍后等)

      • 发送特定消息给维护人员(暂时不做)

      • 记录日志(暂时不做)

    • 其他异常

      • 发送固定消息传递给用户,安抚用户(网络繁忙,请稍后等)

      • 发送特定的消息给编程人员,提醒维护,并且纳入前业务异常或者系统异常(暂时不做)

      • 记录日志(暂时不做)

  • 操作步骤:

    • 第一步:在controller包下编写异常统一处理类(因为只能由mvc扫描)

      • @RestController
        public class ExceptionAdvice {
            @ExceptionHandler(Exception.class)
            public ResultMsg doException(Exception ex){
        //         发生异常数据肯定为空,所以这里data直接写null就行
                 return new ResultMsg(Code.SYSTEM_NUKNOW_ERR,null,"网络繁忙,请稍后重试!");
             }
         }

    • 第二步:我们还可以自己定义异常类,比如业务异常BussiException和系统异常SystemException (定义方法都是一样的,如下一样,只在你认为异常的地方抛出不同的自定义异常类就可以了)

      • public class SystemException extends RuntimeException{
            private Integer code;
        ​
            public SystemException(Integer code) {
                this.code = code;
            }
        ​
            public SystemException(Integer code, String message) {
                super(message);
                this.code = code;
            }
        }

    • 第三步:定义完我们自己的异常类后,我们可以在我们自己认为哪里会出错的地方try{}catch{}抛出我们自己定义的异常,并给一个我们自己定义的异常编码,和异常信息

      • //Code.SYSTEM_ERR 是我们自己定义的异常编码类中的值,为50001
        try{
           int i = 1/0;
        }catch (Exception ex){
            throw new SystemException(Code.SYSTEM_ERR,"网络繁忙,请稍后!");
        }

    • 第四步:在统一异常处理类中,将我们定义的异常分离出来

    • @RestControllerAdvice
      public class ExceptionAdvice {
        
          //未知异常
          @ExceptionHandler(Exception.class)
          public ResultMsg doException(Exception ex){
      //         发生异常数据肯定为空,所以这里data直接写null就行
               return new ResultMsg(Code.SYSTEM_NUKNOW_ERR,null,"网络繁忙,请稍后重试!");
           }
      
           //系统异常,我们自己定义的
           @ExceptionHandler(SystemException.class)
           public ResultMsg doSystemException(SystemException ex){
               //获取抛出的我们自己定义的异常信息编码,和信息
               return new ResultMsg(ex.getCode(),null,ex.getMessage());
           }
       }

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值