刷课刷课刷课嘿嘿嘿1天搞定SpringBoot+Vue全栈开发
本课程是涵盖主流前后端开发技术的全栈课程,主要内容如下:

  • Java EE企业级框架:SpringBoot+MyBatisPlus
  • Web前端核心框架:Vue+ElementUl
  • 公共云部署:前后端项目集成打包与部署

1.课程介绍及环境准备

Web技术基础:
目前市面上的软件主要可分为两种:
1.BS:(Browser/Server,浏览器/服务器架构模式),通过浏览器访问应用程序
2.CS:(Client/Server,客户端/服务器架构模式),通过客户端程序访问服务器

  • C/S架构主要特点是交互性强,具有安全访问模式,网络流量低,响应速度快,因为客户端负责大多数业务逻辑和UI演示,所以也被称为胖客户端,C/S结构的软件需要针对不同的操作系统开发不同版本的软件。
  • 随着互联网的兴起,CS架构不运合Web,,最大的原因是Web应用程序的修改和升级非常迅速,而CS架构需要每个客户端逐个升级桌面App,因此Browser/Server模式开始流行,简称BS架构。
  • B/S架构的主要特点是分散性高、维护方便、开发简单、共享性高、总拥有成本低
    BS架构原理
    在BS架构下,客户端只需要浏览器,应用程序的逻辑和数据都存储在服务器端。
    浏览器只需要请求服务器,获取Web页面,并把Web页面展示给用户即可。
    BS架构原理
    前端主要做WEB浏览器,后端主要做WEB服务器和数据库服务器。

(中间讲了开发环境的配置和推荐的开发工具IDEA)

Maven 是一个项目管理工具,可以对 Java 项目进行自动化的构建和依赖管理。
maven
在pom.xml里面指定依赖
maven install 可以到自己到网上下载依赖
maven compile 可以编译整个项目
maven package 可以把整个项目打成一个 jar 包,然后可以丢给服务器运行
作用分为三类:
1.项目构建:提供标准的,跨平台的自动化构建项目的方式;
2.依赖管理:方便快捷的管理项目依赖的资源(jar包),避免资源间的版本冲突等问题
3.统一开发结构:提供标准的,统一的项目开发结构。
运行 Maven 的时候,Maven 所需要的任何构件都是直接从本地仓库获取的,如果本地仓库没有,它会首先尝试从远程仓库下载构件至本地仓库。
(配置Maven…)

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

2.SpringBoot快速入手

  • Spring Boot是由Pivotal团队提供的基于Spring的全新框架,旨在简化Spring应用的初始搭建和开发过程。
  • Spring Boot是所有基于Spring开发项目的起点。
  • Spring Boot就是尽可能地简化应用开发的门槛,让应用开发、测试、部署变得更加简单

SpringBoot特点:

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

快速创建SpringBoot应用
利用IDEA提供的Spring Initializr创建SpringBoot应用。
填写项目信息
Group:一般输入公司域名。
Artifact:项目名称。
(我的版本好像跟课里的不太一样)
在这里插入图片描述
在这里插入图片描述
这两个要对应(1.8选8,11选11)

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.2</version>
<relativePath/><!-- lookup parent from repository -->
</parent>

在pom.xml中可能没有,运行不了的话要自己导入。

package com.example.helloworld.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestControllerpublic 
class Hellocontroller {
	@GetMapping("/hello")
	//具体访问这个方法的时候需要写一个明确的链接地址,如/hello
	//就是把 get 请求映射到这个函数,浏览器直接访问链接就是get请求
	public string hello(){
		return "hello world";
	}
}

这样我们可以通过http://localhost:8080/hello访问我们的方法(localhost代表本地;访问一个网站,默认访问:80端口,可以省略,但是我们启动这个项目的时候,默认的是8080)
127.0.0.1:8080/hello也能访问
如http://baidu.com/s/xx我们定义的/hello属于这后面的/s/xx

开发环境热部署

  • 在实际的项目开发调试过程中会频繁地修改后台类文件,导致需要重新编译、重新启动,整个过程非常麻烦,影响开发效率。

  • Spring Boot提供了spring-boot-devtools组件,使得无须手动重启SpringBoot应用即可重新编译、启动项目,大大缩短编译启动的时间。

  • devtools会监听classpath下的文件变动,触发Restart类加载器重新加载该类从而实现类文件和属性文件的热部署。

  • 并不是所有的更改都需要重启应用(如静态资源、视图模板),可以通过设置spring.devtools.restart.exclude属性来指定一些文件或目录的修改不用重启应用

  • 在pom.xml配置文件中添加dev-tools依赖。

  • 使用optional=true表示依赖不会传递,即该项目依赖devtools;其他项目如果引入此项目生成的JAR包,则不会包含devtools

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

(如果没下载过右上角有按钮下载)

在application.properties中配置devtools。

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

spring.devtools.restart.enabled=true

spring.devtools.restart.additional-paths=src/main/java

  • 如果使用了Eclipse,那么在修改完代码并保存之后,项目将自动编译并触发重启,而如果使用了IntelliJ IDEA,还需要配置项目自动编译。
  • 打开Settings页面,在左边的菜单栏依次找到Build,Execution,Deployment→Compile,勾选Build project automatically
  • 按Ctrl+Shift+Alt+/快捷键调出Maintenance页面,单击Registry,勾选compilerautomake.allow.when.app.running复选框。/较新版本在Settings-Advanced Settings-Compiler里可以找到哦
  • 做完这两步配置之后,若开发者再次在IntelliDEA中修改代码,则项目会自动重启。

3.SpringBoot Controller

Web入门:

  • Spring Boot将传统Web开发的mvc、json、tomcat等框架整合,提供了spring-boot-starter-web组件,简化了Web应用配置。
  • 创建SpringBoot项目勾选Spring Web选项后,会自动将spring-boot-starter-web组件加入到项目中。
  • spring-boot-starter-web启动器主要包括web、webmvc、ison、tomcat等基础依赖组件,作用是提供Web开发场景所需的所有底层依赖。
  • webmvc为Web开发的基础框架,ison为JSON数据解析组件,tomcat为自带的容器依赖。
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>

控制器:

  • Spring Boot提供了@Controller和@RestController两种注解来标识此类负责接收和处理HTTP请求。
  • 如果请求的是页面和数据,使用@Controller注解即可;如果只是请求数据则可以使用@RestController注解。
    MVC设计模式: M:Model,用来存储或封装数据的
    V:View,用来显示数据的
    C:Controller,用来协调和控制的
    MVC设计模式
    @Control应用:
    1.示例中返回了hello页面和name的数据,在前端页面中可以通过${name}参数获取后台返回的数据并显示。
    2.@Controler通常与Thymeleaf模板引擎结合使用。
    (这个注解不是我们的重点)
@Controller
public class Hellocontroller {
	@RequestMapping("/hello")
	public String index(ModelMap map){
		map.addAttribute( attributeName: "name", attributeValue: "zhangsan");
		return "hello";
	}
}

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

package org.example.helloworld.controller;

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

@RestController
@RequestMapping("/user")
public class HelloController {
    public class User{
        String name;
        String word;
        public void setUsername(String x){name = x;}
        public void setPassword(String x){word = x;}
        public String getName() { return name;}
        public String getWord() { return word;}
    }

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

}

你得写getUsername还有getPassword,他要帮你解析成字符串的时候,会调用这种函数拿到类的成员的值,你没有这两个函数的话,就没办法转成json了,或者可以使用@Data@Data使用与介绍
路由映射:

  • @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”),当在浏览器中请求/getson/a.json或者/getJson/b.json时都会匹配到后台的Json方法

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

  • 符号“* ”匹配任意路径,符号“?”匹配单个字符,"**"匹配任意字符,有通配符的优先级低于没有通配符的,比如/user/add.json比/user/*.json优先匹配。两个 * 优先级低于一个 *

Method匹配

  • HTTP请求Method有GET、POST、PUT、DELETE等方式。HTTP支持的全部Method
  • @RequestMapping注解提供了method参数指定请求的Method类型,包括RequestMethod.GET、RequestMethod.POST、RequestMethod.DELETERequestMethod.PUT等值,分别对应HTTP请求的Method
@RequestMapping(value = "/getData",method = RequestMethod.GET)
public String getData(){
	return "hello";
}

Method匹配也可以使用@GetMapping、@PostMapping等注解代替

参数传递
@RequestParam将请求参数绑定到控制器的方法参数上,接收的参数来自HTTP请求体或请求url的QueryString,当请求的参数名称与Controller的业务方法参数名称一致时,@RequestParam可以省略
@PathVaraible:用来处理动态的URL,URL的值可以作为控制器中处理方法的参数
@RequestBody接收的参数是来自requestBody中,即请求体。一般用于处理非 Content-Type: application/x-www-form-urlencoded编码格式的数据比如:application/jsonapplication/xmi 等类型的数据

@RestController
public class Hellocontroller {
// http://localhost:8080/hello
// http://localhost:8080/hello?nickname=zhangsan
@RequestMapping(value = "/hello",method = RequestMethod.GET)
public String hello(string nickname){
	return"你好"+nickname;
}

多个参数用 & 符号拼接起来
参数名称不对应可以加注释(注释后必须要传递参数,不然方法不会被访问到)

@RequestMapping(value = "/getTest3",method = RequestMethod.GET)
// http://localhost:8080/getTest2?nickname=xxx
public String getTest3(@ReguestParam("nickname") String name){
	System.out.println("nickname:"+name);
	return "GET请求";
}

可以加点东西表示传递不传递都可以@RequestParam(value ="nickname",required =false)

你要想发送POST请求,一个是通过专门的前端程序或者是表单。
我用的是Apifox
POST请求想要加参数,应把Body的编码类型改成x-www-form-urlencoded(这个类型会把对应的参数做一个编码),有时候可能会用到json类型,json类型里面的字符串必须用双引号括起来,还需要加一个单独的在注解public String postTest4(@RequestBody User user){}
如果想把参数放到问号后面,就用Query
在这里插入图片描述
这个要改一下,不然请求不了啊啊啊啊啊啊啊

4.SpringBoot 文件上传+拦截器

静态资源访问

  • 会默认创建出classpath:/static/目录,静态使用IDEA创建Spring Boot项目,资源一般放在这个目录下即可。(做前后端分离的这里一般不放东西)
  • 如果默认的静态资源过滤策略不能满足开发需求,也可以自定义静态资源过滤策略。
  • 在application.properties中直接定义过滤规则和静态资源位置:
    spring.mvc.static-path-pattern=/static/** (访问静态资源时的url,默认值不带static)
    spring.web.resources.static-locations=classpath:/static (静态资源的位置,默认值一般放在static下面)
  • 过滤规则为/static/**,静态资源位置为classpath:/static/
  • classpath 代表的是类路径,编译完的文件都放在target下了

文件上传原理
前端需要有对应的表单

  • 表单的enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码。
  • 当表单的enctype=“application/x-www-form-urlencoded”(默认)时,form表单中的数据格式为:key=value&key=value,应该改为为以下(否则文件传不上来)
  • 当表单的enctype="multipart/form-data"时,其传输数据形式如下:
    在这里插入图片描述
    SpirngBoot实现文件上传功能:
  • Spring Boot工程嵌入的tomcat限制了请求的文件大小,每个文件的配置最大为1Mb,单次请求的文件的总数不能大于10Mb。
  • 要更改这个默认值需要在配置文件(如application.properties)中加入两个配置
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB
  • 当表单的enctype=“multipart/form-data” 时,可以使用MultipartFile 获取上传的文件数据,再通过transferTo(可以帮你写入到服务器的某个目录里面去)方法将其写入到磁盘中
package org.example.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 up(String nickname, MultipartFile photo, HttpServletRequest request)throws IOException {
        //HttpServletRequest request这个类代表的是网络请求
        System.out.println(nickname);
        //获取文件原始昵称
        System.out.println(photo.getOriginalFilename());
        //获取文件类型
        System.out.println(photo.getContentType());

        String path = request.getServletContext().getRealPath(  "/upload/");
        //这个我们是想获取到WEB服务器的运行目录
        //通过request我们可以获取到它的上下文对象(请求所属的上下文,其实就是我们的WEB服务器)
        //(  "/upload/")可以随便写,它要是不存在的,我们把它创建出来就可以了
        System.out.println(path);
        saveFile(photo,path);
        return "上传成功";
    }

    private void saveFile(MultipartFile photo, String path) throws IOException {
        //判断存储的目录是否存在,如果不存在则创建
        File dir = new File(path);
        if(!dir.exists()){
            //创建目录
            dir.mkdir();
        }
        File file = new File( path+photo.getOriginalFilename());
        photo.transferTo(file);//把网络传输过来的文件存储到目录之中
    }
}

实际的上传功能就是把用户传上来的文件存储到web服务器的本地里去;
如果我想要让用户能访问他上传的文件,那我需要配置一个路径:

spring.web.resources.static-locations=/upload/

拦截器

  • 拦截器在Web系统中非常常见,对于某些全局统一的操作,我们可以把它提取到拦截器中实现。总结起来,拦截器大致有以下几种使用场景:
  • 权限检查:如登录检测,进入处理程序检测是否登录,如果没有,则直接返回
    登录页面。
  • 性能监控:有时系统在某段时间莫名其妙很慢,可以通过拦截器在进入处理程序之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间
  • 通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有提取Locale、Theme信息等,只要是多个处理程序都需要的,即可使用拦截器实现。
  • Spring Boot定义了HandlerInterceptor接囗来实现自定义拦截器的功能
    Handlerlnterceptor接口定义了preHandle、postHandle、afterCompletion三种方法,通过重写这三种方法实现请求前、请求后等操作
    拦截器
    拦截器定义
public class LoginInterceptor extends HandlerInterceptor {
/*
*在请求处理之前进行调用(contro1ler方法调用之前)
*/
@override
	public boolean preHandle(HttpservletRequest request, HttpservletResponse response, object handler)throws Exception {
	/*比较重要的request对于前端的请求,reponse你可以利用它给前端返回对应的信息
	*/
		if(条件){
			system.out.printin("通过");
			return true;
		}else{
			system.out.printin("不通过");
			return false;
		}
	}
}

重写完后要做一个拦截器注册

  • addPathPatterns方法定义拦截的地址
  • excludePathPatterns定义排除某些地址不被拦截
  • 添加的一个拦截器没有addPathPattern任何一个url则默认拦截所有请求
  • 如果没有excludePathPatterns任何一个请求,则默认不放过任何一个请求。
@Configuration
public class WebConfigurer implements MebMvcConfigurer {
	@override
	public void addInterceptors(InterceptorRegistry registry){
		registry.addInterceptor(new Loginrnterceptor()).addPathPatterns("/user/**");
		//new Loginrnterceptor()把刚写的拦截器读进来
		//.addPathPatterns("/user/**")这个不是必要的
	}
}

这个一般放在Config包下,注解记得加。

5.RESTful服务 + Swagger

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

RESTful特点:

  • 每一个URI代表一种资源
  • 客户端使用GET、POST、PUT、DELETE四种表示操作方式的动词对服务端资源进行操作:GET用于获取资源,POST用于新建资源(也可以用于更新资源)PUT用于更新资源,DELETE用于删除资源。
  • 通过操作资源的表现形式来实现服务端请求操作。
  • 资源的表现形式是JSON或者HTML。客户端与服务端之间的交互在请求之间是无状态的从客户端到服务端的每个请求都包含必需的信息。

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

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

HTTP Method:

  • HTTP提供了POST、GET、PUT、DELETE等操作类型对某个Web资源进行Create、Read、Update和Delete操作。
  • -个HTTP请求除了利用URI标元目标资源之外,还需要通过HTTP Method指定针对该资源的操作类型,一些常见的HTTP方法及其在RESTfuI风l格下的使用:

HTTP Method
HTTP状态码:

  • HTTP状态码就是服务向用户返回的状态码和提示信息,客户端的每一次请求服务都必须给出回应,回应包括HTTP状态码和数据两部分
  • HTTP定义了40个标准状态码,可用于传达客户端请求的结果。状态码分为以下五个类别:
    • 1xx:信息,通信传输协议级信息
    • 2xx:成功,表示客户端的请求已成功接受
    • 3xx:重定向,表示客户端必须执行一些其他操作才能完成其请求
    • 4xx:客户端错误,此类错误状态码指向客户端
    • 5xx:服务器错误,服务器负责这写错误状态码
  • RESTfUI API中使用HTTP状态码来表示请求执行结果的状态,适用于RESTAPI设计的代码以及对应的HTTP方法。以下是一些状态码详解:

HTTP状态码Spring Boot实现RESTfUI API

  • Spring Boot提供的spring-boot-starter-web组件完全支持开发RESTfuI API提供了与REST操作方式(GET、POST、PUT、DELETE)对应的注解
    @GetMapping:处理GET请求,获取资源。
    @PostMapping:处理POST请求,新增资源。
    @PutMapping:处理PUT请求,更新资源。
    @DeleteMapping:处理DELETE请求,删除资源.
    @PatchMapping:处理PATCH请求,用于部分更新资源。
  • 在RESTful架构中,每个网址代表一种资源,所以URI中建议不要包含动词,只包含名词即可,而且所用的名词往往与数据库的表格名对应。
    用户管理模块API示例:
@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/fid}")
public String deleteById(@PathVariable int id){
	return "根据ID删除用户"}

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

<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>
package org.example.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 // 告诉Spring容器,这个类是一个配置类
@EnableSwagger2 //启用Swagger2功能
public class SwaggerConfig {
    //配置Swagger2相关的Bean
    @Bean
    public Docket CreateRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("org"))//org包下所有API都交给Swagger2管理
                .paths(PathSelectors.any()).build();
    }
    //此处主要是API文档显示信息
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("演示项目API")// 标题
                .description("学习Swagger2的演示项目") //描述
                .build();
    }
}

启动项目访问 http://127.0.0.1:8080/swagger-ui.html,http://locahost:8080/swagger-ui/index.html即可打开自动生成的可视化测试页面
注: 22年12月末的 IDEA新建项目默认使用的 springframework是3.0.1版本,但 swagger2 的 2.9.2版本 不支持这么高版本,再声就是 swagger3 了(注意3与2的语法不相同)我自己用的 springframework是 2.4.13版本,可以实现与swagger2 的版本匹配。
Swagger常用注解

6.MybatisPlus快速入手

ORM

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

MyBatis-Plus介绍

  • MyBatis是一款优秀的数据持久层ORM框架,被广泛地应用于应用系统。
  • MyBatis能够非常灵活地实现动态SQL,可以使用XML或注解来配置和映射原生信息,能够轻松地将Java的POJO(Plain Ordinary Java Object,普通的Java对象)与数据库中的表和字段进行映射关联。
  • MyBatis-Plus是一个 MyBatis 的增强工具,在 MyBatis 的基础上做了增强简化了开发。
		<!-- MyBatisPlus依赖 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version></dependency>
        <!-- mysq1驱动依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <!--数据连接池 druid-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.20</version>
        </dependency>

mysql驱动依赖最新版本

		<!-- mysql驱动依赖最新版本-->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test1?useSSL=false
spring.datasource.username=root
spring.datasource.password=
//密码和数据库要自己改,数据库是第三个
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
@SpringBootApplication
@MapperScan("com.xx.mapper")
public class MybatisplusDemoApplication {
	public static void main(string[] args){
		SpringApplication.run(MybatisplusDemoApplication.class, args);
	}
}

在这里插入图片描述
完成这些后,我们在 mapper 包里面新建一个 interface,接口前面要加注解@Mapper

//查询所有用户
@Select("select*from ...")
public List<...> find();
@Insert("insert into ... (id,...)")//(id,...)也可以不指定用value(#{})
public int insert(<> ...)
//返回值代表插入了几条记录

偷个小懒(直接插入课里打好的示例):
在这里插入图片描述

@Options(keyProperty="id",useGeneratedKeys = true)生成并返回主键值

如果我们用MyBatis-Plus,这些也可以不写:

@Mapper
public interface UserMapper extends BaseMapper<User>{
}

如何在Controller使用:

@Autowired
private <接口名> ...;

如果表名和类名不一致:

@TableName("t_user")
public class User {}

还介绍了一些注解

  • @Tabled(type = IdType.Auto)
  • @TableField("nickname")
  • @TableField(exist = false)

更多注解可以在mybatis-plus官网查看

7.MybatisPlus多表查询及分类查询

多表查询
实现复杂关系映射,可以使用@Results注解,@Result注解,@One注解@Many注解组合完成复杂关系的配置。
在这里插入图片描述
如果我的user表里没有order,想读到order表的order(要建一个ordermapper来读order表):

@Select("select *from tuser")
@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.example.mpdemo.mapper.OrderMapper.selectByUid")
		//这个时候他就会吧这个id传给这个方法的参数}

想在order中读到user同理,一对一用@One,一对多用@Many

驼峰命名自动映射开关a_column -> aCloumn

// application.properties
mybatis.configuration.map-underscore-to-camel-case=true

条件查询

QueryWrapper<User> queryWrapper =new QueryWrapper();
queryWrapper.eq( column: "username",val: "zhangsan");
return userMapper.selectList(queryWrapper);
//分页查询
@GetMapping(©"/user/findByPage")public IPage findByPage(){
//设置起始值及每页条数
Page<User> page =new Page<>( 0, 2);//第一个从第几条开始取,第二个是取几条
IPage iPage =userMapper.selectPage(page,null);
return iPage;
}

得先配置一个类:

@Configuration
public class MyBatisPlusconfig {
	@Bean
	public MybatisPlusInterceptor paginationInterceptor(){
	MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
	PaginationInnerInterceptor paginationInterceptor = new 	PaginationInnerInterceptor(DbType.MYSQL);
	//MYSQL你数据库的类型
	interceptor.addInnerInterceptor(paginationInterceptor);
	return interceptor;
}

分页查询:

<!--PageHelper分页插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.4.2</version>
        </dependency>

在这里插入图片描述

8.Vue框架快速上手

Vue框架介绍
Vue是一套用于构建用户界面的渐进式框架。
Vue.js提供了MVM数据绑定和一个可组合的组件系统,具有简单、灵活的API。
其目标是通过尽可能简单的API实现响应式的数据绑定和可组合的视图组件。

1.导入 vue.js 的 script 脚本文件
2.在页面中声明一个将要被 vue 所控制的 DOM 区域,既MVVM中的View
3.创建 vm 实例对象(vue 实例对象)

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>

<div id="app">{{ message }}</div>

<script>
  const { createApp, ref } = Vue

  createApp({
    setup() {
      const message = ref('Hello vue!')
      return {
        message
      }
    }
  }).mount('#app')
</script>

script中也可以这么写

const hello ={
//指定数据源,既MVVM中的Mode1
	data:function(){
		return {
			message:'He11o Vue!'
		}
	}
}
const app = Vue.createApp(he11o)
app.mount('#app')// 指定当前vue实例要控制页面的哪个区域

属性绑定指令:

<div id="app">
	<a v-bind:href="link">百度</a>
	<input type="text" :placeholder="inputValue">:style="{width:w}" alt="")
	<img :src="imgSrc">
</div>
<script>
	const vm = {
		data: function(){
			return{
				link:"http://www.baidu.com'
				// 文本框的占位符内容
				inputValue:'请输入内容',
				//图片的 src 地址
				imgSrc:'./images/demo.png',
				w:'500px'
			}
		}
	}
	const app =Vue.createApp(vm)
	app.mount('#app')
</script>

事件绑定指令:

<div id="app">
	<h3>count 的值为:{{count}}</h3>
	<button v-on:click="addCount">+1</button>
	<button @click="count+=1">+1</button>
	<!--两个botton在这里用处相同-->
</div>
<script>
	const vm={
		data: function(){
			return {
				count:0}
		},
		methods:{
		//点击按钮,让 count 自增 +1
			addCount(){
				this.count += 1
			}
		}
	}
	const app =Vue.createApp(vm)
	app.mount('#app')
</script>

条件渲染指令:

<p v-if="flag">请求成功 --- 被 v-if 控制</p>
<p v-show="flag">请求成功---被 v-show 控制</p>

可以写if-else语句:

<p v-if="type ==='A'">优秀</p>
<p v-else-if="type ==='B'">良好</p>
<p v-else-if="type === 'C'">一般</p>
<p v-else></p>

列表渲染指令:

<div id="app">
	<ul>
		<li v-for="(user,i)in userList">索引是:{{i}},姓名是:{{user.name}}</li>
	</ul>
</div>
<script>
	const vm={
		data: function(){
			return {
				userList:[
					{id:1,name:'zhangsan'}
					{id:2,name:'lisi'}
				]
			}
		}
	}
	const app =Vue.createApp(vm)
	app.mount('#app')
</script>			

v-for中的key:

<div id="app">
	<!--添加用户的区域-->
	<div>
		<input type="text" v-model="name"><!-- v-model双向绑定 -->
		<button @click="addNewUser">添加</button>
	</div>
	<!--用户列表区域-->
	<ul>
		<li v-for="(user, index)in userlist":key="user.id">
			<input type="checkbox" />姓名:{{user.name}}
		</li>
	</ul>
</div>
<script>
	const vm = {
		data: function(){
			return {// 用户列表
				userlist:[
					{id:1,name:'zhangsan'},
					{id:2,name:'lisi'},
				]
				// 输入的用户名
				name:' ',
				//下一个可用的 id 值
				nextId:3
			}
		}
		methods:{
		// 点击了添加按钮
			addNewUser(){
				this.userlist.unshift({ id: this.nextId, name: this.name })
				this.name =' '
				this.nextId++
			}
		}
	}
	const app =Vue.createApp(vm)
	app.mount('#app')
</script>

9.Vue组件化开发

NPM简介:

  • NPM(Node Package Manager)是一个NodeJS包管理和分发工具
  • NPM以其优秀的依赖管理机制和庞大的用户群体,目前已经发展成为整个JS领域的依赖管理工具
  • NPM最常见的用法就是用于安装和更新依赖。要使用NPM,首先要安装Node工具

Node.js安装:Node.js 是一个基于 Chrome V8引擎 的 JavaScript 运行时环境。Node中包含了NPM包管理工具。下载地址:node.js

npm使用
在这里插入图片描述
Vue CLl使用

  • Vue CLl是Vue官方提供的构建工具,通常称为脚手架。
  • 用于快速搭建一个带有热重载(在代码修改后不必刷新页面即可呈现修改后的效果)及构建生产版本等功能的单页面应用。
    Vue CLl基于 webpack 构建,也可以通过项目内的配置文件进行配置。
  • 安装:npm install -g @vue/cli
    (这个脚手架有点慢,底层是webpack,现在更快的是用vite
    创建新项目直接用npm create vue@latest就好
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

?Save this as a preset for future projects?(y/N)最后这个输入一个N就可以了
选择完这些选项后,会让你命名。
课程里用npm run service,用vite的话用 npm run dev
(这个的意思是为后面的命令起一个别名,一般就是 serve 或者 dev)

main.js主要用到模块化开发的思想:

import { createApp } from 'vue'
import App from './App.vue' 
//通过import引入模块
createApp(App).mount('#app')

App.vue是Vue提供的一个组件,Vue的思想里面倾向于我们用组件的思想做开发:

  • 组件(Component)是Vue.js最强大的功能之一。组件可以扩展HTML元素封装可重用的代码。
  • Vue的组件系统允许我们使用小型、独立和通常可复用的组件构建大型应用。
  • 组件的构成
    Vue 中规定组件的后缀名是 .vue,每个 .vue 组件都由 3部分构成,分别是
    • template,组件的模板结构,可以包含HTML标签及其他的组件
    • script,组件的JavaScript 代码
    • style,组件的样式
      在这里插入图片描述
      组件倒入完要做一个注册,如上图所示

10.第三方组件element-ui

  • 组件间的传值:

    • 组件可以由内部的Data提供数据,也可以由父组件通过prop的方式传值。
    • 兄弟组件之间可以通过Vuex等统一数据源提供数据共享。
      (课里说vue3没有element-ui,但课好几年前的的,elementplus,现在的vue3用的这个)
  • <script></script>里面一定要有export default来导出

我们在App.vue中import自己建的Movie.vue。
在Movie中,我们在script中使用自定义的属性props:["title"],在这里面,可以任意定义属性的名称,这样外面就可以使用这个名称,也就是我们可以在我们的App.vue中<Movie title="金刚狼"></Movie>或者

<template>
	<div id="app">
	<Movie v-for="movie in movies" :key="movie.id":title="movie.title":rating="movie.rating"></Movie></div>
</template>

<script>
	import Movie from./components/Movie.vue'
	export default{
		name:'App',
		data:function(){
			return {
				movies :[
					{id:1,title:"金刚狼1",rating:8.7},
					{id:2,title:"金刚狼2",rating:8.8},
					{id:3,title:"金刚狼3",rating:8.6},
				]
			}
		}
		components:{
			Movie
		}
	}
</script>

要在components里面做一个映射

element-ui介绍
Element是国内饿了么公司提供的一套开源前端框架,简洁优雅,提供了Vue、React、Angular等多个版本。
文档地址:element-ui
安装:npm i element-ui
引入Element:

import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from'./App.vue';

Vue.use(ElementUI);

new Vue({
	el:'#app',
	render:h=>h(App)
});

elementplus:element-plus
(引入和安装可在网站上找,引入在快速开始那里)

然后要用组件就查官方文档就行了。

第三方图标库
由于Element Ul提供的字体图符较少,一般会采用其他图表库,如著名的FontAwesome
Font Awesome提供了675个可缩放的矢量图标,可以使用CSS所提供的所有特性对它们进行更改,包括大小、颜色、阴影或者其他任何支持的效果。
文档地址:Font Awesome
安装:npm install font-awesome
使用:import 'font-awesome/css/font-awesome.min.css‘
<i class="fa fa-camera-retro"></i>fa-camera-retro

element-plusicon图标里也有很多图标

11.Axios网络请求

  • Axios简介
    • 在实际项目开发中,前端页面所需要的数据往往需要从服务器端获取,这必然涉及与服务器的通信。
    • Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中。
    • Axios 在浏览器端使用XMLHttpRequests发送网络请求,并能自动完成JSON数据的转换 。
    • 安装:npm install axios
    • 地址:Axios

使用的时候import axios from 'axios'

发送网络请求
发送GET请求:

// 向给定ID的用户发起请求
axios.get("/user?ID=12345')
	.then(function(response){
	//处理成功情况
	console.log(response);
	})
	.catch(function(error){
	// 处理错误情况
	console.log(error);
	})
	.then(function(){
	// 总是会执行
	});
//上述请求也可以按以下方式完成(可选)
axios.get('/user',{
	params:{
		ID:12345
	}
	})
	.then(function(response){
		console.log(response);
	})
	.catch(function(error){
		console.log(error);
	})
	.then(function(){
	// 总是会执行
	});

发送POST请求:

axios.post('/user',{
	firstName:'Fred',
	lastName:'Flintstone'
	})
	.then(function(response){
	console.log(response);
	})
	.catch(function(error){
	console.log(error);
	});

异步回调问题解决
async/await

// 支持async/await用法
async function getUser(){
	try{
		const response =await axios.get('/user?ID=12345');
		console.log(response);
	}catch(error){
		console.error(error);
	}
}

其他请求方式:
参考:https://axios-http.com/zh/docs/req_config

//发起一个post请求
axios({ 
	method :'post ',
	url:'/user/12345',
	data:{
		firstName :'Fred',
		lastName:'Flintstone'
	}
});

生命周期函数created:function(){ },,和data同级
还有个类似的挂载的mounted:function(){ },其他这些可以在官网vue查询。
一般axios写在created:function(){ },里面,'/user’写这个的时候,要明确往哪个端口发,如"http://localhost:8088/user"
当8080端口向8088端口发送请求时,会出现 跨域问题 导致失败

为什么会出现跨域问题?

  • 为了保证浏览器的安全,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源,称为同源策略,同源策略是浏览器安全的基石
  • 同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能
  • 所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)
  • 当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域,此时无法读取非同源网页的 Cookie,无法向非同源地址发送 AJAX 请求。

跨域问题解决

  • CORS(Cross-Origin Resource Sharing)是由W3C制定的一种跨域资源共享技术标准,其目的就是为了解决前端的跨域请求。
  • CORS可以在不破坏即有规则的情况下,通过后端服务器实现CORS接口,从而实现跨域通信。
  • CORS将请求分为两类:简单请求和非简单请求,分别对跨域通信提供了支持。

简单请求

  • 满足以下条件的请求即为简单请求:
    • 请求方法:GET、POST、HEAD
    • 除了以下的请求头字段之外,没有自定义的请求头:
      Accept、Accept-Language、Content-Language、 Last-Event-lDContent-Type
    • Content-Type的值只有以下三种:
      text/plain、multipart/form-data、application/x-www-form-urlencoded

简单请求的服务器处理
对于简单请求,CORS的策略是请求时在请求头中增加一个Origin字段
Host:localhost:8080
Origin:http://localhost:8081
Referer:http://localhost:8081/index.html
服务器收到请求后,根据该字段判断是否允许该请求访问,如果允许,则在HTTP头信息中添加Access-Control-Allow-Origin字段。
Access-Control-Allow-0rigin:http://localhost:8081
Content-Length:20
Content-Type:text/plain;charset=UTF-8
Date:Thu,12 Jul2018 12:51:14 GMT

非简单请求

  • 对于非简单请求的跨源请求,浏览器会在真实请求发出前增加一次OPTION请求,称为预检请求(preflight request)

  • 预检请求将真实请求的信息,包括请求方法、自定义头字段、源信息添加到HTTP头信息字段中,询问服务器是否允许这样的操作。

    • 例如一个GET请求:
      OPTIONS /testHTTP/1.1
      Origin:http://www.test.com
      Access-Control-Request-Method:GET
      Access-Control-Request-Headers:X-Custom-Header
      Host:www.test.com
  • Access-Control-Request-Method表示请求使用的HTTP方法,AccessControl-Request-Headers包含请求的自定义头字段。

  • 服务器收到请求时,需要分别对Origin、Access-Control-Request-Method.Access-Control-Request-Headers进行验证,验证通过后,会在返回HTTP头信息中添加:
    Access-Control-Allow-0rigin:http://www.test.com
    Access-Control-A1low-Methods:GET,POST,PUT,DELETE
    Access-Control-Allow-Headers:X-Custom-Header
    Access-Control-Allow-Credentials:true
    Access-Control-Max-Age:1728000

  • Access-Control-Allow-Methods、Access-Control-Allow-Headers:真实请
    求允许的方法、允许使用的字段

  • Access-Control-Allow-Credentials:是否允许用户发送、处理cookieAccess-Control-Max-Age:预检请求的有效期,单位为秒,有效期内不会重新发送预检请求。

Spring Boot中配置CORS
在传统的Java EE开发中,可以通过过滤器统一配置,而Spring Boot中对此则提供了更加简洁的解决方案:

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")//允许跨域访问的路径
                .allowedOrigins("*")//允许跨域访问的源
                .allowedMethods("POST","GET","PUT","OPTIONS","DELETE") //允许请求方法
                .maxAge(168000)//预检间隔时间
                .allowedHeaders("*")//允许头部设置
                .allowCredentials(true);//是否发送cookie
    }
}

(全局配置,所有的控制器就都生效了)
也可以在你要使用的控制器里加一个@CrossOrigin

created:function(){
	axios.get("http://localhost:8088/user/findAll").then((response)=>{
	})
},

java(response)=>{ }
可以使发送网络请求时的作用域,继承它的父级。

与Vue整合
在实际项目开发中,几乎每个组件中都会用到 axios 发起数据请求。此时会遇到如下两个问题:
每个组件中都需要导入 axios
每次发请求都需要填写完整的请求路径

可以通过全局配置的方式解决上述问题:(在main.js中导入axios)

//配置请求根路径,localhost:
axios .defaults.baseURL = 'http://api.com'
// 将axios作为全局的自定义属性,每个组件可以在内部直接访问(vue3)
app.config.globalProperties.$http=axios
// 将axios作为全局的自定义属性,每个组件可以在内部直接访问(vue2)
Vue.prototype.$http = axios

这样在组件里用this.$http.get(),就不用每个都写http://localhost:8080之类的,以后端口改了修改也方便。

Logo

一站式 AI 云服务平台

更多推荐