一、入门
1.mvc 介绍![](https://i-blog.csdnimg.cn/direct/bbf90eefde1144f7ab0398354acfe7a2.png)
model 模型层:pojo,java-bin
2.启动类
/**
* 1.表明当前项目为springBoot 工程,这是一个启动类,也是应用程序的入口类
* 2.启动类需要放在根包路径之下,因为他会默认扫描controller 和 service以及mapper 等相关组件
* 扫描完了之后,会放到spring/springboot 的容器中
*/
@SpringBootApplication
@MapperScan("com.yksj.monitor.mapper")
//@ComponentScan("com.yksj.monitor.mapper")
public class MonitorApplication {
public static void main(String[] args) {
TimeZone timeZone = TimeZone.getTimeZone("Asia/Shanghai");
TimeZone.setDefault(timeZone);
SpringApplication.run(MonitorApplication.class, args);
}
}
3.控制器
restcontroller 参考自 restfull API
@RestController 与 @Controller + @ResponseBody 结合效果一样,默认执行view 层,加上后适用于前后分离项目,返回JSON或者sting.
@Controller
public class HelloController {
@ResponseBody
@RequestMapping("hello")
public String Hello(){
return "hello world";
}
}
@RestController
public class HelloController {
@RequestMapping("hello")
public String Hello(){
return "hello world";
}
}
//https://www.imooc.com/learn/1314
4.配置文件
5.自动重启实现(可忽略)
缺点:不能重新加载到配置项,快捷键:cmd+F9,自动重启构建
<!-- sprint boot 提供的开发者工具-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional> true</optional>
</dependency>
6.依赖注入与控制反转
HelloController.java
package com.yksj.monitor.controller;
import com.yksj.monitor.entity.Stu;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
//@Controller
@RestController
public class HelloController {
// @ResponseBody
@RequestMapping("hello")
public String Hello(){
return "hello world-123";
}
@Autowired //实现依赖注入 DI
Stu stu;
@GetMapping("getStu")
public Object getStu() {
return stu; // 控制反转 IOC
}
}
SprintBootConfig.java 配置文件,放在包名下,跟启动类同一级目录
package com.yksj.monitor;
import com.yksj.monitor.entity.Stu;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration //为了说明当前类为配置类,加上这个注解后,会被容器扫描到
/**
* @Bean
* @Controller
* @Service
* @Repository
* @Component
* 这些组件注解也都能使用,根据场景以及类的业务去使用和定义即可
*/
public class SprintBootConfig {
@Bean //将Stu 放入sprintboot 容器内
public Stu stu(){
return new Stu("lxew",18);
}
}
Stu.java pojo<==>entity 作用是一样的
package com.yksj.monitor.entity;
public class Stu {
private String name;
private Integer age;
public Stu(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
使用@Data 代替getter 和 setter, 减少代码量
package com.yksj.monitor.entity;
import lombok.Data;
@Data
public class Stu {
private String name;
private Integer age;
public Stu(String name, Integer age) {
this.name = name;
this.age = age;
}
}
7.字符集 'ISO-8859-1' 存在不受支持的字符
报错如下:
解决方法:idea没设置properties的编码格式,改为utf-8就解决了,
idea对Properties 文件进行专门的编码设置
IntelliJ IDEA 可以对 Properties 文件进行专门的编码设置,也建议改为 UTF-8,其中有一个重点就是属性 Transparent native-to-ascii conversion,一般都要勾选,不然 Properties 文件中的注释显示的都不会是中文
8.解决dependency ‘org.springframework.boot:spring-boot-configuration-processor:2.7.4‘ not found问题
现在pom.xml文件中添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
如果还没成功
就赋予其版本号
例如我就是这样解决
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
<version>2.3.12.RELEASE</version>
</dependency>
加上版本号,就可以了
9.在yml中实现自定义配置与表达式
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
application.yml
server:
port: 8001
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/monitor?characterEncoding=utf-8&useSSL=false&useLegacyDatetimeCode=false&serverTimezone=UTC
username: root
password: 123456
# 配置日期格式化
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: Asia/Shanghai
web:
resources:
static-locations:
[ classpath:/haha/ ]
# mybatis
mybatis:
mapper-locations: classpath:mapper/*.xml
# type-aliases-package:com.yksj.model
app:
name:
xxx:
yyy: aaa
self:
custom:
config:
sdkSecret: 123
host: https://www.baidu.com
port: ${server.port}
//在yml中实现自定义配置与表达式
@Value("${self.custom.config.sdkSecret}")
private String sdkSecret;
@Value("${self.custom.config.host}")
private String host;
@Value("${self.custom.config.port}")
private int port;
@GetMapping("myYmlConfig")
public Object myYmlConfig() {
return sdkSecret + "\t" + host + ":" +port;
}
10.实现自定义启动logo
参考:佛祖保佑,永不宕机,永无bug_佛祖保佑,永无bug-CSDN博客
佛子保佑,永无bug.txt
————————————————————————————————————————————————————————————————————
// _ooOoo_ //
// o8888888o //
// 88" . "88 //
// (| ^_^ |) //
// O\ = /O //
// ____/`---'\____ //
// .' \\| |// `. //
// / \\||| : |||// \ //
// / _||||| -:- |||||- \ //
// | | \\\ - /// | | //
// | \_| ''\---/'' | | //
// \ .-\__ `-` ___/-. / //
// ___`. .' /--.--\ `. . ___ //
// ."" '< `.___\_<|>_/___.' >'"". //
// | | : `- \`.;`\ _ /`;.`/ - ` : | | //
// \ \ `-. \_ __\ /__ _/ .-` / / //
// ========`-.____`-.___\_____/___.-`____.-'======== //
// `=---=' //
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
// 佛祖保佑 永不宕机 永无BUG //
————————————————————————————————————————————————————————————————————
application.yml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/monitor?characterEncoding=utf-8&useSSL=false&useLegacyDatetimeCode=false&serverTimezone=UTC
username: root
password: 123456
banner:
location: banner/fozu.txt
图片形式:
banner:
image:
location: banner/banner.png
pixelmode: text
width: 130
# height: 35
# location: banner/fozu.txt
二、SpringBoot 核心功能讲解
1.静态资源访问
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/monitor?characterEncoding=utf-8&useSSL=false&useLegacyDatetimeCode=false&serverTimezone=UTC
username: root
password: 123456
banner:
location: banner/fozu.txt
# mvc:
# static-path-pattern: /haha/**
# 访问URL路径:http://localhost:8001/haha/3.jpg, 访问的是static 目录下的3.jpg 图片,/haha/** 定义的是路由前缀,
# http://localhost:8001/ 默认访问的是static 目录下单 index.html 文件
# mvc:
# static-path-pattern: /static/**
#静态资源文件配置,默认是 static 目录
web:
resources:
static-locations:
[ classpath:/haha/ ]
2. 通过Lombok 提高开发效率以及日志设置
优点:Lombok 使代码更加直观,简化配置,代码量
缺点:团队中一人使用的话,大家都得使用,否则编译不过去;个人使用无所谓
在java 程序中允许存在同名的方法,只要传参不同即可同时存在。但在PHP中是不允许同时存在的同名方法的。
entity/Student.java
package com.yksj.monitor.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data //生成getter 和setter
@ToString //生成toString 方法
@AllArgsConstructor //生成全参的构造函数
@NoArgsConstructor //生成默认的构造函数,不带参数
public class Student {
private String name;
private Integer age;
//1.与 @ToString 效果相同,不能同时存在
/*@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}*/
// 2. 与 @NoArgsConstructor 效果相同,不能同时存在
/* public Student() {
}*/
// 3.与 @AllArgsConstructor 效果相同,不能同时存在
/*public Student(String name, Integer age) {
this.name = name;
this.age = age;
}*/
}
使用 @Slf4j 注解引入日志设置
HelloController.java
package com.yksj.monitor.controller;
import com.yksj.monitor.entity.MyConfig;
import com.yksj.monitor.entity.Stu;
import com.yksj.monitor.entity.Student;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import java.sql.SQLOutput;
//@Controller
@RestController
@Slf4j
public class HelloController {
// @ResponseBody
@RequestMapping("hello")
public String Hello() {
return "hello world-123";
}
@Autowired //实现依赖注入 DI
Stu stu;
@GetMapping("getStu")
public Object getStu() {
return stu; // 控制反转 IOC
}
//
@Autowired
MyConfig myConfig;
@GetMapping("myConfig")
public Object getMyCOnfig() {
return myConfig;
}
//在yml中实现自定义配置与表达式
@Value("${self.custom.config.sdkSecret}")
private String sdkSecret;
@Value("${self.custom.config.host}")
private String host;
@Value("${self.custom.config.port}")
private int port;
@GetMapping("myYmlConfig")
public Object myYmlConfig() {
return sdkSecret + "\t" + host + ":" + port;
}
@GetMapping("getStudent")
public Object getStudent() {
// 用的是 NoArgsConstructor 生成的无参数的构造函数
Student student = new Student();
student.setName("lxw-123");
student.setAge(20);
System.out.println(student);//Student(name=lxw-123, age=20)
//用的是 AllArgsConstructor,生成的有参数的构造函数
Student student1 = new Student("lxw-456", 23);
log.info(student1.toString());
log.debug("log-debug");
log.info("log-info");
log.warn("log-warn");
log.error("log-error");
return student;
}
}
3.接收参数常用注解
- @RequestParam: url的请求参数
- @PathVariable :路径的参数
- @RequestBody:请求体的对象,增加或修改时的,将对象信息通过body 传递给后端
- @RequestHeader:请求头中的参数,token,用户ID,鉴权
- @CookieValue:cookie 中保存的值
package com.yksj.monitor.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
@RestController
@Slf4j
@RequestMapping("stu")
public class StuController {
//测试url: http://localhost:8001/stu/get/9/11?id=1&age=22&name=w44
@GetMapping("get/{stuId}/{page}") //这里定义几个变量,请求时必须传递几个变量,可以不使用但必须传,否则报错
public String getStudents(@PathVariable("stuId") String stuId, //
// Integer page, //@PathVariable 获取路径中的变量, //page=null
@PathVariable("page") Integer page, //page=11
@RequestParam Integer id,
@RequestParam String name,
Integer age) {
// @RequestParam: 用于获得url中的请求参数 key=>value形式,如果参数变量名保持一致,该注解可省略
log.info("id={}", id);//id=1
log.info("name={}", name);//name=w44
log.info("stuId=" + stuId);//stuId=9
log.info("age=" + age); //age=22
log.info("page=" + page); //page=null
return "查询学生";
}
@PostMapping("create")
public String createStu(@RequestBody Map<String, Object> map,
@RequestHeader("token") String token,
@CookieValue("clientId") String clientId,
HttpServletRequest request) {
log.info("token=" + token);
log.info("clientId={}", clientId);
log.info("map={}", map.toString());
String HeaderToken = request.getHeader("token");
log.info("HeaderToken={}", HeaderToken);
return "添加学生";
}
}
3. 接口返回响应对象
区别:返回参数不同,object《==》JSONResult
//返回json 对象
@GetMapping("getStudent")
public Object getStudent() {
// 用的是 NoArgsConstructor 生成的无参数的构造函数
Student student = new Student();
student.setName("lxw-123");
student.setAge(20);
System.out.println(student);//Student(name=lxw-123, age=20)
//用的是 AllArgsConstructor,生成的有参数的构造函数
Student student1 = new Student("lxw-456", 23);
log.info(student1.toString());
log.debug("log-debug");
log.info("log-info");
log.warn("log-warn");
log.error("log-error");
return student;
}
//返回响应式结果
@GetMapping("getStudent")
public JSONResult getStudent() {
// 用的是 NoArgsConstructor 生成的无参数的构造函数
Student student = new Student();
student.setName("lxw-123");
student.setAge(20);
System.out.println(student);//Student(name=lxw-123, age=20)
//用的是 AllArgsConstructor,生成的有参数的构造函数
Student student1 = new Student("lxw-456", 23);
log.info(student1.toString());
log.debug("log-debug");
log.info("log-info");
log.warn("log-warn");
log.error("log-error");
return JSONResult.ok(stu);
}
如果单独返回状态OK,data 不返回
@GetMapping("getStudent")
public JSONResult getStudent() {
// 用的是 NoArgsConstructor 生成的无参数的构造函数
Student student = new Student();
student.setName("lxw-123");
student.setAge(20);
System.out.println(student);//Student(name=lxw-123, age=20)
//用的是 AllArgsConstructor,生成的有参数的构造函数
Student student1 = new Student("test-456", 23);
log.info(student1.toString());
log.debug("log-debug");
log.info("log-info");
log.warn("log-warn");
log.error("log-error");
return JSONResult.ok(); // ok 方法中不传递数据即可
}
4.上传文件
// 上传文件
@PostMapping("upload")
public String uploadFile(MultipartFile image) throws Exception {
image.transferTo(new File("/tmp/" + image.getOriginalFilename()));
return "上传成功";
}
application.yml 中配置限制文件上传大小
spring:
servlet:
multipart:
max-file-size: 500KB
max-request-size: 2MB
pom.xml 添加依赖
<!--spring boot 官方推荐的模版-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
并在 resoures/templets 目录下编写提示页面
error.html sprintboot 配置的默认的错误页面也是这个名字
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 style="color: brown"> 系统异常错误,请联系管理员!</h1>
</body>
</html>
出现问题:Could not transfer artifact org.thymeleaf:thymeleaf:jar:3.0.15.RELEASE from/to central (https://repo
提示框中有个:强制导入maven ,点击执行下OK,可以参考这个,但对我没用到
5.统一异常封装处理
前后端 分离场景下:
package com.yksj.monitor;
import com.yksj.monitor.utils.JSONResult;
import org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* 自定义的助手类:统一异常拦截处理
* 可以针对异常自定义去捕获去处理,返回指定的类型(json 类型)到前端
*/
@ControllerAdvice //为controller服务的
public class GraceExceptionHandler {
@Value("${spring.servlet.multipart.max-file-size}")
private String maxFileSize;
@ExceptionHandler(FileSizeLimitExceededException.class)//这里拦截异常,如果不想拦截,注释掉即可
@ResponseBody
public JSONResult ReturnFileSizeLimit(FileSizeLimitExceededException e) {
return JSONResult.errorMsg("文件大小不能超出" + maxFileSize);
}
}
6.实现拦截器
(1) 定义拦截器:
package com.yksj.monitor.controller.Interceptor;
import com.mysql.cj.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Slf4j
public class UserInfoInterceptor implements HandlerInterceptor {
/**
* 拦截请求,访问controller 之前
*
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
String userId = request.getHeader("UserId");
String userToken = request.getHeader("UserToken");
if (StringUtils.isEmptyOrWhitespaceOnly(userId) || StringUtils.isEmptyOrWhitespaceOnly(userToken)) {
log.error("用户信息不能为空");
return false;
}
// userId:1001 userToken:abc123
if (!userId.equalsIgnoreCase("1001")||!userToken.equalsIgnoreCase("abc123")){
log.error("用户没有权限");
return false;
}
//return true;
return HandlerInterceptor.super.preHandle(request, response, handler);
}
/**
* 请求访问到controller 之后,渲染视图之前
*
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
/**
* 请求访问到controller 之后,渲染视图之后
*
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
(2)配置注册拦截器
package com.yksj.monitor;
import com.yksj.monitor.controller.Interceptor.UserInfoInterceptor;
import org.springframework.context.annotation.Bean;
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 InterceptorConfig implements WebMvcConfigurer {
@Bean
public UserInfoInterceptor userInfoInterceptor(){
return new UserInfoInterceptor();
}
//注册拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(userInfoInterceptor()).
addPathPatterns("/upload").
addPathPatterns("/upload2"); //添加要拦截的路由,有几个需要拦截的加几个
WebMvcConfigurer.super.addInterceptors(registry);
}
}
https://github.com/lxw1844912514/java-api-demo.git
7. 定时任务
package com.yksj.monitor.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import java.time.LocalDateTime;
@Configuration // 2、标记配置类,使得springboot容器可以扫描到
@EnableScheduling // 1、开启定时任务
@Slf4j
public class MyTask {
// 3、添加一个任务,并且注明任务的运行表达式
// @Scheduled(cron = "*/5 * * * * ? ")
public void pulishMsg() {
log.warn("开始执行任务:" + LocalDateTime.now());
}
// 常用定时任务表达式
// 每隔5秒执行一次:*/5 * * * * ?
// 每隔1分钟执行一次:0 */1 * * * ?
// 每天23点执行一次: 0 0 23 * * ?
// 每天凌晨1点执行1次: 0 0 1 * * ?
//每月1号凌晨1点执行1次: 0 0 1 1 * ?
//每月最后一天凌晨23点执行一次:0 0 23 L * ?
//每周星期天凌晨1点执行一次:0 0 1 ?* L
// 在 23,26,29分执行一次:0 23,26,29 * * * ?
}
8.pagehelper实现分页出现报错循环依赖
com.github.pagehelper.autoconfigure.PageHelperAutoConfiguration
问题:pagehelper-spring-boot-starter 1.2.5不兼容最新springboot 2.6.1版本,报错
***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
┌──->──┐
| com.github.pagehelper.autoconfigure.PageHelperAutoConfiguration
└──<-──┘
Action:
Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.
The dependencies of some of the beans in the application context form a cycle:
┌──->──┐
| com.github.pagehelper.autoconfigure.PageHelperAutoConfiguration
└──<-──┘
这个报错的原因就是因为导入了pagehelper-spring-boot-starter这个依赖,依赖本身具有传递性,所以导致了出现mybatis这个依赖出现了多次导入造成循环依赖出不去
解决方法:
方法一:进行依赖排除,下图所示:
如果排除之后还出现该错误,就是版本出现冲突,把pagehelper的版本调高就Ok啦
方法二:可以自己手动指定版本导入也可以解决
我的pom.xml, 测试可行!
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 引入父工程sprintBoot(启动器starter),他里面包含了很多 sprintBoot的子工程-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!-- 打包格式 -->
<packaging>jar</packaging>
<!-- 打包插件 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
<layout>JAR</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<attach>false</attach>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<groupId>com.yksj</groupId>
<artifactId>monitor</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>monitor</name>
<description>monitor</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 整合MyBatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<!-- 通用Mapper启动器 -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.1.5</version>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>4.0.4</version>
</dependency>
<!--分页助手类-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.3.1</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.1</version>
<!-- 排除mybits的两个依赖-->
<!--<exclusions>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</exclusion>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</exclusion>
</exclusions>-->
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>2.3.1</version>
<scope>test</scope>
</dependency>
<!-- sprint boot 提供的开发者工具-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!--springboot场景启动器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!--spring boot 官方推荐的模版-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--引入springboot 默认的数据源(HicariCP)-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--引入数据库的驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
参考:https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper-spring-boot-starter/1.4.1
https://blog.csdn.net/SG753/article/details/123900452
https://github.com/pagehelper/pagehelper-spring-boot
9.java.lang.NoSuchMethodException: tk.mybatis.mapper.provider.base.BaseInsertProvider.<init>() 报错
发生这种情况一般考虑三种原因:
1.依赖是否是版本过低或过高
一般这种情况是很容易避免的,所以这里不用再进行赘述。
2.在控制器中是否使用了错误的注解
一般我们没有使用@Autowired注解或者是@Resource注解,或者是在@Controller注解上没有使用@ResponseBody注解等原因造成的。
3.就是我们在启动类上使用@MapperScanner注解时导错了包导致的
在没有引入tk.mybatis依赖的时候我们一般在启动类上使用org.mybatis.spring.annotation.MapperScan这个包里的注解 ,如下图所示:
但是在我们引用了tk.mybatis依赖时,我们需要使用tk.mybatis.spring.annotation.MapperScan这个包里的注解。即可解决问题。如下图所示:
参考:https://blog.csdn.net/qq_53636944/article/details/132651254
10.idea 快捷键
(1).生成:ctrl+N
(2).实现:alt+i ,重写 ALT+O
11.实现类和接口的关系
实现(implements)关键字
在面向对象编程中,实现类和接口的关系主要通过实现(implements)关键字来建立。当一个类使用implements
关键字后跟一个或多个接口名时,该类就承诺提供这些接口中所有方法的具体实现。这种关系确保了实现类遵循接口定义的规范,即实现了接口中声明的所有行为。12
- 接口的定义:接口是一种抽象类型,它只包含方法的声明,不包含方法的实现。接口主要用于定义一组行为,这些行为由实现类来具体实现。
- 实现类的责任:任何实现了一个或多个接口的类都必须提供这些接口中所有方法的实现。这种关系强制实现了代码的模块化和可插拔性,因为可以实现多个不同的类来满足同一个接口的不同需求。
- 多重实现的可能性:一个类可以实现多个接口,只要它提供了所有这些接口中方法的具体实现。这种能力使得类可以以灵活的方式组合多个接口的功能,从而增加了代码的复用性和扩展性。
总之,实现类和接口的关系是编程中的一个核心概念,它允许类以一种结构化和可维护的方式定义和扩展其行为。
12.常用校验注解
@NotNull 用于确保字段不为 null,适用于任何类型的字段,包括基本数据类型和对象引用。
@NotBlank 用于确保字符串字段不为空且长度大于 0,仅适用于字符串类型的字段。
@NotEmpty 用于确保集合、数组、Map 或者字符串类型的字段不为空。
@Min 和 @Max 用于确保数字字段的值在指定的范围内。
@Size 用于确保集合、数组或者字符串字段的大小在指定范围内。
@Pattern 使用正则表达式验证字符串字段的格式。
@Valid 用于嵌套验证,对一个对象的属性进行验证。
<!--引入校验-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
package com.yksj.monitor.entity.bo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.ToString;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.*;
import java.util.List;
@Data
@ToString
@AllArgsConstructor
public class StuBo {
private Integer id;
@NotEmpty // 空字符串视为有值
private String name;
@NotBlank //验证是否为空字符串或空或不传值
private String name1;
@NotNull
private Integer sex;
@Min(value = 8, message = "学生年龄最小8岁")
@Max(value = 60, message = "年龄最大60岁")
private Integer age;
@Range(min = 1, max = 20, message = "学生所在班级区间为1-18")
private Integer classroom;
@Size(min = 2, max = 5, message = "技能填写至少2个,最多5个")
private List<String> skill;
// @Length(min = 3, max = 8, message = "学生的英文名字长度区间在3-8")
private String englishName;
@Email(message = "邮箱格式不正确")
private String email;
/**
*
* 请求体:{"name":" ","name1":" ","classroom":" 20","skill":["php","java","js","css","go","rust"],"englishName":"test123456","email":"11@qq.com"}
* 返回值:
*{
* "status": 501,
* "msg": "error",
* "data": {
* "englishName": "学生的英文名字长度区间在3-8",
* "skill": "技能填写至少2个,最多5个",
* "sex": "不能为null",
* "name1": "不能为空"
* },
* "requestId": "70e23884-bb50-449d-9874-38c3e3726981"
* }
*/
}
import javax.validation.constraints.Size;
import java.util.List;
public class Example {
@Size(min = 2, max = 50, message = "用户名长度必须在2到50之间")
private String username;
@Size(min = 1, max = 10, message = "列表大小必须在1到10之间")
private List<String> items;
@Size(min = 1, max = 100, message = "数组长度必须在1到100之间")
private String[] array;
// Getters and setters
}
import javax.validation.constraints.Pattern;
public class Example {
@Pattern(regexp = "[a-zA-Z0-9]+", message = "用户名只能包含字母和数字")
private String username;
// Getters and setters
}
import javax.validation.Valid;
public class Outer {
@Valid
private Inner inner;
// Getters and setters
}
public class Inner {
@NotBlank(message = "姓名不能为空")
private String name;
// Getters and setters
}
- 控制器(Controller)中启用字段校验
在 Spring Boot 中,可以通过在控制器类或方法上添加 @Validated 注解来启用验证,并使用 @Valid 注解对请求对象进行验证。import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import javax.validation.Valid; @RestController @Validated // 注解表示启用验证 public class MyController { @PostMapping("/example") public String example(@RequestBody @Valid MyRequest request) { // 处理请求 return "Success"; } }
参考;https://blog.csdn.net/qq_25385555/article/details/139702515
13.查询操作
1.StuService.jva 服务类
package com.yksj.monitor.service;
import com.yksj.monitor.entity.Stu;
import java.util.List;
/**
* stu 服务接口
*/
public interface StuService {
/**
* 新增stu 到数据库
* @param stu
*/
public void savaStu(Stu stu);
/**
* 根据ID查询
* @param id
*/
public Stu queryById(String id);
/**
* 根据条件查询stu的list结果集
* @param id
* @param age
* @return
*/
public List<Stu> queryByCondition(String id,Integer age);
}
2.StuServiceImpl.java 实现类
方法一:适用于多种复杂查询的情况下,模糊查询,大于,小于等
@Override
public List<Stu> queryByCondition(String name, Integer age) {
Example example=new Example(Stu.class);
Example.Criteria criteria=example.createCriteria();
// criteria.andEqualTo("name",name); //等于
// criteria.andLike("name",name); // like模糊查询
criteria.andBetween("age",1,12); // 年龄在1-12岁之间的,包含1和12岁
// criteria.andEqualTo("age",age);
return stuMapper.selectByExample(example);
// return Collections.emptyList(); //返回空集合
}
方法二:仅适用于属性匹配,也就是说:只能在简单等于的情况下
@Override
public List<Stu> queryByCondition(String name, Integer age) {
//条件对象
Stu stu = new Stu();
stu.setName(name);
stu.setAge(age);
return stuMapper.select(stu);
}
3.StuController 控制器
// 根据ID查询用户信息 {{host}}/stu/getStuById?stuId=111
@GetMapping("getStuById")
public JSONResult getStuById(String stuId) {
Stu stu = stuService.queryById(stuId);
return JSONResult.ok(stu);
}
// 根据条件查询结果集 {{host}}/stu/getStuByCondition?name=test&age=1
@GetMapping("getStuByCondition")
public JSONResult getStuByCondition(String name, Integer age) {
List<Stu> stuList = stuService.queryByCondition(name, age);
// List<Stu> stuList = stuService.queryByCondition("lxw",33);
return JSONResult.ok(stuList);
}
14.变更数据源
sprintboot 2 默认数据源是 com.zaxxer.hikari.HikariDataSource,当要变更时,
在pom.xml 中添加如下
<!--引入阿里的druid 数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.5</version>
</dependency>
并在application.yml 中添加配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
获取当前数据源使用的是哪个:
@Autowired
private DataSource dataSource;
//method如果不写的话,那么get,post方式都能进入方法,但是不安全
@RequestMapping(value = {"/say"},method = RequestMethod.GET)
public String say(@RequestParam(value = "id",required = false,defaultValue = "0")String id){
return dataSource.toString();
}
如果想取消 DruidDataSource,需要在pom.xml 中注释掉添加的druid-spring-boot-starter依赖,并更新Maven即可,暂时没想到好办法,有好的办法欢迎评论指正。
15.开启mybatis的日志实现,打印SQL语句到控制台
# mybatis 相关的配置
mybatis:
type-aliases-package: com.yksj.entity #所有数据库表逆向后--映射后的实体类【entity/pojo/Bean】
mapper-locations: classpath:mapper/*.xml #所有mapper映射的文件所在的目录位置
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启mybatis的日志实现,可以在控制台打印输出SQL语句日志 ,生成环境要去掉,否则日志非常大
16. aop 切面日志
package com.yksj.monitor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.aspectj.lang.annotation.Aspect;
/**
* 系统日志切面
*/
@Slf4j
@Aspect // 使用@Aspect注解声明一个切面
@Component
public class AopLogSout {
/**
* AOP 通知类型
* 1. 前置通知
* 2.后置通知
* 3.环绕通知
* 4.异常通知
* 5.最终通知
*/
/**
* 这里我们使用注解的形式
* 当然,我们也可以通过切点表达式直接指定需要拦截的package,需要拦截的class 以及 method
* 切点表达式: execution(...)
* execution(public * *(..)) 任意的公共方法
* execution(* set*(..)) 以set开头的所有的方法
* execution(* com.LoggerApply.*(..))com.LoggerApply这个类里的所有的方法
* execution(* com.annotation.*.*(..))com.annotation包下的所有的类的所有的方法
* execution(* com.annotation..*.*(..))com.annotation包及子包下所有的类的所有的方法
* execution(* com.annotation..*.*(String,?,Long)) com.annotation包及子包下所有的类的有三个参数,第一个参数为String类型,第二个参数为任意类型,第三个参数为Long类型的方法
* execution(@annotation(com.lingyejun.annotation.Lingyejun))
*/
// @Pointcut("@annotation(com.space.aspect.anno.SysLog)")
// public void logPointCut() {}
/**
* 环绕通知 @Around, 当然也可以使用 @Before (前置通知) @After (后置通知)
* @param joinPoint
* @return
* @throws Throwable
*/
// @Around("execution( * com.yksj.monitor.service..*.*(..))")
@Around("execution( * com.yksj.monitor.service..*.*(..))")
public Object printLogTimeOfService(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("正在执行:类名:{}, 方法名:{}", joinPoint.getTarget().getClass(), joinPoint.getSignature().getName());
long startTime = System.currentTimeMillis();
Object result = joinPoint.proceed();
long endTime = System.currentTimeMillis();
long excTimes = endTime - startTime;
log.info("开始时间: {}, 结束时间: {}", startTime,endTime);
if (excTimes > 3000) {
log.error("-当前执行耗时: {}ms", excTimes);
} else if (excTimes > 10) {
log.warn("--当前执行耗时: {}ms", excTimes);
} else {
log.info("---当前执行耗时: {}ms", excTimes);
}
return result;
}
}
引入spring-boot的aop实现
<!--引入spring-boot的aop实现-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
三、thymeleaf 模版使用
1. thymeleaf 模版与基本使用
注意:使用的是 th:text, 不是 th:value .
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>hello test!</h1>
<span th:text="${age}"></span>
<h2 th:text="${name}"></h2>
</body>
</html>
#模版
thymeleaf:
prefix: classpath:/templates/html/
suffix: .html
package com.yksj.monitor.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@Slf4j
@RequestMapping("thyme")
public class ThymeleafController {
@GetMapping("view")
public String view(Model model) {
model.addAttribute("name", "lxw");
model.addAttribute("age", 11);
return "teacher"; //模版文件名
}
}
四、配置
1.使用profile 多环境配置
application.yml
spring:
profiles:
active: dev #走dev 配置文件中的环境
server:
port: 8001
spring:
profiles:
active: dev #走dev 配置文件中的环境
datasource:
# type: com.alibaba.druid.pool.DruidDataSource #引入自定义的阿里云数据源
# type: com.zaxxer.hikari.HikariDataSource #指定数据源的类型HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/monitor?characterEncoding=utf-8&useSSL=false&useLegacyDatetimeCode=false&serverTimezone=UTC
username: root
password: 123456
hikari:
connection-timeout: 30000 #等待连接池分配链接的最大时长(毫秒),超过这个时长断开?
minimum-idle: 5 #最小连接数
maximum-pool-size: 20 #最大连接数
auto-commit: true #自动提交
idle-timeout: 600000 #连接超时的最大时长(豪秒),超时则被释放
pool-name: DataSourceHikariCP #连接池名字
max-lifetime: 1800000 #连接的生命时长(毫秒),超时而且没被使用则被释放
connection-test-query: SELECT 1
banner:
location: banner/fozu.txt
# mvc:
# static-path-pattern: /haha/**
# 访问URL路径:http://localhost:8001/haha/3.jpg, 访问的是static 目录下的3.jpg 图片,/haha/** 定义的是路由前缀,
# http://localhost:8001/ 默认访问的是static 目录下单 index.html 文件
# mvc:
# static-path-pattern: /static/**
#静态资源文件配置,默认是 static 目录
#模版
thymeleaf:
prefix: classpath:/templates/html/
suffix: .html
web:
resources:
static-locations:
[ classpath:/haha/ ]
#限制上传文件大小
servlet:
multipart:
max-file-size: 500KB
max-request-size: 2MB
# 配置日期格式化
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: Asia/Shanghai
# mybatis 相关的配置
mybatis:
type-aliases-package: com.yksj.entity #所有数据库表逆向后--映射后的实体类【entity/pojo/Bean】
mapper-locations: classpath:mapper/*.xml #所有mapper映射的文件所在的目录位置
#configuration:
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启mybatis的日志实现,可以在控制台打印输出SQL语句日志 ,生成环境要去掉,否则日志非常大
#通用mapper配置
mapper:
mappers: com.yksj.monitor.my.mapper.MyMapper #所有mapper都需要实现的接口
not-empty: false #在进行数据库操作的时候,判断一个属性是否为空的时候,是否需要自动追加不为空字符串的判断
# 例如 userName!=null 后面不需要 userName!=""
identity: MYSQL #身份标识
#分页插件助手的配置
pagehelper:
support-methods-arguments: true
helper-dialect: mysql #方言
#自动义配置
self:
custom:
config:
sdkSecret: 123
host: https://www.baidu.com
port: ${server.port}
application-dev.xml
server:
port: 8011