1. 课程介绍及环境准备

1.1 课程内容

Java EE企业级框架:SpringBoot + MyBatisPlus

Web前端核心框架:Vue + ElementUI

公共云部署:前后端项目集成打包和部署

1.2 目标

掌握JavaEE企业级开发框架的使用,能够利用SpringBoot开发Web应用

掌握Web前端开发框架Vue的使用,能够完成前后端分离开发

掌握云端环境的配置与使用,能够完成前后端程序的打包部署

1.3 Web应用概述

市面上的软件主要分为两种架构模式:

  • B/S(Browser/Server,浏览器/服务器架构)

    B/S架构的主要特点是分散性高、维护方便、开发简单、共享性高、总拥有成本低。

    在B/S架构下,客户端只需要浏览器,应用程序的逻辑和数据都存储在服务器端,浏览器只需要请求服务器,获取Web页面,并把Web页面展示给用户即可。

  • C/S(Client/Server,客户端/服务器架构)、

    C/S架构的主要特点是交互性强,具有安全访问模式,网络流量低,响应速度快,客户端负责大多数业务逻辑和UI演示。C/S架构软件需要针对不同的操作系统开发不同版本的软件。

1.4 开发环境配置

Java环境配置

1)下载JDK8安装包:

https://www.oracle.com/java/technologies/downloads/#java8-windows

2)安装JDK8

双击下载好的JDK,按照提示进行默认安装即可,注意安装路径不能出现中文或空格

3)配置系统环境变量

系统环境变量新增JAVA_HOME变量,填入JDK8安装路径

系统环境变量Path变量新增——%JAVA_HOME%\bin

系统环境变量Path变量新增——%JAVA_HOME%\jre\bin

4)测试

java -version

javac

Maven

Maven是一个项目管理工具,可以对Java项目进行自动化的构建和依赖管理

1)下载Maven:https://maven.apache.org/download.cgi

2)将压缩包解压到任意目录,注意路径不能出现中文

3)配置系统环境变量

系统环境变量新增MAVEN_HOME变量,填入Maven解压路径

系统环境变量Path变量新增——%MAVEN_HOME%\bin

4)测试:

mvn -v

5)运行Maven时,Maven所需任何构件都是直接从本地仓库获取的,如果本地仓库没有,则会尝试从远处仓库下载构建到本地仓库,进行本地仓库配置:修改maven安装包中的conf/settings.xml文件,指定本地仓库位置和镜像仓库

<localRepository>D:/.m2/repository</localRepository>

<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>

IDEA开发工具

1)下载IDEA工具:

https://www.jetbrains.com/idea/download/#section=windows

建议下载免费使用的社区版,避免商业版权纠纷

2)配置JDK

新建Maven项目时,选择前面安装的JDK8

3)配置Maven

打开设置 File | Settings | Build, Execution, Deployment | Build Tools | Maven,配置

  • Maven home path —— 前面Maven解压的路径
  • User settings file —— 前面Maven配置的settings.xml文件路径

2. SpringBoot快速上手

2.1 SpringBoot介绍

Spring Boot是由Pivotal团队提供的基于Spring的全新框架,旨在简化Spring应用的初始搭建和开发过程;

Spring Boot是所有基于Spring开发项目的起点;

Spring Boot尽可能地简化应用开发的门槛,让应用开发、测试、部署变得更加简单。

Spring Boot的特点:

  • 遵循“约定优于配置”的原则,只需要很少的配置或使用默认的配置
  • 能够使用内嵌的Tomcat、Jetty服务器,不需要部署war文件
  • 提供定制化的启动器Starters,简化Maven配置,开箱即用
  • 纯Java配置,没有代码生成,也不需要XML配置
  • 提供了生产级的服务监控方案,如安全监控、应用监控、健康检测等

2.2 快速创建SpringBoot应用

1)利用IDEA提供的Spring Initializr创建SpringBoot应用

  • Group: 一般填公司域名,Artifact:项目名称
  • 注意选择 Language 为 Java、 Type 为 Maven、JDK 为1.8、Java为8、Packaging 为 Jar
  • 勾选Web -> Spring Web
  • 创建后,检查项目的Maven配置

2)第1个helloworld程序

  • /helloworld/src/main/java/com/xiongbinzou/helloworld/下创建controller包

  • 在目录controller中,创建HelloController.java文件,内容如下:

    package com.xiongbinzou.helloworld.controller;

    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;

    @RestController
    public class HelloController {

    @GetMapping("/hello")
    public String Hello() {
    return "Hello World";
    }
    }

3)启动项目,在浏览器输入"http://localhost:8080/hello"

2.3 开发环境热部署

热部署应用背景:

  • 在实际项目开发调试过程中,会频繁地修改后台类文件,导致需要重新编译、重新启动,整个过程效率低下
  • Spring Boot提供了spring-boot-devtools组件,使得无需手动重启Spring Boot应用即可重新编译、启动项目,大大缩短编译启动时间
  • devtools会监听classpath下的文件变动,触发Restart类加载器重新加载类,从而实现类文件和属性文件的热部署
  • 并不是所有的更改都需要重启应用(如静态文件,视图模板),可以通过设置spring.devtools.restart.exclude属性来指定一些文件或目录的修改不用重启应用

1)/helloworld/pom.xml中添加依赖

<dependencies>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>

2)在/helloworld/src/main/resources/application.properties添加配置

# 热部署生效
spring.devtools.restart.enabled=true
# 设置重启目录
spring.devtools.restart.additional-paths=src/main/java
# 设置classpath目录下的WEB-UBF文件内容修改不重启
spring.devtools.restart.exclude=static/**

3)打开 File | Settings | Build, Execution, Deployment | Compiler,勾选 Build project automatically

4)打开 File | Settings | Advanced Settings,勾选 Allow auto-make to start even if developed application is currently running

3. Web开发基础

3.1 启动器

  • Spirng Boot将传统Web开发的mvc、json、tomcat等框架整合,提供了spring-boot-starter-web组件,简化了web应用配置

  • 创建Spring Boot项目后勾选Spring Web选项后,会自动将spring-boot-starter-web组件加入到项目中

  • spring-boot-start-web启动器主要包括web、webmvc、json、tomcat等基础依赖组件,作用是提供Web开发场景需要的所有底层依赖

  • webmvc为Web开发的基础框架,json为JSON数据解析组件,tomcat为自带的容器依赖

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
......
</dependencies>

3.2 控制器

  • Spring Boot提供了@Controller和@RestController两种注解来标识此类负责接受和处理HTTP请求
  • 如果请求的是页面和数据,使用@Controller注解即可;如果只是请求数据,则可以使用@RestController注解

@Controller的用法:适合前后端不分离的模式

package com.xiongbinzou.helloworld.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController {

@RequestMapping("/hello")
public String index(ModelMap map) {
map.addAttribute("name", "xiongbinzou");
return "Hello";
}
}
  • 示例中返回了hello页面和name的数据,在前端页面中可以通过${name}参数获取后台返回的数据并展示
  • @Controller通常与Thymeleaf模板引擎结合使用

@RestController用法:适合前后端分离的模式

package com.xiongbinzou.helloworld.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

@RequestMapping("/user")
public User getUser() {
User user = new User();
user.setUsername("xiongbinzou");
user.setPassword("123");
return user;
}
}

  • 默认情况下,@RestController注解会将返回的对象数据转换为JSON格式

3.3 路由映射

  • @RequestMapping注解主要负责URL的路由映射,它可以添加在Controller类或具体的方法上

  • 如果添加在Controller类上,则这个Controller中的所有路由映射都将会加上此映射规则,如果添加到方法上,则只对当前方法生效

  • @RequestMapping注解包含很多属性参数来定义HTTP的请求映射规则,常用的属性参数如下:

    • value:请求URL的路径,支持URL模板、正则表达式
    • method:HTTP请求方法
    • consumes:请求的媒体类型(Content-Type),如application/json
    • produces:响应的媒体类型
    • params,headers:请求的参数及请求头的值
  • @RequestMapping的value属性用于匹配URL映射,value支持简单表达式@RequestMapping(“/user”)

  • @RequestMapping支持使用通配符匹配URL,用于统一映射某些URL规则类似的请求:

    如:@RequestMapping(“/getJson/*.json”),当在浏览器中请求/getJson/a.json或者/getJson/b.json时都会匹配到后台的Json方法

  • @RequestMapping的通配符匹配非常简单实用,支持*?**

    其中,*匹配任意字符,**匹配任意路径,?匹配单个字符

  • 有通配符的优先级低于没有通配符的优先级,如/user/add.jsonjson/*.json优先级高,有**通配符的优先级低于有*的优先级

    package com.xiongbinzou.helloworld.controller;

    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;

    @RestController
    public class HelloController {

    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public String Hello() {
    return "Hello World";
    }
    }

3.4 参数传递

  • @RequestParam将请求参数绑定到控制器的方法参数上,接收的参数来自HTTP请求体或请求url的QueryString,当请求的参数名称与Controller的业务方法参数名称一致时,@RequestParam可以省略

  • @PathVariable用来请求动态URL,URL的值可以作为控制器中处理方法的参数

  • @RequestBody接收的参数是来自requestBody中,即请求体,一般用于处理非Content-Type:application/x-www-form-urlencoded编码格式的数据

    比如:application/jsonapplication/xml等类型的数据

    /helloworld/src/main/java/com/xiongbinzou/helloworld/controller文件夹下新建ParamsController类,内容如下:

    package com.xiongbinzou.helloworld.controller;

    import org.springframework.web.bind.annotation.*;
    import com.xiongbinzou.helloworld.entity.User;

    @RestController
    public class ParamsController {

    @RequestMapping(value = "/getTest1", method = RequestMethod.GET)
    public String getTest1() {
    return "GET请求";
    }

    @RequestMapping(value="/getTest2", method = RequestMethod.GET)
    public String getTest2(String nickname, String phone) {
    System.out.println("nickname:" + nickname);
    System.out.println("phone:" + phone);
    return "GET请求";
    }

    @RequestMapping(value = "/getTest3", method = RequestMethod.GET)
    public String getTest3(@RequestParam(value="nickname", required = false) String name) {
    System.out.println("nickname:" + name);
    return "GET请求";
    }

    @RequestMapping(value = "/postTest1", method = RequestMethod.POST)
    public String postTest1() {
    return "POST请求";
    }

    @RequestMapping(value = "/postTest2", method = RequestMethod.POST)
    public String postTest2(String username, String password) {
    System.out.println("username:" + username);
    System.out.println("password:" + password);
    return "POST请求";
    }

    @RequestMapping(value = "/postTest3", method = RequestMethod.POST)
    public String postTest3(User user) {
    System.out.println(user);
    return "POST请求";
    }

    @RequestMapping(value = "/postTest4", method = RequestMethod.POST)
    public String postTest4(@RequestBody User user) {
    System.out.println(user);
    return "POST请求";
    }

    @GetMapping("/test/**")
    public String test() {
    return "通配符请求";
    }
    }

4. Web开发进阶

4.1 静态资源访问

  • 使用IDEA创建Spring Boot项目,会默认创建出classpath:/static/目录,静态资源一般放在这个目录下即可

  • 如果默认的静态资源过滤策略不能满足开发需求,也可自定义静态资源过滤策略

  • 在/helloworld/src/main/resources/application.properties中直接定义过滤规则和静态资源位置:

    # 设置静态资源的url访问路径
    spring.mvc.static-path-pattern=/images/**
    # 设置静态资源的存放路径
    spring.web.resources.static-locations=classpath:/static
  • 过滤规则为/static/**,静态资源位置为classpath:/static/

    注:一般使用默认设定即可,不需要再设置

4.2 文件上传

  • 表单的enctype属性规定在发送到服务器之前应该如何对表单数据进行编码

  • 当表单的enctype=“application/x-www-form-urlencoded”(默认)时,form表单中的数据格式为:key=value&key=value

  • 当表单的enctype="multipart/form-data"时,其传输数据形式如下:

  • Spring Boot工程嵌入的tomcat限制了请求的文件大小,每个文件的配置最大为1MB,单次请求的文件的总数不能大于10MB,更改这个默认设定,需要在/helloworld/src/main/resources/application.properties配置文件中加入两个配置:

    # 设置请求文件大小
    spring.servlet.multipart.max-file-size=10MB
    # 设置单次请求文件的总大小
    spring.servlet.multipart.max-request-size=10MB
  • 当表单为enctype="multipart/form-data"时,可以使用MultipartFile获取上传的文件数据,再通过transferTo方法将其写入到磁盘中

    /hellowworld/src/main/java/com/xiongbinzou/helloworld/controller文件夹下新建FileUploadController类,内容如下:

    package com.xiongbinzou.helloworld.controller;

    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.multipart.MultipartFile;

    import javax.servlet.http.HttpServletRequest;
    import java.io.File;
    import java.io.IOException;

    @RestController
    public class FileUploadController {

    @PostMapping("/upload")
    public String upload(String nickname, MultipartFile photo, HttpServletRequest request) throws IOException {
    System.out.println(nickname);
    System.out.println("文件大小:" + photo.getSize());
    System.out.println("文件原始名称:" + photo.getOriginalFilename());
    System.out.println("文件类型:" + photo.getContentType());
    System.out.println(System.getProperty("user.dir"));

    String path = request.getServletContext().getRealPath("/upload/");
    System.out.println(path);
    saveFile(photo, path);
    return "上传成功";
    }

    public void saveFile(MultipartFile photo, String path) throws IOException {
    File upDir = new File(path);
    if (!upDir.exists()) {
    upDir.mkdir();
    }
    File file = new File(path+photo.getOriginalFilename());
    photo.transferTo(file);
    }
    }

4.3 拦截器

  • 拦截器在Web系统中非常常见,对于某些全局统一的操作,可以把它提取到拦截器中实现。拦截器有以下几种使用场景:

    1. 权限检查:如登录检测,进入处理程序检测是否登录,如果没有,则直接返回登录页面
    2. 性能检测:通过拦截器在进入处理程序之前记录开始时间,在处理完成之后记录结束时间,从而得到请求的处理时间
    3. 通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还要提取Locale、Theme等信息,只要是多个处理程序需要的,即可使用拦截器来实现
  • Spring Boot定义了HandlerInterceptor接口来实现自定义拦截器功能

  • HandlerInterceptor接口定义了preHandle、postHandle、afterCompletion三种方法,通过重写这三种方法实现请求前、请求后等操作

    /helloworld/src/main/java/com/xiongbinzou/helloworld/文件夹下新建interceptor包,并新建HandlerInterceptor类,内容如下:

    package com.xiongbinzou.helloworld.interceptor;

    import org.springframework.web.servlet.HandlerInterceptor;

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
    System.out.println("LoginInterceptor");
    return true;
    }
    }

  • addPathPatterns方法定义拦截器地址,添加的一个拦截器没有addPathPattern任何一个url,则默认拦截所有请求

  • excludePathPatterns定义排除某些地址不被拦截,如果没有excludePathPatterns任何一个请求,则默认不放过任何一个请求

    /helloworld/src/main/java/com/xiongbinzou/helloworld/文件夹下新建config包,并新建WebConfig类,内容如下:

    package com.xiongbinzou.helloworld.config;

    import com.xiongbinzou.helloworld.interceptor.LoginInterceptor;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

    @Configuration
    public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/user/**");
    }

    }

5. RESTful服务和Swagger

5.1 RESTful介绍

  • RESTful是目前流行的互联网软件服务架构设计风格
  • REST(表达性状态转移,Representational State Transfer)是由Roy Thomas Fielding在2000年的博士论文中提出,它定义了互联网软件服务的架构原则,如果一个架构符合REST原则,则称之为RESTful架构
  • REST并不是一个标准,它更像一组客户端和服务端交互时的架构理念和设计原则,基于这种架构理念和设计原则的Web API更加简洁,更有层次

RESTful的特点

  • 每一种URI代表一种资源

  • 客户端使用GET、POST、PUT、DELETE四种表示操作方法的动词对服务资源进行操作:

    GET —— 用于获取资源

    POST —— 用于新建资源(也可用于更新资源)

    PUT —— 用于更新资源

    DELETE —— 用于删除资源

  • 通过操作资源的表现形式来实现服务端的请求操作

  • 资源的表现形式是JSON或者HTML

  • 客户端与服务器之间的交互在请求之间是无状态的,从客户端到服务端的每个请求都包含必需的信息

符合RESTful规范的Web API需要具备两个关键特性

  • 安全性:安全的方法被期望不会产生任何副作用,当使用GET操作获取资源时,不会引起资源本身的改变,也不会引起服务器状态的改变
  • 幂等性:幂等的方法保证了重复一个请求和一次请求的效果相同(并不是指响应总是相同,而是指服务器上资源的状态从第一次请求后就不再改变了),在数学上幂等性指N次变换和1次变换相同

HTTP Method

  • HTTP提供了POST、GET、PUT、DELETE等操作类型对某个Web资源进行Create、Read、Update和Delete操作
  • 一个HTTP请求处理利用URI标志目标资源之外,还需要通过HTTP Method指定对资源的操作类型,一些常见的HTTP方法及其在RESTful风格下的使用:
HTTP方法操作返回值特定返回值
POSTCreate201(Created),提交或保存资源404(Not Found),409(Conflict)资源已存在
GETRead200(OK),获取资源或数据列表,支持分页、排序和条件查询200(OK)返回资源,404(Not Found)资源不存在
PUTUpdate200(OK)或 204(No Content),修改资源404(Not Found)资源不存在,405(Method Not Allowed)禁止使用方法调用
PATCHUpadte200(OK)或 204(No Content),修改资源404(Not Found)资源不存在
DELETEDelete200(OK),资源删除成功404(Not Found)资源不存在,405(Method Not Allowed)禁止使用方法调用

HTTP状态码

  • HTTP状态码时服务向用户返回的状态码和提示信息,客户端的每一次请求,服务都必须给出回应,回应包括HTTP状态码和数据两部分
  • HTTP定义了40个标准状态码,可用于传达客户端请求的结果,状态码分为以下5个类别:
    • 1xx:信息,通信传输协议级信息
    • 2xx:成功,表示客户端的请求已经成功接受
    • 3xx:重定向,表示客户端必须执行一些其他操作才能完成其请求
    • 4xx:客户端错误,此类错误状态码指向客户端
    • 5xx:服务器操作,服务器负责这些错误状态码
HTTP状态码返回值HTTP Method特定返回值
200OKGET服务器成功返回用户请求的数据,该操作时幂等性的
201CreatedPOST/PUT/PATCH用户创建或修改数据成功
202Accepted*表示一个请求已经进入后台排队(异步任务)
204NO CONTENTDELETE用户删除数据成功
400INVALID REQUESTPOST/PUT/PATCH用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作时幂等的
401Unauthorized*表示用户没有权限(令牌、用户名、密码错误)
403Forbidden*表示用户得到授权(与401相对),但是访问是被禁止的
404NOT FOUND*用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的
406Not AcceptableGET用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)
410GoneGET用户请求的资源被永久删除,且不会再得到
422Unprocessable entityPOST/PUT/P{Atch}当创建一个对象时,发生一个验证错误
500INTERNAL SERVER ERROR*服务器发生错误,用户将无法判断发出的请求是否成功

5.2 构建RESTful应用接口

  • Spring Boot提供了spring-boot-starter-web组件完全支持开发RESTful API,提供了与REST操作方法对于的注解:

    @GetMapping:处理GET请求,获取资源

    @PostMapping:处理POST请求,新增资源

    @PutMapping:处理PUT请求,更新资源

    @DeleteMapping:处理DELETE请求,删除资源

    @PatchMapping:处理PATCH请求,部分更新资源

  • 在RESTful架构中,每个网址代表一种资源,所有URL中建议不用包含动词,只包含名词即可,而且所用的名词往往与数据库的表格名对应

    用户管理模块API示例:

    HTTP Method接口地址接口说明
    POST/user创建用户
    GET/user/id根据id获取用户信息
    PUT/user更新用户
    DELETE/user/id根据id删除用户信息

    /helloworld/src/main/java/com/xiongbinzou/helloworld/controller文件夹下新建UserController类,内容如下:

    package com.xiongbinzou.helloworld.controller;

    import com.xiongbinzou.helloworld.entity.User;
    import org.springframework.web.bind.annotation.*;

    @RestController
    public class UserController {
    @GetMapping("/user/{id}")
    public String getUserById(@PathVariable int id) {
    return "根据ID获取用户";
    }

    @PostMapping("/user")
    public String save(User user) {
    return "添加用户";
    }

    @PutMapping("/user")
    public String update(User user) {
    return "更新用户";
    }

    @DeleteMapping("/user/{id}")
    public String deleteById(@PathVariable int id) {
    return "根据ID删除用户";
    }
    }

5.3 使用Swagger生成Web API文档

Swagger介绍

  • Swagger是一个规范和完整的框架,用于生成、描述、调用和可视化RESTful风格的Web服务,是非常流行的API表达工具
  • Swagger能够自动生成完善的RESTful API文档,同时并根据后台代码的修改同步更新,并提供完整的测试页面来调试API

配置Swagger

  • 在Spring boot项目的/helloworld/pom.xml文件引入springfox-swagger2和springfox-swagger-ui依赖:

    <dependencies>
    ......
    <dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
    </dependency>
    <dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
    </dependency>
    </dependencies>
  • Spring Boot 2.6.x后与Swagger有版本冲突问题,需要在/helloworld/src/main/resources/application.properties配置文件中加入以下配置:

    spring.mvc.pathmatch.matching-strategy=ant_path_matcher
  • /helloworld/src/main/java/com/xiongbinzou/helloworld/config文件夹下新建Swagger2Config类,内容如下:

    package com.xiongbinzou.helloworld.config;

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import springfox.documentation.builders.ApiInfoBuilder;
    import springfox.documentation.builders.PathSelectors;
    import springfox.documentation.builders.RequestHandlerSelectors;
    import springfox.documentation.service.ApiInfo;
    import springfox.documentation.spi.DocumentationType;
    import springfox.documentation.spring.web.plugins.Docket;
    import springfox.documentation.swagger2.annotations.EnableSwagger2;

    @Configuration
    @EnableSwagger2
    public class Swagger2Config {
    @Bean
    public Docket createRestApi() {
    return new Docket(DocumentationType.SWAGGER_2)
    .apiInfo(apiInfo())
    .select()
    .apis(RequestHandlerSelectors.basePackage("com"))
    .paths(PathSelectors.any())
    .build();
    }

    public ApiInfo apiInfo() {
    return new ApiInfoBuilder()
    .title("演示项目API")
    .description("演示项目")
    .version("1.0")
    .build();
    }
    }

  • 使用@ApiOperation()修改/helloworld/src/main/java/com/xiongbinzou/helloworld/controller/UserController类,添加接口注解

    package com.xiongbinzou.helloworld.controller;

    import com.xiongbinzou.helloworld.entity.User;
    import io.swagger.annotations.ApiOperation;
    import org.springframework.web.bind.annotation.*;

    @RestController
    public class UserController {

    @ApiOperation("获取用户")
    @GetMapping("/user/{id}")
    public String getUserById(@PathVariable int id) {
    return "根据ID获取用户";
    }

    @ApiOperation("添加用户")
    @PostMapping("/user")
    public String save(User user) {
    return "添加用户";
    }

    @ApiOperation("更新用户")
    @PutMapping("/user")
    public String update(User user) {
    return "更新用户";
    }

    @ApiOperation("删除用户")
    @DeleteMapping("/user/{id}")
    public String deleteById(@PathVariable int id) {
    return "根据ID删除用户";
    }
    }
  • 访问 http://localhost:8080/swagger-ui.html 即可得到接口可视化文档

6. Mybatis-Plus快速上手

Mybatis-Plus的官方网址:https://baomidou.com/

6.1 ORM介绍

  • ORM(对象关系映射,Object Relational Mapping)是为了解决面向对象与关系数据库存在的互不匹配的一种技术
  • ORM通过使用描述对象和数据库之间映射的元数据将程序中的对象自动持久化到关系数据库中
  • ORM框架的本质是简化编程操作中操作数据库的编码

6.2 Mybatis-Plus介绍

  • MyBatis是一款优秀的数据持久层ORM框架,被广泛应用于应用系统中

  • MyBatis能够非常灵活地实现动态SQL,可以使用XML或注解来配置和映射原生信息,能够轻松地将Java的POJO(Plain Ordinary Java Object,普通的Java对象)与数据库中的表和字段进行映射关联

  • MyBatis-Plus是一个Mybatis的增强工具,在MyBatis的基础上做了增强,简化了开发

  • Mybatis CURD注解

    注解功能
    @Insert实现插入
    @Update实现更新
    @Delete实现删除
    @Select实现查询
    @Result实现结果封装
    @Results可以与@Result一起,封装多个结果
    @One实现一对一结果集封装
    @Many实现一对多结果集封装

示例:

按照前面的教程配置热部署和Swagger

0)准备数据库,(可参考教程:https://blog.csdn.net/rbx508780/article/details/127176754安装mysql软件),账户为root,密码设置为123456,端口为3306,成功登录后,执行下面SQL语句生成数据库mydb和t_user表:

create database if not exists mydb default CHARACTER set utf8 collate utf8_general_ci;
use mydb;
create table if not exists t_user (
id int not null auto_increment primary key comment "用户编号",
username varchar(20) comment "用户名",
password varchar(20) comment "用户密码",
birthday varchar(20) comment "用户生日"
) Engine=InnoDB DEFAULT CHARSET=utf8;
insert into t_user (id, username, password, birthday) values (1, "lucy", "123", "2018-12-12");
insert into t_user (id, username, password, birthday) values (2, "haohao", "123", "2019-12-12");

1) 创建一个新的Spring boot项目mybatisplusdemo,按照前面的教程配置热部署和Swagger,然后在/mybatisplusdemo/pom.xml文件引入mybatis-plus、mysql、druid依赖:

<dependencies>
......
<!-- MyBatis-Plus 依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<!-- mysql驱动依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!-- 数据连接池 druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.20</version>
</dependency>
</dependencies>

2)在/mybatisplusdemo/src/main/resources/application.properties添加数据库相关配置

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mydb?useSSL=false&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=123456
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

3)在/mybatisplusdemo/src/main/java/com/xiongbinzou/mybatisplusdemo/下创建entity包,在entity目录中创建User.java类文件,内容如下:

package com.xiongbinzou.mybatisplusdemo.entity;

import com.baomidou.mybatisplus.annotation.TableName;

@TableName("t_user")
public class User {
private int id;
private String username;
private String password;
private String birthday;

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public String getBirthday() {
return birthday;
}

public void setBirthday(String birthday) {
this.birthday = birthday;
}

@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", birthday='" + birthday + '\'' +
'}';
}
}

4)在/mybatisplusdemo/src/main/java/com/xiongbinzou/mybatisplusdemo/下创建mapper包,在mapper目录中创建UserMapper.java接口文件,内容如下:

package com.xiongbinzou.mybatisplusdemo.mapper;

import com.xiongbinzou.mybatisplusdemo.entity.User;
import org.apache.ibatis.annotations.*;

import java.util.List;

@Mapper
public interface UserMapper {
@Insert("insert into user values (#{id},#{username},#{password},#{birthday})")
int add(User user);

@Update("update user set username=#{username},password=#{password},birthday=#{birthday} where id=#{id}")
int update(User user);

@Delete("delete form user where id=#{id}")
int delete(int id);

@Select("select * from user where id=#{id}")
User findById(int id);

@Select("select * from user")
List<User> queryAll();
}

5)在/mybatisplusdemo/src/main/java/com/xiongbinzou/mybatisplusdemo/下创建controller包,在controller目录中创建UserController.java类文件,内容如下:

package com.xiongbinzou.mybatisplusdemo.controller;

import com.xiongbinzou.mybatisplusdemo.entity.User;
import com.xiongbinzou.mybatisplusdemo.mapper.UserMapper;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
public class UserController {
@Autowired
private UserMapper userMapper;

@ApiOperation("创建用户")
@PutMapping("/user")
public String create(User user) {
int i = userMapper.add(user);
if (i > 0) {
return "插入成功";
} else {
return "插入失败";
}
}

@ApiOperation("更新用户")
@PostMapping("/user")
public String update(User user) {
int i = userMapper.update(user);
if (i > 0) {
return "更新成功";
} else {
return "更新失败";
}
}

@ApiOperation("根据id删除用户")
@DeleteMapping("/user/{id}")
public String delete(int id) {
int i = userMapper.delete(id);
if (i > 0) {
return "删除成功";
} else {
return "删除失败";
}
}

@ApiOperation("根据id查找用户")
@GetMapping("/user/{id}")
public User findById(int id) {
User user = userMapper.findById(id);
System.out.println(user);
return user;
}

@ApiOperation("获取所有用户")
@GetMapping("/user")
public List queryAll() {
List<User> list = userMapper.queryAll();
System.out.println(list);
return list;
}
}

6)通过访问 http://localhost:8080/user 测试

6.3 Mybatis-Plus CRUD操作

Mybatis-Plus极大简化了Mybatis的CRUD操作

1)修改/mybatisplusdemo/src/main/java/com/xiongbinzou/mybatisplusdemo/mapper/UserMapper.java接口文件,继承Mybatis-Plus的BaseMapper接口,内容如下:

package com.xiongbinzou.mybatisplusdemo.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xiongbinzou.mybatisplusdemo.entity.User;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper extends BaseMapper<User> {

}

Mybatis-Plus的BaseMapper接口会根据User类自动提供CRUD操作

2)修改/mybatisplusdemo/src/main/java/com/xiongbinzou/mybatisplusdemo/controller/UserController.java类文件,内容如下:

package com.xiongbinzou.mybatisplusdemo.controller;

import com.xiongbinzou.mybatisplusdemo.entity.User;
import com.xiongbinzou.mybatisplusdemo.mapper.UserMapper;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
public class UserController {
@Autowired
private UserMapper userMapper;

@ApiOperation("创建用户")
@PutMapping("/user")
public String create(User user) {
int i = userMapper.insert(user);
if (i > 0) {
return "插入成功";
} else {
return "插入失败";
}
}

@ApiOperation("更新用户")
@PostMapping("/user")
public String update(User user) {
int i = userMapper.updateById(user);
if (i > 0) {
return "更新成功";
} else {
return "更新失败";
}
}

@ApiOperation("根据id删除用户")
@DeleteMapping("/user/{id}")
public String delete(int id) {
int i = userMapper.deleteById(id);
if (i > 0) {
return "删除成功";
} else {
return "删除失败";
}
}

@ApiOperation("根据id查找用户")
@GetMapping("/user/{id}")
public User findById(int id) {
User user = userMapper.selectById(id);
System.out.println(user);
return user;
}

@ApiOperation("获取所有用户")
@GetMapping("/user")
public List<User> queryAll() {
List<User> list = userMapper.selectList(null);
System.out.println(list);
return list;
}
}

Mybatis-Plus提供了各种注解以应对不同的应用情况,详情请看:https://baomidou.com/pages/223848/#tablename

7. Mybatis-Plus复杂查询

7.1 多表查询

  • 实现复杂关系映射,可以使用@Results注解,@Result注解,@One注解,@Many注解组合完成复杂关系的配置
注解说明
@Results代替<resultMap>标签,该注解中可加入单个或多个@Result注解
@Result代替<id>标签和<Result>标签,@Result中可以使用以下属性:
- column:数据表的字段名称
-property:类中对应的属性名
-one:与@One注解配合,进行一对一的映射
-many:与@Many注解配合,进行一对多的映射
@One代替<assocation>标签,用于指定查询中返回的单一对象
通过select属性指定用于多表查询的方法
使用格式:@Result(column=“”,property=“”,one=@One(select=“”))
@Many代替<collection>标签,用于指定查询中返回的集合对象
使用格式:@Result(column=“”,property=“”,many=@Many(select=“”))

示例

0)准备数据库,执行下面SQL语句生成数据库mydb和t_order表:

create table if not exists t_order (
id int not null auto_increment primary key comment "订单编号",
order_time varchar(20) comment "订单时间",
total float comment "订单总价",
uid int comment "订单所属用户",
foreign key(uid) references t_user(id)
) Engine=InnoDB DEFAULT CHARSET=utf8;
insert into t_order (id, order_time, total, uid) values (1, "2018-12-12", "3000", 1);
insert into t_order (id, order_time, total, uid) values (2, "2018-12-12", "5000", 2);

1)在/mybatisplusdemo/src/main/java/com/xiongbinzou/mybatisplusdemo/entity/目录下创建Order.java类文件,添加orders字段及其方法,内容如下:

package com.xiongbinzou.mybatisplusdemo.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

@TableName("t_order")
public class Order {
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private String ordertime;
private Float total;

@TableField(exist = false)
private User user;

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getOrdertime() {
return ordertime;
}

public void setOrdertime(String ordertime) {
this.ordertime = ordertime;
}

public Float getTotal() {
return total;
}

public void setTotal(Float total) {
this.total = total;
}

public User getUser() {
return user;
}

public void setUser(User user) {
this.user = user;
}

@Override
public String toString() {
return "Order{" +
"id=" + id +
", ordertime='" + ordertime + '\'' +
", total=" + total +
", user=" + user +
'}';
}
}

2)修改/mybatisplusdemo/src/main/java/com/xiongbinzou/mybatisplusdemo/entity/User.java类文件,内容如下:

package com.xiongbinzou.mybatisplusdemo.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

import java.util.List;

@TableName("t_user")
public class User {
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private String username;
private String password;
private String birthday;
@TableField(exist = false)
private List<Order> orders;

public List<Order> getOrders() {
return orders;
}

public void setOrders(List<Order> orders) {
this.orders = orders;
}

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public String getBirthday() {
return birthday;
}

public void setBirthday(String birthday) {
this.birthday = birthday;
}

@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", birthday='" + birthday + '\'' +
", orders=" + orders +
'}';
}
}

3)修改/mybatisplusdemo/src/main/java/com/xiongbinzou/mybatisplusdemo/mapper/UserMapper.java接口文件,内容如下:

package com.xiongbinzou.mybatisplusdemo.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xiongbinzou.mybatisplusdemo.entity.User;
import org.apache.ibatis.annotations.*;

import java.util.List;

@Mapper
public interface UserMapper extends BaseMapper<User> {

@Select("select * from t_user where id = #{id}")
User selectById(int id);

@Select("select * from t_user")
@Results(
{
@Result(column = "id", property = "id"),
@Result(column = "username", property = "username"),
@Result(column = "password", property = "password"),
@Result(column = "birthday", property = "birthday"),
@Result(column = "id", property = "orders", javaType = List.class,
many = @Many(select = "com.xiongbinzou.mybatisplusdemo.mapper.OrderMapper.selectByUid")
)
}
)
List<User> selectAllUserAndOrders();
}

4)在/mybatisplusdemo/src/main/java/com/xiongbinzou/mybatisplusdemo/mapper目录下创建OrderMapper.java接口文件,内容如下:

package com.xiongbinzou.mybatisplusdemo.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xiongbinzou.mybatisplusdemo.entity.Order;
import com.xiongbinzou.mybatisplusdemo.entity.User;
import org.apache.ibatis.annotations.*;

import java.util.List;

@Mapper
public interface OrderMapper extends BaseMapper<Order> {

@Select("select * from t_order where uid=#{uid}")
List<Order> selectByUid(int uid);

@Select("select * from t_order")
@Results(
{
@Result(column = "id", property = "id"),
@Result(column = "order_time", property = "ordertime"),
@Result(column = "total", property = "total"),
@Result(column = "uid", property = "user", javaType = User.class,
one = @One(select = "com.xiongbinzou.mybatisplusdemo.mapper.UserMapper.selectById")
)
}
)
List<Order> selectAllOrderAndUser();
}

5)修改/mybatisplusdemo/src/main/java/com/xiongbinzou/mybatisplusdemo/controller/UserController.java类文件,内容如下:

package com.xiongbinzou.mybatisplusdemo.controller;

import com.xiongbinzou.mybatisplusdemo.entity.User;
import com.xiongbinzou.mybatisplusdemo.mapper.UserMapper;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
public class UserController {
@Autowired
private UserMapper userMapper;

@ApiOperation("创建用户")
@PutMapping("/user")
public String create(User user) {
int i = userMapper.insert(user);
if (i > 0) {
return "插入成功";
} else {
return "插入失败";
}
}

@ApiOperation("更新用户")
@PostMapping("/user")
public String update(User user) {
int i = userMapper.updateById(user);
if (i > 0) {
return "更新成功";
} else {
return "更新失败";
}
}

@ApiOperation("根据id删除用户")
@DeleteMapping("/user/{id}")
public String delete(int id) {
int i = userMapper.deleteById(id);
if (i > 0) {
return "删除成功";
} else {
return "删除失败";
}
}

@ApiOperation("根据id查找用户")
@GetMapping("/user/{id}")
public User findById(int id) {
User user = userMapper.selectById(id);
System.out.println(user);
return user;
}

@ApiOperation("获取所有用户")
@GetMapping("/user")
public List<User> queryAll() {
List<User> list = userMapper.selectList(null);
System.out.println(list);
return list;
}

@ApiOperation("获取所有用户及其订单")
@GetMapping("/user/findAll")
public List<User> findByCond() {
List<User> list = userMapper.selectAllUserAndOrders();
System.out.println(list);
return list;
}
}

6)在/mybatisplusdemo/src/main/java/com/xiongbinzou/mybatisplusdemo/controller目录下,创建OrderController.java类文件,内容如下:

package com.xiongbinzou.mybatisplusdemo.controller;

import com.xiongbinzou.mybatisplusdemo.entity.Order;
import com.xiongbinzou.mybatisplusdemo.mapper.OrderMapper;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class OrderController {
@Autowired
private OrderMapper orderMapper;

@ApiOperation("获取所有订单")
@GetMapping("/order")
public List<Order> queryAll() {
List<Order> list = orderMapper.selectList(null);
System.out.println(list);
return list;
}

@ApiOperation("获取所有订单及其用户")
@GetMapping("/order/findAll")
public List<Order> findByCond() {
List<Order> list = orderMapper.selectAllOrderAndUser();
System.out.println(list);
return list;
}
}

7.2 条件查询

https://baomidou.com/pages/10c804/

在/mybatisplusdemo/src/main/java/com/xiongbinzou/mybatisplusdemo/controller/UserController.java类文件新增内容如下:

@ApiOperation("根据名字查找用户")
@GetMapping("/user/find")
public List<User> findByCond(String username) {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("username", username);
return userMapper.selectList(queryWrapper);
}

7.3 分页查询

在/mybatisplusdemo/src/main/java/com/xiongbinzou/mybatisplusdemo/controller/UserController.java类文件新增内容如下:

@ApiOperation("分页查询用户列表")
@GetMapping("/user/findByPage")
public IPage findByPage(int pageIndex, int pageSize) {
Page<User> page = new Page<>(pageIndex, pageSize);
IPage iPage = userMapper.selectPage(page, null);
return iPage;d
}

在/helloworld/src/main/java/com/xiongbinzou/mybatisplusdemo/config文件夹下新建MyBatisPlusConfig类,内容如下:

package com.xiongbinzou.mybatisplusdemo.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor paginationInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
PaginationInnerInterceptor paginationInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
interceptor.addInnerInterceptor(paginationInterceptor);
return interceptor;
}
}

8. Vue框架快速上手

8.1 前端环境准备

8.2 Vue框架介绍

  • Vue(读音 /vju:/,类似于view)是一套用于构建用户界面的渐进式框架
  • Vue.js提供了MVVM数据绑定和一个可组合的组件系统,具有简单、灵活的API
  • 其目标是通过尽可能简单的API实现响应式的数据绑定和可组合的视图组件

9. Vue组件化开发

10. 第三方组件element-ui

11. Axios网络请求

12. 前端路由VueRouter

13. 状态管理VueX

14. 前端数据模拟MockJS

15. vue-element-admin后台集成方案

16. JWT跨域认证

17. SpringBoot+vue-element-admin

18. 阿里云服务使用

19. SpringBoot+Vue云端环境配置

20. SpringBoot+Vue项目云端部署