zoukankan      html  css  js  c++  java
  • Spring Boot demo系列(二):简单三层架构Web应用

    2021.2.24 更新

    1 概述

    这是Spring Boot的第二个Demo,一个只有三层架构的极简Web应用,持久层使用的是MyBatis

    2 架构

    一个最简单的Spring Boot Web应用分为三层:

    • Controller层:负责具体业务流程的控制,调用Service层来控制业务逻辑
    • Service层:业务逻辑层,真正执行业务的操作,比如获取用户信息等
    • Dao层:负责数据持久化,在这一层中与各种数据库,比如MySQLOracle等打交道

    先来简单说一下三层所使用到的注解。

    2.1 Controller

    Controller层也是入口层,一般涉及如下注解:

    • @Controller@Controller是经典的Controller层注解,@Controller标识的类代表该类是控制器类
    • @RequestMapping:使用@RequestMapping可以对请求进行映射,可以注解在类上或者方法上,在类上的话表示该类所有的方法都是以该地址作为父地址,在方法上就表示可以映射对应的请求到该方法上
    • @GetMapping/@PostMapping:这两者实际上是@RequestMapping对应不同方法的简化版,因为@RequestMapping有一个method属性,如果该method指定为GET那么就相当于@GetMapping,如果指定为POST就相当于@PostMapping
    • @ResponseBody:作用在方法上,将返回的数据进行可能的转换(取决于请求头,转换为JSONXML等等,默认的情况下比如单纯字符串就直接返回),比如返回语句为return "success";,如果加上了@ResponseBody就直接返回success,如果不加上就会跳转到success.jsp页面
    • @RequestParm:处理Contrent-Typeapplication/x-www-form-urlencoded的内容,可以接受简单属性类型或者对象,支持GET+POST
    • @RequestBody:处理Content-Type不为application/x-www-form-urlencoded的内容(也就是需要指定Content-Type),不支持GET,只支持POST
    • @PathVariable:可以将占位符的参数传入方法参数,比如/path/1,可以将1传入方法参数中
    • @PathParm:与@RequestParm一样,一般使用@RequestParm
    • @RestController:相当于@Controller+@ResponseBody

    2.2 Service

    Service层用于执行主要的业务逻辑,主要就是下面这个注解:

    • @Serice:是一个增强型的@Component@Component表示一个最普通的组件,可以被注入到Spring容器进行管理,而@Service是专门用于处理业务逻辑的注解,@Controller类似,也是一个增强型的@Component,专门用于Controller层的处理

    2.3 Dao

    Dao是数据持久层,这里进行数据持久化的操作,一般加上@Repository即可:

    • @Repository:也是一个增强型的@Component,注解在持久层中,具有将具体数据库抛出的异常转为Spring持久层异常的功能

    讲完注解了下面就开始实践一下。

    3 实践

    3.1 新建项目

    选择如下依赖:

    在这里插入图片描述

    Lombok能简化代码,推荐使用,并且需要IDEA安装插件。ORM框架这里选择MyBatis

    3.2 新建包

    新建如下四个包:

    • controller
    • dao
    • entity
    • service
    • config

    在这里插入图片描述

    3.3 Controller

    3.3.1 简单Controller

    controller包下新建Controller.java

    @RestController
    @RequestMapping("/")
    public class Controller {
        @GetMapping("test")
        public String testMethod()
        {
            return "test controller";
        }
    }
    

    运行之后,如果出现如下错误:

    在这里插入图片描述

    这是因为没有配置数据源,可以先把MySQLMyBatis的依赖删去:

    在这里插入图片描述

    运行之后在浏览器输入localhost:8080/test会返回test controller

    在这里插入图片描述

    这样一个最简单的Controller就完成了。

    3.3.2 @RequestParm

    然后下一步是添加参数,可以考虑使用@RequestParm添加:

    @GetMapping("withParm")
    public String withParm(@RequestParam String id)
    {
        return "id:"+id;
    }
    

    这样直接访问localhost:8080/withParm是不行的,因为没有携带id参数:

    在这里插入图片描述

    加入参数即可,也就是localhost:8080/withParm?id=1

    在这里插入图片描述

    3.3.3 @PathVariable

    另一种添加参数的方式是使用@PathVariable

    @GetMapping("path1/{id}")
    public String path1(@PathVariable("id") String id)
    {
        return "id:"+id;
    }
    

    这样不是加入?id=xx,而是直接加入占位符,比如localhost:8080/path1/1

    在这里插入图片描述

    3.3.4 完整CURD

    这里是一个完整的CRUD示例:

    @RestController
    @RequestMapping("/")
    @CrossOrigin("http://localhost:3000")
    @RequiredArgsConstructor(onConstructor = @__(@Autowired))
    public class CRUDController {
        private final Service service;
    
        @PostMapping("save")
        public boolean save(@RequestBody User user)
        {
            return service.save(user);
        }
    
        @GetMapping("delete")
        public boolean delete(@RequestParam String id)
        {
            return service.delete(id);
        }
    
        @GetMapping("select")
        public User select(@RequestParam String id)
        {
            return service.select(id);
        }
    
        @GetMapping("selectAll")
        public List<User> selectAll()
        {
            return service.selectAll();
        }
    
    }
    

    注解基本上都在上面说过了,除了下面两个:

    • @RequiredArgsConstrutcor:这个是Lombok的注解,用来消除直接使用@Autowired出现的警告
    • @CrossOrgin:跨域注解,由于笔者使用Postwoman测试,默认运行端口为3000,因此需要加上该注解,使用Postman测试则不需要

    3.4 Service

    @org.springframework.stereotype.Service
    @RequiredArgsConstructor(onConstructor = @__(@Autowired))
    public class Service {
        private final UserMapper mapper;
    
        public boolean save(User user)
        {
            String id = user.getId();
            User currentUser = select(id);
            if(currentUser != null)
                return mapper.update(user) == 1;
            return mapper.insert(user) == 1;
        }
    
        public boolean delete(String id)
        {
            return mapper.deleteById(id) == 1;
        }
    
        public User select(String id)
        {
            return mapper.selectById(id);
        }
    
        public List<User> selectAll()
        {
            return mapper.selectAll();
        }
    }
    

    简单的CRUD,调用持久层的方法。

    3.5 Dao

    由于使用MyBatis,这里的Dao层只有一个Mapper

    @Mapper
    @Component
    public interface UserMapper{
        @Select("select * from user where id=#{id}")
        User selectById(@Param("id") String id);
    
        @Select("select * from user")
        List<User> selectAll();
    
        int insert(@Param("user") User user);
    
        int deleteById(@Param("id") String id);
    
        int update(@Param("user") User user);
    }
    

    selectsql直接写在了上面,剩下的sql语句写在了xml配置文件,另外@Mapper注解表示在编译后生成对应的接口实现类。

    3.6 实体类

    @Data
    @AllArgsConstructor
    public class User {
        private String id;
        private String username;
        private String password;
        @Override
        public String toString()
        {
            return "id:"+id+"
    "+"username"+username+"
    password"+password+"
    ";
        }
    }
    

    3.7 配置类

    @Configuration
    @MapperScan("com.example.demo.dao")
    public class MyBatisConfig {
    }
    
    • @Configuration:定义为配置类
    • @MapperScan@Mapper的扫描路径

    3.8 配置文件

    在这里插入图片描述

    配置文件常用的有properties以及yamlyaml格式更加简单,这里使用yaml格式:

    spring:
      datasource:
        url: jdbc:mysql://127.0.0.1:3306/test
        username: test
        password: test
    
    mybatis:
      configuration:
        map-underscore-to-camel-case: true
      mapper-locations: classpath:mappers/*.xml
    

    分别指定数据库链接,数据库用户名以及密码,还有下划线转驼峰命名以及mapper文件的位置。

    另外还需要创建UserMapper.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.example.demo.dao.UserMapper">
        <insert id="insert">
            INSERT INTO `user` (`id`,`username`,`password`)
            VALUES (#{user.id},#{user.username},#{user.password})
        </insert>
    
        <update id="update">
            UPDATE `user` set `username`=#{user.username} , `password`=#{user.password} where id=#{user.id}
        </update>
    
        <delete id="deleteById">
            DELETE FROM `user` WHERE `id` = #{id}
        </delete>
    </mapper>
    

    就单纯的sql语句。

    另外需要准备建表以及建用户的sql

    CREATE DATABASE IF NOT EXISTS test;
    
    CREATE USER IF NOT EXISTS 'test'@'localhost' IDENTIFIED BY 'test';
    
    GRANT ALL ON test.* to 'test'@'localhost';
    
    USE test;
    
    CREATE TABLE user
    (
        id char(10) primary key ,
        username varchar (30) not null,
        password varchar (30) not null
    );
    

    测试数据:

    USE test;
    INSERT INTO user(id,username,password) values ('1','username1','password1'),('2','username2','password2');
    

    最终配置文件如下:

    在这里插入图片描述

    4 其他准备

    4.1 建库建表建用户

    直接执行上面的脚本即可。

    4.2 开启服务

    使用相应命令开启数据库服务。

    5 测试

    5.1 单元测试

    修改一下自带的测试类即可:

    @SpringBootTest
    @RequiredArgsConstructor(onConstructor = @__(@Autowired))
    class DemoApplicationTests {
    
        private final Service service;
    
        @Test
        void contextLoads() {
        }
    
        @Test
        void select()
        {
            System.out.println(service.select("1"));
        }
    
        @Test
        void selectAll()
        {
            service.selectAll().forEach(System.out::println);
        }
    
    //    @Test
    //    void delete()
    //    {
    //        service.delete("3");
    //    }
    
        @Test
        void save()
        {
            service.save(new User("3","username3","password3"));
        }
    }
    

    在这里插入图片描述

    直接点击左边的按钮即可运行,测试通过图如下:

    在这里插入图片描述

    5.2 浏览器测试

    由于没有做前端,这里就使用Postwoman模拟前端测试:

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    6 源码

    Java版:

    Kotlin版:

    7 参考

  • 相关阅读:
    vmware:使用.zip文件在vmware中安装操作系统
    Nodejs:Node.js模块机制小结
    vue:vue router学习小结
    axios使用思路总结
    vuex:使用思路总结
    React的keepAlive路由缓存的一种实现思路
    Echarts的一些用法
    gojs去水印的方法
    平面坐标与经纬度坐标的相互转换
    HTML5 添加水印
  • 原文地址:https://www.cnblogs.com/6b7b5fc3/p/13621606.html
Copyright © 2011-2022 走看看