• Spring - 3 ( 12000 字 Spring 入门级教程 )


    一:Spring Web MVC入门

    1.1 响应

    在我们前⾯的代码例子中,都已经设置了响应数据, Http 响应结果可以是数据, 也可以是静态页面,也可以针对响应设置状态码, Header 信息等.

    1.2 返回静态页面

    创建前端页面 index.html(注意路径)

    在这里插入图片描述

    1. html代码
    DOCTYPE html>
    <html lang="en">
    
    <head>
    <meta charset="UTF-8">
    <title>Index⻚⾯title>
    head>
    
    <body>
    Hello,Spring MVC,我是Index⻚⾯.
    body>
    
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    1. 后台代码:
    @RestController
    public class IndexController {
        @RequestMapping("/index")
        public Object index(){
    		//返回index.html
            return "/index.html";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    运行结果:http://127.0.0.1:8080/index

    在这里插入图片描述
    结果却发现, 页面未正确返回, http响应把 “/index.html” 当做了http响应正文的数据,那 Spring MVC 如何才能识别出来 index.html 是⼀个静态页面, 并进行返回呢?

    我们需要把 @RestController 改为 @Controller

    正确代码如下:

    @Controller
    public class IndexController {
        @RequestMapping("/index")
        public Object index(){
            return "/index.html";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    再次运行: http://127.0.0.1:8080/index

    在这里插入图片描述
    发现页面正确展示了

    @RestController 和 @Controller 有着什么样的关联和区别呢,咱们前⾯讲了MVC模式, 后端会返回视图, 这是早期时的概念

    在这里插入图片描述
    随着互联网的发展, 目前项目开发流行"前后端分离"模式, Java 主要是用来做后端项目的开发, 所以也就不再处理前端相关的内容了

    因此 MVC 的概念也逐渐发生了变化, View 不再返回视图, 而是返回显示视图时需要的数据.所以前⾯使⽤的 @RestController 其实是返回的数据.

    其实 @RestController = @Controller + @ResponseBody

    • @Controller : 定义⼀个控制器, Spring 框架启动时加载, 把这个对象交给Spring管理.
    • @ResponseBody : 定义返回的数据格式为非视图, 返回⼀个 text/html 信息

    所以如果想返回视图的话, 只需要用 @Controller 就可以了

    1.3 返回数据@ResponseBody

    我们上⾯讲到, @ResponseBody 表示返回数据.

    @Controller
    @ResponseBody
    public class IndexController {
        @RequestMapping("/index")
        public Object index(){
            return "/index.html";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    加上 @ResponseBody 注解, 该方法就会把 “/index.html” 当做⼀个数据返回给前端.

    运行:http://127.0.0.1:8080/index

    在这里插入图片描述
    @ResponseBody 既是类注解, ⼜是方法注解

    • 如果作用在类上, 表示该类的所有方法, 返回的都是数据,
    • 如果作用在方法上, 表示该方法返回的是数据.

    也就是说: 在类上添加 @ResponseBody 就相当于在所有的方法上添加了 @ResponseBody 注解.同样, 如果类上有 @RestController 注解时:表示所有的方法上添加了 @ResponseBody 注解

    如果⼀个类的方法里, 既有返回数据的, 又有返回页面的, 就把 @ResponseBody 注解添加到需要返回页面的方法上即可.

    @Controller
    public class IndexController {
        @RequestMapping("/index")
        public Object index(){
            return "/index.html";
        }
        @RequestMapping("/returnData")
        @ResponseBody
        public String returnData(){
            return "该⽅法返回数据";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    多个注解时, 没有先后顺序, 先写哪个都可以

    运行程序, 浏览器响应结果如下: http://127.0.0.1:8080/returnData

    在这里插入图片描述
    如果去掉 @ResponseBody 注解, 程序会报404错误,程序会认为需要返回的是视图, 根据内容去查找文件, 但是查询不到, 路径不存在, 报404

    在这里插入图片描述

    1.4 返回HTML代码片段

    后端返回数据时, 如果数据中有 HTML 代码, 也会被浏览器解析

    @RequestMapping("/returnHtml")
    @ResponseBody
    public String returnHtml() {
            return "

    Hello,HTML~

    "
    ; }
    • 1
    • 2
    • 3
    • 4
    • 5

    运行程序, 浏览器响应结果如下: http://127.0.0.1:8080/returnHtml

    在这里插入图片描述
    通过 Fiddler 观察响应结果, Content-Type 为 text/html

    在这里插入图片描述
    响应中的 Content-Type 常见取值有以下几种:

    • text/html : body 数据格式是 HTML
    • text/css : body 数据格式是 CSS
    • application/javascript : body 数据格式是 JavaScript
    • application/json : body 数据格式是 JSON

    1.5 返回JSON

    Spring MVC 也可以返回 JSON

    后端方法返回结果为对象:

    @RequestMapping("/returnJson")
    @ResponseBody
    public HashMap<String, String> returnJson() {
            HashMap<String, String> map = new HashMap<>();
            map.put("Java", "Java Value");
            map.put("MySQL", "MySQL Value");
            map.put("Redis", "Redis Value");
            return map;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    运行程序, 浏览器响应结果如下: http://127.0.0.1:8080/returnJson

    在这里插入图片描述
    过 Fiddler 观察响应结果, Content-Type 为 application/json

    在这里插入图片描述

    1.6 设置状态码

    Spring MVC 会根据我们方法的返回结果自动设置响应状态码, 程序员也可以手动指定状态码,状态码可以通过 Spring MVC 的内置对象 HttpServletResponse 提供的方法来进行设置

    @RequestMapping(value = "/setStatus")
    @ResponseBody
    public String setStatus(HttpServletResponse response) {
            response.setStatus(401);
            return "设置状态码成功";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    运行程序, 浏览器响应结果如下: http://127.0.0.1:8080/setStatus

    在这里插入图片描述
    通过 Fiddler 来观察设置的结果:

    在这里插入图片描述

    1.7 设置Header (了解)

    Http 响应报头也会向客户端传递⼀些附加信息,这些信息通过 @RequestMapping 注解的属性来实现

    先来看 @RequestMapping 的源码:

    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Mapping
    public @interface RequestMapping {
        String name() default "";
        @AliasFor("path")
        String[] value() default {};
        @AliasFor("value")
        String[] path() default {};
        RequestMethod[] method() default {};
        String[] params() default {};
        String[] headers() default {};
        String[] consumes() default {};
        String[] produces() default {};
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    1. value: 指定映射的URL
    2. method: 指定请求的 method 类型, 如GET, POST等
    3. consumes: 指定处理请求的 Content-Type,例如 application/json,text/html;
    4. produces: 指定返回的内容类型,仅当 request 请求头中的 Accept 类型中包含该指定类型才返回
    5. Params: 指定 request 中必须包含某些参数值时,才让该方法处理
    6. headers: 指定 request 中必须包含某些指定的 header 值,才能让该方法处理请求

    1.8 设置 Content-Type

    我们通过设置 produces 属性的值, 设置响应的报头 Content-Type

    @RequestMapping(value = "/returnJson2",produces = "application/json")
    @ResponseBody
    public String returnJson2() {
            return "{\"success\":true}";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    运行程序, 浏览器响应结果如下:http://127.0.0.1:8080/returnJson2

    在这里插入图片描述
    通过 Fiddler 来观察设置的结果:

    在这里插入图片描述
    如果不设置 produces , 方法返回结果为 String 时, Spring MVC 默认返回类型是 text/html.

    1.9 设置其他Header

    设置其他 Header 的话, 需要使⽤ Spring MVC 的内置对象 HttpServletResponse 提供的方法来进行设置

    @RequestMapping(value = "/setHeader")
    @ResponseBody
    public String setHeader(HttpServletResponse response) {
            response.setHeader("MyHeader","MyHeaderValue");
            return "设置Header成功";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    void setHeader(String name, String value) 设置⼀个带有给定的名称和值的 header. 如果 name已经存在, 则覆盖旧的值.

    运行程序, 浏览器响应结果如下: http://127.0.0.1:8080/setHeader

    在这里插入图片描述
    通过 Fiddler 来观察设置的结果:
    在这里插入图片描述

    二:综合性练习

    结合上述内容, 我们可以做⼀些小案例,主要掌握知识点:

    1. 理解前后端交互过程
    2. 接口传参, 数据返回, 以及页面展示

    2.1 加法计算器

    需求: 输入两个整数, 点击 “点击相加” 按钮, 显示计算结果

    在这里插入图片描述

    1. 创建 SpringBoot 项目: 引⼊ Spring Web 依赖, 把前端页面放在项目中

    在这里插入图片描述

    1. 约定前后端交互接口:

    首先进行需求分析:加法计算器功能, 对两个整数进行相加, 需要客户端提供参与计算的两个数, 服务端返回这两个整数计算的结果,基于以上分析, 我们来定义接口:

    接口定义:

    请求路径:calc/sum
    请求⽅式:GET/POST
    接⼝描述:计算两个整数相加
    
    • 1
    • 2
    • 3

    请求参数:

    参数名类型是否必须备注
    num1Integer参与计算的第⼀个数
    num2Integer参与计算的第⼆个数

    响应数据:

    Content-Type: text/html
    响应内容: 计算机计算结果: 8
    
    • 1
    • 2

    2.1.1 服务器代码

    @RestController
    @RequestMapping("/calc")
    public class CalcController {
        @RequestMapping("/sum")
        public String sum(Integer num1,Integer num2){
            Integer sum = num1+num2;
            return "

    计算机计算结果: "+sum+"

    "
    ; } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2.1.2 调整前端页面代码

    <form action="calc/sum" method="post">
        <h1>计算器h1>
        数字1:<input name="num1" type="text"><br>
        数字2:<input name="num2" type="text"><br>
        <input type="submit" value=" 点击相加">
    form>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.1.3 运行测试

    启动服务, 运行并测试
    在这里插入图片描述

    2.2 图书管理系统

    需求:

    1. 登录: 用户输⼊账号,密码完成登录功能
    2. 列表展示: 展示图书

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

    1. 准备工作

    创建新项目, 引入对应依赖, 把前端页面放在项目中

    1. 约定前后端交互接口

    需求分析:图书管理系统是⼀个相对较大一点的案例, 咱们先实现其中的⼀部分功能.

    • 用户登录

    在这里插入图片描述

    • 图书列表

    在这里插入图片描述

    根据需求可以得知, 后端需要提供两个接口

    1. 账号密码校验接口: 根据输入用户名和密码校验登录是否通过
    2. 图书列表: 提供图书列表信息

    接口定义:

    1. 登录接⼝
    [URL]
    POST /user/login
    [请求参数]
    name=admin&password=admin
    [响应]
    true //账号密码验证成功
    false//账号密码验证失败
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1. 图书列表展示
    [URL]
    POST /book/getList
    [请求参数][响应]
    返回图书列表
    [
    {
    "id": 1,
    "bookName": "活着",
    "author": "余华",
    "count": 270,
    "price": 20,
    "publish": "北京⽂艺出版社",
    "status": 1,
    "statusCN": "可借阅"
    },
    ...
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    1. 字段说明:
    参数名类型是否必须备注
    idInteger图书ID
    bookNameString图书名称
    authorString作者
    countInteger数量
    priceDouble定价
    publishString图书出版社
    statusInteger图书状态
    statusCNString图书状态中文含义

    2.2.1 服务器代码

    1. 创建图书类 BookInfo
    @Data
    public class BookInfo {
        //图书ID
        private Integer id;
        //书名
        private String bookName;
        //作者
        private String author;
        //数量
        private Integer count;
        //定价
        private BigDecimal price;
        //出版社
        private String publish;
        //状态 0-⽆效 1-允许借阅   2-不允许借阅
        private Integer status;
        private String statusCN;
        //创建时间
        private Date createTime;
        //更新时间
        private Date updateTime;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    1. 创建 UserController, 实现登录验证接口
    import org.springframework.util.StringUtils;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import javax.servlet.http.HttpSession;
    @RequestMapping("/user")
    @RestController
    public class UserController {
        @RequestMapping("/login")
        public boolean login(String name, String password, HttpSession session){
    		//账号或密码为空
            if (!StringUtils.hasLength(name) || !StringUtils.hasLength(password)){
                return false;
            }
    		//模拟验证数据, 账号密码正确
            if("admin".equals(name) && "admin".equals(password)){
                session.setAttribute("userName",name);
                return true;
            }
    		//账号密码错误
            return false;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    1. 创建 BookController, 获取图书列表
    @RequestMapping("/book")
    @RestController
    public class BookController {
        @RequestMapping("/getList")
        public List<BookInfo> getList(){
    		//获取数据
            List<BookInfo> books = mockData();
    		//处理⻚⾯展⽰
            for (BookInfo book:books){
                if (book.getStatus()==1){
                    book.setStatusCN("可借阅");
                }else {
                    book.setStatusCN("不可借阅");
                }
            }
            return books;
        }
    		/**
    		 * 数据Mock 获取图书信息
    		 *
    		 * @return
    		 */
    public List<BookInfo> mockData() {
        List<BookInfo> books = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            BookInfo book = new BookInfo();
            book.setId(i);
            book.setBookName("书籍" + i);
            book.setAuthor("作者" + i);
            book.setCount(i * 5 + 3);
            book.setPrice(new BigDecimal(new Random().nextInt(100)));
            book.setPublish("出版社" + i);
            book.setStatus(1);
            books.add(book);
        }
        return books;
    }
    
    }
    
    • 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

    在这个实例中数据采⽤ mock(假数据) 的方式, 实际数据应该从数据库中获取

    2.2.2 调整前端页面代码

    1. 登录页面:

    添加登录处理逻辑

    <script src="js/jquery.min.js"></script>
    <script>
        function login() {
            $.ajax({
                type: "post",
                url: "/user/login",
                data: {
                    name: $("#userName").val(),
                    password: $("#password").val()
                },
                success: function (result) {
                    if (result) {
                        location.href = "book_list.html";
                    } else {
                        alert("账号或密码不正确!");
                    }
                }
            });
        }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    1. 图书列表展示:

    删除前端伪造的代码, 从后端获取数据并渲染到页面上

    function getBookList() {
        $.ajax({
            type: "get",
            url: "/book/getList",
            success: function(result) {
                console.log(result);
                if (result != null) {
                    var finalHtml = "";
                    for (var book of result) {
                        finalHtml += '';
                        finalHtml += '';
                        finalHtml += '' + book.id + '';
                        finalHtml += '' + book.bookName + '';
                        finalHtml += '' + book.author + '';
                        finalHtml += '' + book.count + '';
                        finalHtml += '' + book.price + '';
                        finalHtml += '' + book.publish + '';
                        finalHtml += '' + book.statusCN + '';
                        finalHtml += '
    '; finalHtml += '+ book.id + '">Update'; finalHtml += '+ book.id + ')">Delete'; finalHtml += '
    '
    ; finalHtml += ''; } $("tbody").html(finalHtml); } } }); }
    • 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

    2.2.3 运行测试

    访问: http://127.0.0.1:8080/login.html

    输入账号密码: admin admin, 登录成功, 跳转到图书列表页,界⾯展示:

    在这里插入图片描述

    三:lombok

    3.1 lombok介绍

    Lombok 是⼀个 Java 工具库,通过添加注解的方式,简化 Java 的开发.

    下面来简单来学习下它的使用:

    1. 引入依赖
    <dependency>
    	<groupId>org.projectlombokgroupId>
    	<artifactId>lombokartifactId>
    	<optional>trueoptional>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 使用

    lombok通过⼀些注解的方式, 可以帮助我们消除⼀些冗长代码, 使代码看起来简洁⼀些,比如之前的 Person 对象 就可以改为

    @Data
    public class Person {
        private int id;
        private String name;
        private String password;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    @Data 注解会帮助我们⾃动⼀些方法, 包含 getter/setter, equals, toString 等

    1. 原理解释

    加了 @Data 注解之后, Idea 反编译的 class ⽂件,不是真正的字节码文件,而是 Idea 根据字节码进行反编译后的文件

    反编译是将可执行的程序代码转换为某种形式的高级编程语言, 使其具有更易读的格式. 反编译是⼀种逆向工程,它的作用与编译器的作用相反

    在这里插入图片描述
    在这里插入图片描述
    可以看出来, lombok 是⼀款在编译期生成代码的工具包.

    • Java 程序的运行原理:

    在这里插入图片描述

    • Lombok 的作用如下图所示:

    在这里插入图片描述
    4. 更多使用

    如果觉得 @Data 比较粗暴(生成方法太多), lombok 也提供了⼀些更精细粒度的注解

    注解作用
    @Getter自动添加 getter 方法
    @Setter自动添加 setter 方法
    @ToString自动添加 toString 方法
    @EqualsAndHashCode自动添加 equals 和 hashCode 方法
    @NoArgsConstructor自动添加无参构造方法
    @AllArgsConstructor自动添加全属性构造方法,顺序按照属性的定义顺序
    @NonNull属性不能为 null
    @RequiredArgsConstructor自动添加必需属性的构造方法,final + @NonNull 的属性为必需

    @Data = @Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor+@NoArgsConstructor

    3.2 更快捷的引入依赖

    上述引入 lombok 依赖, 需要去找 lombok 的坐标,接下来介绍更简单引入依赖的⽅式

    1. 安装插件 EditStarter, 重启 Idea

    在这里插入图片描述

    1. 在 pom.xml ⽂件中, 单击右键, 选择 Generate, 操作如下图所示

    在这里插入图片描述

    1. 进入 Edit Starters 的编辑界⾯, 添加对应依赖即可.

    在这里插入图片描述

    注意:不是所有依赖都可以在这里添加的, 这个界面和 SpringBoot 创建项目界⾯⼀样,依赖不在这里的, 还需要去 Maven 仓库查找坐标, 添加依赖.

    四: 应用分层

    通过上面的练习, 我们学习了 Spring MVC 简单功能的开发, 但是我们也发现了⼀些问题:目前我们程序的代码有点 “杂乱”, 然而当前只是 “⼀点点功能” 的开发. 如果我们把整个项目功能完成呢?代码会更加的 “杂乱无章”

    基于此, 咱们接下来学习应用分层.

    在这里插入图片描述

    阿里开发手册中, 关于工程结构部分, 定义了常见工程的应用分层结构:

    在这里插入图片描述

    • 那么什么是应用分层呢?

    应用分层是⼀种软件开发设计思想, 它将应用程序分成N个层次, 这N个层次分别负责各自的职责, 多个层次之间协同提供完整的功能,根据项目的复杂度, 把项目分成三层, 四层或者更多层

    • 为什么需要应用分层?

    在最开始的时候,为了让项目快速上线,我们通常是不考虑分层的.

    但是随着业务越来越复杂,大量的代码混在⼀起,会出现逻辑不清晰、各模块相互依赖、代码扩展性差、改动⼀处就牵⼀发而动全身等问题. 所以我们需要对应用进行分层

    • 如何分层(三层架构)

    咱们上⼀节中学习的 MVC, 就是把整体的系统分成了 Model(模型), View(视图)和Controller(控制器)三个层次

    也就是将用户视图和业务处理隔离开,并且通过控制器连接起来,很好地实现了表现和逻辑的解耦,是⼀种标准的软件分层架构。

    在这里插入图片描述

    目前现在更主流的开发方式是 “前后端分离” 的方式, 后端开发工程师不再需要关注前端的实现,

    所以对于Java后端开发者, ⼜有了⼀种新的分层架构: 把整体架构分为表现层、业务逻辑层和数据层. 这种分层⽅式也称之为"三层架构".

    1. 表现层: 就是展示数据结果和接受用户指令的,是最靠近用户的⼀层;
    2. 业务逻辑层: 负责处理业务逻辑, 里面有复杂业务的具体实现;
    3. 数据层: 负责存储和管理与应用程序相关的数据

    可以看到, 咱们前面的代码, 并不符合这种设计思想, 我们将所有的代码堆砌在⼀起

    在这里插入图片描述
    按照上面的层次划分, Spring MVC 站在后端开发人员的角度上, 也进行了支持, 把上面的代码划分为三个部分:

    • 请求处理、响应数据:负责,接收页面的请求,给页面响应数据.
    • 逻辑处理:负责业务逻辑处理的代码.
    • 数据访问:负责业务数据的维护操作,包括增、删、改、查等操作.

    这三个部分, 在Spring的实现中, 均有体现:

    在这里插入图片描述

    • Controller:控制层。接收前端发送的请求,对请求进行处理,并响应数据。
    • Service:业务逻辑层。处理具体的业务逻辑。
    • Dao:数据访问层,也称为持久层。负责数据访问操作,包括数据的增、删、改、查.

    4.1 MVC 和三层架构的区别和联系

    Spring MVC 是针对 Web 应用程序的一个具体框架,而三层架构是一种通用的软件架构模式,Spring MVC 是在表示层的基础上实现了 MVC 设计模式,而三层架构涵盖了整个应用程序,包括表示层、业务逻辑层和数据访问层。

    在这里插入图片描述

    4.2 代码重构

    我们使用上⾯的分层思想, 来对代码进行改造

    1. 先创建对应的包路径, 并把代码移到对应的目录

    在这里插入图片描述

    1. 控制层: 接收前端发送的请求,对请求进行处理,并响应数据
    package com.example.demo.controller;
    import com.example.demo.model.BookInfo;
    import com.example.demo.service.BookService;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import java.util.List;
    @RequestMapping("/book")
    @RestController
    public class BookController {
        @RequestMapping("/getList")
        public List<BookInfo> getList(){
            BookService bookService = new BookService();
    		//获取数据
            List<BookInfo> books = bookService.getBookList();
            return books;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    1. 业务逻辑层: 处理具体的业务逻辑。
    import com.example.demo.dao.BookDao;
    import com.example.demo.model.BookInfo;
    import java.util.List;
    public class BookService {
        public List<BookInfo> getBookList(){
            BookDao bookDao = new BookDao();
            List<BookInfo> books = bookDao.mockData();
            for (BookInfo book:books){
                if (book.getStatus()==1){
                    book.setStatusCN("可借阅");
                }else {
                    book.setStatusCN("不可借阅");
                }
            }
            return books;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    1. 数据访问层: 负责数据访问操作,包括数据的增、删、改、查
    import java.util.List;
    import java.util.Random;
    public class BookDao {
        /**
         * 数据Mock 获取图书信息
         * @return
         */
        public List<BookInfo> mockData(){
            List<BookInfo> books = new ArrayList<>();
            for (int i=0;i<5;i++){
                BookInfo book = new BookInfo();
                book.setId(i);
                book.setBookName("书籍"+i);
                book.setAuthor("作者"+i);
                book.setCount(i*5+3);
                book.setPrice(new BigDecimal(new Random().nextInt(100)));
                book.setPublish("出版社"+i);
                book.setStatus(1);
                books.add(book);
            }
            return books;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    4.3 应用分层的好处

    • 降低层与层之间的依赖, 结构更加的明确, 利于各层逻辑的复用
    • 开发人员可以只关注整个结构中的其中某⼀层, 极大地降低了维护成本和维护时间
    • 可以很容易的用新的实现来替换原有层次的实现
    • 有利于标准化

    4.4 5. 企业规范

    1. 类名使用大驼峰风格,但以下情形例外:DO/BO/DTO/VO/AO
    2. 方法名、参数名、成员变量、局部变量统⼀使用小驼峰风格
    3. 包名统⼀使⽤小写,点分隔符之间有且仅有⼀个自然语义的英语单词.

    常见命名命名风格介绍

    • 大驼峰: 所有单词首字⺟都需要大写, 又叫帕斯卡命名法, 比如: UserController
    • 小驼峰: 除了第⼀个单词,其他单词首字⺟大写,比如: userController
    • 蛇形: 用下划线(_)作⽤单词间的分隔符, ⼀般小写, 又叫下划线命名法, 比如: user_controller
    • 串形: 用短横线(-)作⽤单词间的分隔符, ⼜叫脊柱命名法,比如: user-controller
  • 相关阅读:
    面试官常问到的问题
    CSS层叠是什么意思?(v1)
    PDF文件格式(二):交叉引用类型“O“
    基于session实现发送短信和验证码登录注册功能
    【藏经阁一起读】(77)__《Apache Dubbo3 云原生升级与企业最佳实践》
    Android 全栈的进击之路
    magento2 跨域处理
    有关 ThreadLocal 的一切
    想要进行期权模拟?这里是最佳选择!
    代码随想录算法训练营第五十八天| 583. 两个字符串的删除操作 72. 编辑距离
  • 原文地址:https://blog.csdn.net/weixin_73232539/article/details/138088946