## 一、SpringBoot介绍 #### 1、两大核心 起步依赖:Spring Boot 提供了一系列名为 `spring-boot-starter-*` 的依赖项。这些依赖项不是单个库,而是一组经过精心挑选、能完美协同工作的依赖集合。例如,你只需要引入 `spring-boot-starter-web`,它就自动帮你引入了 Spring MVC、Tomcat、Jackson(用于 JSON 处理)等所有相关依赖,并且保证了版本兼容性。 自动配置:这是 Spring Boot 最核心的特性。你只需要在项目中引入了相关的依赖(比如 `spring-boot-starter-web`),Spring Boot 就会自动为你配置好运行一个 Web 应用所需的大部分组件(如 Tomcat 服务器、Spring MVC 等),你无需或只需很少的配置。 #### 2、Spring Boot 与 Spring 框架的区别 为了更好地理解,我们可以用一个形象的比喻: - Spring 框架就像一个汽车零部件工厂。它提供了发动机(IoC容器)、变速箱(AOP)、底盘(Data Access)等所有高质量的零件。但要造出一辆能跑的车,你需要自己懂得如何选择零件、如何组装、如何调试。这个过程复杂且容易出错。 - Spring Boot 则像一个汽车组装流水线或一台“整车”。它已经用 Spring 的零件帮你把车造好了(自动配置),你只需要坐进去,加上油(写上业务代码),就能直接开走。它简化了“组装”的过程。 下面是具体的区别对比: | 特性 | Spring Framework | Spring Boot | | :----------- | :------------------------------------------------------------------------ | :----------------------------------------------------------------------------- | | **核心目标** | 提供一个全面的编程和配置模型,用于构建任何类型的Java应用。 | 快速创建可以独立运行的、生产级的基于Spring的应用程序。 | | **配置方式** | **显式配置**为主。需要大量使用XML配置文件或Java注解来进行配置,比较繁琐。 | **约定大于配置,自动配置**为主。大部分配置都已预先写好,极大减少了配置工作量。 | | **项目搭建** | 需要手动管理依赖和版本兼容性,搭建过程复杂。 | 通过**起步依赖**快速搭建,依赖管理自动化。 | | **部署方式** | 通常需要将应用打包成 WAR 文件,然后部署到外部的 Web 服务器(如 Tomcat)。 | 应用打包成可执行的**JAR** 文件,**内嵌服务器**,可以直接运行。 | | **上手难度** | 较高,需要深入理解Spring的各个模块和配置原理。 | **非常简单**,对新手友好,能快速上手并构建出可用的应用。 | | **功能范围** | Spring Boot 是构建在 Spring 框架之上的一个项目,它简化了 Spring 的使用。 | | ## 二、SpringBoot项目创建 #### 1、官方Installer [Spring Initializr](https://start.spring.io/)  #### 2、IDEA创建 新建 -> 选择Spring Boot项目 选择合适的依赖 ## 三、配置文件 #### 1、修改服务器的端口号 若出现`8080`端口被占用,可以在`application.properties`修改 ```properties server.port=8090 ``` #### 2、设置应用程序访问上下文路径 ```properties # 原本链接:http://localhost:8090/ctrl/hello # 设置后链接:http://localhost:8090/dome/ctrl/hello server.servlet.context-path=/dome ``` #### 3、设置日志输出级别 ```properties # 设置SpringBoot日志输出级别(error、warn、info、debug) logging.level.org.springframework=debug # 也可以只输出自己项目下的日志 logging.level.cn.doooog.[project]=debug ``` 修改完成后重新访问即可 #### 4、yml文件格式配置 * 大小写敏感:键名区分大小写。 * 缩进分割:利用缩进代替`.` * 不要使用 Tab:确保编辑器设置为将 Tab 转换为空格。 * 字符串引号:大多数情况下可省略,但特殊字符需加引号。 * 文档分隔符:多个 YAML 文档可用 `---` 分隔。 ``` # 文档1 server: ... --- # 文档2 database: ... ``` YAML 的简洁语法使其成为配置文件的理想选择,但需注意缩进和格式的准确性。 例如`application.properties`可以改为`application.yaml` ```yml spring : application: name:SpringBoot logging : level :cn.doooog.springboot=debug ``` #### 5、设置Banner图标 在`rescources`根目录下创建`banner.txt`默认使用该内容 关闭Banner图标 ```yml spring.main.banner-mode=off ``` ## 四、Controller层 #### 1、测试项目 在项目根目录创建`controller/MyController.java` ```java package cn.doooog.springboot.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller @RequestMapping("/api") public class MyController { @GetMapping("/hello") @ResponseBody public String hello(){ return "Hello SpringBoot"; } } ``` #### 2、使用Jetty服务器(可选) 修改`pom.xml`将Tomcat服务器依赖排除 ```xml org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-tomcat org.springframework.boot spring-boot-starter-jetty ``` #### 3、参数接收 ##### 普通参数 ```java @GetMapping("/params") @ResponseBody public String params(@RequestParam(name = "name",defaultValue = "test") String name, @RequestParam(name = "age",required = false) Integer age) { return "name:" + name + "; age:" + age; } ``` **注意**:若参数为可选参数,使用`required`属性时必须为引用类型参数,因为会被赋值为`null`;`POST`请求必须使用`@RequestParam`注解,否则可能会出现错误。 ##### Restful 风格 使用`@PathVariable`注解标记动态路径的参数 ```java @GetMapping("/restful/{name}/{age}") @ResponseBody public String restful(@PathVariable String name, @PathVariable Integer age) { return "name:" + name + "; age:" + age; } ``` ##### Json参数 po对象 ```java package cn.doooog.springboot.po; public class User { private String name; private String sex; private int age; public User(String name, String sex, int age) { this.name = name; this.sex = sex; this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", sex='" + sex + '\'' + ", age=" + age + '}'; } public User() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } ``` 处理器方法 ```java @RequestMapping("/user") public User user(@RequestBody User user) { return user; } ``` ##### List参数 ```java @RequestMapping("/user-list") public List user(@RequestBody List userList) { return userList; } ``` #### 4、`@RestController` 联合注解:`@Controller`与`@ResponseBody`,相当于把这俩注解结合在一起。 ```java package cn.doooog.springboot.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/api") public class MyController { @GetMapping("/hello") public String hello() { return "Hello SpringBoot"; } @GetMapping("/params") public String params(@RequestParam(name = "name",defaultValue = "test") String name, @RequestParam(name = "age",required = false) Integer age) { return "name:" + name + "; age:" + age; } @PostMapping("/params") public String params2(@RequestParam(name = "name",defaultValue = "test") String name, @RequestParam(name = "age",required = false) Integer age) { return "name:" + name + "; age:" + age; } @GetMapping("/restful/{name}/{age}") public String restful(@PathVariable String name, @PathVariable Integer age) { return "name:" + name + "; age:" + age; } } ``` ## 五、整合MyBatis #### 1、添加依赖包 #### 2、添加数据库配置 修改`application.properties`文件 ```properties spring.datasource.url=jdbc:mysql://localhost:3306/database?characterEncoding=utf-8 spring.datasource.username=username spring.datasource.password=password spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver ``` #### 3、po层 创建`po/Emp.java` ```java package cn.doooog.springboot.po; import java.util.Objects; public class Emp { private Integer EMPno; private String ename; private String job; private Integer mgr; private String hiredate; private Double sal; private Double comm; private Integer DEPTno; public Emp() { } public Emp(Integer EMPno) { this.EMPno = EMPno; } public Emp(Integer EMPno, String ename, String job, Integer mgr, String hiredate, Double sal, Double comm, Integer DEPTno) { this.EMPno = EMPno; this.ename = ename; this.job = job; this.mgr = mgr; this.hiredate = hiredate; this.sal = sal; this.comm = comm; this.DEPTno = DEPTno; } public Integer getDEPTno() { return DEPTno; } public void setDEPTno(Integer DEPTno) { this.DEPTno = DEPTno; } public Double getComm() { return comm; } public void setComm(Double comm) { this.comm = comm; } public Double getSal() { return sal; } public void setSal(Double sal) { this.sal = sal; } public String getHiredate() { return hiredate; } public void setHiredate(String hiredate) { this.hiredate = hiredate; } public Integer getMgr() { return mgr; } public void setMgr(Integer mgr) { this.mgr = mgr; } public String getJob() { return job; } public void setJob(String job) { this.job = job; } public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public Integer getEMPno() { return EMPno; } public void setEMPno(Integer EMPno) { this.EMPno = EMPno; } @Override public String toString() { return "Emp{" + "EMPno=" + EMPno + ", ename='" + ename + '\'' + ", job='" + job + '\'' + ", mgr='" + mgr + '\'' + ", hiredate='" + hiredate + '\'' + ", sal=" + sal + ", comm=" + comm + ", DEPTno=" + DEPTno + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Emp emp)) return false; return Objects.equals(getEMPno(), emp.getEMPno()) && Objects.equals(getEname(), emp.getEname()) && Objects.equals(getJob(), emp.getJob()) && Objects.equals(getMgr(), emp.getMgr()) && Objects.equals(getHiredate(), emp.getHiredate()) && Objects.equals(getSal(), emp.getSal()) && Objects.equals(getComm(), emp.getComm()) && Objects.equals(getDEPTno(), emp.getDEPTno()); } @Override public int hashCode() { return Objects.hash(getEMPno(), getEname(), getJob(), getMgr(), getHiredate(), getSal(), getComm(), getDEPTno()); } } ``` #### 4、mapper层 创建`mapper/EmpMapper.java`接口 ```java package cn.doooog.springboot.mapper; import cn.doooog.springboot.po.Emp; import cn.doooog.springboot.provider.EmpProvider; import org.apache.ibatis.annotations.*; import java.util.List; public interface EmpMapper { @Select("select * from EMP limit #{page},#{size}") List listEmpAll(@Param("page") int page,@Param("size") int size); @Select("select * from EMP where EMPno=#{EMPno}") Emp getEmpById(Integer EMPno); @Delete("delete from EMP where EMPno=#{EMPno}") int deleteEmpById(Integer EMPno); @InsertProvider(type = EmpProvider.class, method = "addEmp") @Options(useGeneratedKeys = true, keyProperty = "EMPno", keyColumn = "EMPno") int addEmp(Emp emp); @UpdateProvider(type = EmpProvider.class, method = "updateEmpById") int updateEmpById(Emp emp); } ``` 修改`/Application.java` ```java package cn.doooog.springboot; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @MapperScan("cn.doooog.springboot.mapper") public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` **注意**:必须在类名上方添加`@Mapper`,或在SpringBoot启动类添加注解`@MapperSacn("mapper层的包路径")` 创建`provider/EmpProvider.java` ```java package cn.doooog.springboot.provider; import cn.doooog.springboot.po.Emp; import org.apache.ibatis.jdbc.SQL; public class EmpProvider { public String addEmp(Emp emp) { return new SQL() {{ INSERT_INTO("EMP"); if (emp.getEMPno() != null) VALUES("EMPno", emp.getEMPno() + ""); if (emp.getEname() != null && !emp.getEname().isEmpty()) VALUES("ename", "'" + emp.getEname() + "'"); if (emp.getJob() != null && !emp.getJob().isEmpty()) VALUES("job", "'" + emp.getJob() + "'"); if (emp.getMgr() != null) VALUES("mgr", emp.getMgr() + ""); if (emp.getHiredate() != null && !emp.getHiredate().isEmpty()) VALUES("hiredate", "'" + emp.getHiredate() + "'"); if (emp.getSal() != null) VALUES("sal", emp.getSal() + ""); if (emp.getComm() != null) VALUES("comm", emp.getComm() + ""); if (emp.getDEPTno() != null) VALUES("DEPTno", emp.getDEPTno() + ""); }}.toString(); } public String updateEmpById(Emp emp) { return new SQL() {{ UPDATE("EMP"); if (emp.getEname() != null && !emp.getEname().isEmpty()) SET("ename=#{ename}"); if (emp.getJob() != null && !emp.getJob().isEmpty()) SET("job=#{job}"); if (emp.getMgr() != null) SET("mgr=#{mgr}"); if (emp.getHiredate() != null && !emp.getHiredate().isEmpty()) SET("hiredate=#{hiredate}"); if (emp.getSal() != null) SET("sal=#{sal}"); if (emp.getComm() != null) SET("comm=#{comm}"); if (emp.getDEPTno() != null) SET("DEPTno=#{DEPTno}"); WHERE("EMPno=#{EMPno}"); }}.toString(); } } ``` #### 5、格式化返回数据 创建`po/ResponseData.java`类 ```java package cn.doooog.springboot.po; public class ResponseData { private Integer code; private String msg; private T data; public ResponseData(int code, String msg, T data) { this.code = code; this.msg = msg; this.data = data; } public ResponseData() { } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public Object getData() { return data; } public void setData(T data)、 { this.data = data; } } ``` #### 6、service层 创建`service/EmpService.java` ```java package cn.doooog.springboot.service; import cn.doooog.springboot.mapper.EmpMapper; import cn.doooog.springboot.po.Emp; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class EmpService { @Autowired private EmpMapper empMapper; public List listEmpAll() { return listEmpAll(1, 20); } public List listEmpAll(int page, int size) { return empMapper.listEmpAll((page - 1) * size, size); } public Emp getEmpById(Integer EMPno) { if (EMPno == null || EMPno <= 0) return null; return empMapper.getEmpById(EMPno); } public int addEmp(Emp emp) { if (emp == null || emp.equals(new Emp())) return 0; int res = empMapper.addEmp(emp); if (res < 1) return 0; return emp.getEMPno(); } public int updateEmpById(Emp emp) { if (emp == null || emp.equals(new Emp()) || emp.getEMPno() == null || emp.getEMPno() <= 0) return 0; return empMapper.updateEmpById(emp); } public int deleteEmpById(Integer EMPno) { if (EMPno == null || EMPno <= 0) return 0; return empMapper.deleteEmpById(EMPno); } } ``` #### 7、controller层 创建`controller/EmpController.java` ```java package cn.doooog.springboot.controller; import cn.doooog.springboot.po.Emp; import cn.doooog.springboot.po.ResponseData; import cn.doooog.springboot.service.EmpService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping("/api/emp") public class EmpController { @Autowired private EmpService empService; @RequestMapping("/list-all") public ResponseData> listEmpAll() { List list = empService.listEmpAll(); if (list != null && !list.isEmpty()) return new ResponseData<>(200, "查询成功", list); return new ResponseData<>(203, "查询失败", null); } @GetMapping("/id") public ResponseData getEmpById(@RequestBody @RequestParam("id") Integer EMPno) { if (EMPno == null || EMPno <= 0) return new ResponseData<>(203, "id不合法", null); Emp emp = empService.getEmpById(EMPno); if (emp != null) return new ResponseData<>(200, "查询成功", emp); return new ResponseData<>(203, "未找到该id", null); } @PostMapping("/id") public ResponseData addEmp(@RequestBody Emp emp) { if (emp == null || emp.equals(new Emp())) return new ResponseData<>(203, "新增内容不能为空", null); int res = empService.addEmp(emp); if (res < 1) return new ResponseData<>(203, "新增失败", null); return new ResponseData<>(200, "新增成功", emp); } @PutMapping("/id") public ResponseData updateEmp(@RequestBody Emp emp) { if (emp == null || emp.getEMPno() == null || emp.getEMPno() <= 0) return new ResponseData<>(203, "id不合法", null); if (emp.equals(new Emp(emp.getEMPno()))) return new ResponseData<>(203, "更改内容不能为空", null); int res = empService.updateEmpById(emp); if (res < 1) return new ResponseData<>(203, "修改失败", null); return new ResponseData<>(200, "修改成功", empService.getEmpById(emp.getEMPno())); } @PatchMapping("/id") public ResponseData updateEmp2(@RequestBody Emp emp) { if (emp == null || emp.getEMPno() == null || emp.getEMPno() <= 0){ return new ResponseData<>(203, "id不合法", null);} if (emp.equals(new Emp(emp.getEMPno()))) return new ResponseData<>(203, "更改内容不能为空", null); int res = empService.updateEmpById(emp); if (res < 1) return new ResponseData<>(203, "修改失败", null); return new ResponseData<>(200, "修改成功", empService.getEmpById(emp.getEMPno())); } @DeleteMapping("/id") public ResponseData deleteEmp(@RequestBody Emp emp) { if (emp.getEMPno() == null || emp.getEMPno() <= 0) return new ResponseData<>(203, "id不合法", null); Emp emp2 = empService.getEmpById(emp.getEMPno()); if (emp2 == null || emp2.equals(new Emp())) return new ResponseData<>(203, "未找到该id", null); int res = empService.deleteEmpById(emp.getEMPno()); if (res < 1) return new ResponseData<>(203, "删除失败", null); return new ResponseData<>(200, "删除成功", emp2); } } ``` 成功如下  #### 8、映射`.XML`文件 修改`application.properties`配置,添加别名 ```properties # MyBatisConfig mybatis.type-aliases-package=cn.doooog.[project].po mybatis.mapper-locations=cn.doooog.[project].mapper.*.xml ``` 在`resources`文件夹下创建与项目包全名路径相同的目录,比如`cn/doooog/springboot/mapper/EmpMapper.xml` ## 六、解决跨域访问 #### 1、配置单个请求 在处理器上添加`@CrossOrigin("*")` ```java @CrossOrigin("*") @RequestMapping("/list-all") public ResponseData> listEmpAll(@RequestParam(name = "page", defaultValue = "1") int page, @RequestParam(name = "size", defaultValue = "10") int size) { List list = empService.listEmpAll(page, size); if (list != null && !list.isEmpty()) return new ResponseData<>(200, "查询成功", list); return new ResponseData<>(203, "查询失败", null); } ``` #### 2、过滤器 创建`util/GlobalCorsConfig.java` ```java package cn.doooog.springboot.util; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class GlobalCorsConfig { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { // 重写父类提供的跨域请求处理的接口 @Override public void addCorsMappings(CorsRegistry registry) { // 添加映射路径 registry.addMapping("/**") .allowedOriginPatterns("*") // 放行哪些域名,可以多个 .allowCredentials(true) // 是否发送Cookie信息 .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS", "PATCH") // 放行哪些请求方式 .allowedHeaders("*") // 放行哪些原始域(头部信息) .exposedHeaders("Header1", "Header2") // 暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息) .maxAge(3600); // 预请求的结果有效期,默认1800分钟,3600是一小时 } }; } } ``` #### 3、拦截器 创建`util/WebMvcConfig.java` ```java package cn.doooog.springboot.util; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { /* * addMapping:配置可以被跨域的路径,可以任意配置,可以具体到直接请求路径。 * allowCredentials:是否开启Cookie * allowedMethods:允许的请求方式,如:POST、GET、PUT、DELETE等。 * allowedOrigins:允许访问的url,可以固定单条或者多条内容 * allowedHeaders:允许的请求header,可以自定义设置任意请求头信息。 * maxAge:配置预检请求的有效时间 */ registry.addMapping("/**") .allowedOriginPatterns("*") // 放行哪些域名,可以多个 .allowCredentials(true) // 是否发送Cookie信息 .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS", "PATCH") // 放行哪些请求方式 .allowedHeaders("*") // 放行哪些原始域(头部信息) .exposedHeaders("Header1", "Header2") // 暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息) .maxAge(3600); } } ``` Loading... ## 一、SpringBoot介绍 #### 1、两大核心 起步依赖:Spring Boot 提供了一系列名为 `spring-boot-starter-*` 的依赖项。这些依赖项不是单个库,而是一组经过精心挑选、能完美协同工作的依赖集合。例如,你只需要引入 `spring-boot-starter-web`,它就自动帮你引入了 Spring MVC、Tomcat、Jackson(用于 JSON 处理)等所有相关依赖,并且保证了版本兼容性。 自动配置:这是 Spring Boot 最核心的特性。你只需要在项目中引入了相关的依赖(比如 `spring-boot-starter-web`),Spring Boot 就会自动为你配置好运行一个 Web 应用所需的大部分组件(如 Tomcat 服务器、Spring MVC 等),你无需或只需很少的配置。 #### 2、Spring Boot 与 Spring 框架的区别 为了更好地理解,我们可以用一个形象的比喻: - Spring 框架就像一个汽车零部件工厂。它提供了发动机(IoC容器)、变速箱(AOP)、底盘(Data Access)等所有高质量的零件。但要造出一辆能跑的车,你需要自己懂得如何选择零件、如何组装、如何调试。这个过程复杂且容易出错。 - Spring Boot 则像一个汽车组装流水线或一台“整车”。它已经用 Spring 的零件帮你把车造好了(自动配置),你只需要坐进去,加上油(写上业务代码),就能直接开走。它简化了“组装”的过程。 下面是具体的区别对比: | 特性 | Spring Framework | Spring Boot | | :----------- | :------------------------------------------------------------------------ | :----------------------------------------------------------------------------- | | **核心目标** | 提供一个全面的编程和配置模型,用于构建任何类型的Java应用。 | 快速创建可以独立运行的、生产级的基于Spring的应用程序。 | | **配置方式** | **显式配置**为主。需要大量使用XML配置文件或Java注解来进行配置,比较繁琐。 | **约定大于配置,自动配置**为主。大部分配置都已预先写好,极大减少了配置工作量。 | | **项目搭建** | 需要手动管理依赖和版本兼容性,搭建过程复杂。 | 通过**起步依赖**快速搭建,依赖管理自动化。 | | **部署方式** | 通常需要将应用打包成 WAR 文件,然后部署到外部的 Web 服务器(如 Tomcat)。 | 应用打包成可执行的**JAR** 文件,**内嵌服务器**,可以直接运行。 | | **上手难度** | 较高,需要深入理解Spring的各个模块和配置原理。 | **非常简单**,对新手友好,能快速上手并构建出可用的应用。 | | **功能范围** | Spring Boot 是构建在 Spring 框架之上的一个项目,它简化了 Spring 的使用。 | | ## 二、SpringBoot项目创建 #### 1、官方Installer [Spring Initializr](https://start.spring.io/)  #### 2、IDEA创建 新建 -> 选择Spring Boot项目 <img src="https://pic.soki.me/file/piclist/image-20251103093339150.png" alt="image-20251103093339150" style="zoom: 50%;" style=""> 选择合适的依赖 <img src="https://pic.soki.me/file/piclist/image-20251103093849720.png" alt="image-20251103093849720" style="zoom:50%;" style=""> ## 三、配置文件 #### 1、修改服务器的端口号 若出现`8080`端口被占用,可以在`application.properties`修改 ```properties server.port=8090 ``` #### 2、设置应用程序访问上下文路径 ```properties # 原本链接:http://localhost:8090/ctrl/hello # 设置后链接:http://localhost:8090/dome/ctrl/hello server.servlet.context-path=/dome ``` #### 3、设置日志输出级别 ```properties # 设置SpringBoot日志输出级别(error、warn、info、debug) logging.level.org.springframework=debug # 也可以只输出自己项目下的日志 logging.level.cn.doooog.[project]=debug ``` 修改完成后重新访问即可 #### 4、yml文件格式配置 * 大小写敏感:键名区分大小写。 * 缩进分割:利用缩进代替`.` * 不要使用 Tab:确保编辑器设置为将 Tab 转换为空格。 * 字符串引号:大多数情况下可省略,但特殊字符需加引号。 * 文档分隔符:多个 YAML 文档可用 `---` 分隔。 ``` # 文档1 server: ... --- # 文档2 database: ... ``` YAML 的简洁语法使其成为配置文件的理想选择,但需注意缩进和格式的准确性。 例如`application.properties`可以改为`application.yaml` ```yml spring : application: name:SpringBoot logging : level :cn.doooog.springboot=debug ``` #### 5、设置Banner图标 在`rescources`根目录下创建`banner.txt`默认使用该内容 关闭Banner图标 ```yml spring.main.banner-mode=off ``` ## 四、Controller层 #### 1、测试项目 在项目根目录创建`controller/MyController.java` ```java package cn.doooog.springboot.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller @RequestMapping("/api") public class MyController { @GetMapping("/hello") @ResponseBody public String hello(){ return "Hello SpringBoot"; } } ``` #### 2、使用Jetty服务器(可选) 修改`pom.xml`将Tomcat服务器依赖排除 ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <!--web起步依赖环境中,排除Tomcat起步依赖--> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <!--添加Jetty起步依赖,版本由SpringBoot的starter控制--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency> ``` #### 3、参数接收 ##### 普通参数 ```java @GetMapping("/params") @ResponseBody public String params(@RequestParam(name = "name",defaultValue = "test") String name, @RequestParam(name = "age",required = false) Integer age) { return "name:" + name + "; age:" + age; } ``` **注意**:若参数为可选参数,使用`required`属性时必须为引用类型参数,因为会被赋值为`null`;`POST`请求必须使用`@RequestParam`注解,否则可能会出现错误。 ##### Restful 风格 使用`@PathVariable`注解标记动态路径的参数 ```java @GetMapping("/restful/{name}/{age}") @ResponseBody public String restful(@PathVariable String name, @PathVariable Integer age) { return "name:" + name + "; age:" + age; } ``` ##### Json参数 po对象 ```java package cn.doooog.springboot.po; public class User { private String name; private String sex; private int age; public User(String name, String sex, int age) { this.name = name; this.sex = sex; this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", sex='" + sex + '\'' + ", age=" + age + '}'; } public User() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } ``` 处理器方法 ```java @RequestMapping("/user") public User user(@RequestBody User user) { return user; } ``` <img src="https://pic.soki.me/file/piclist/image-20251103105828969.png" alt="image-20251103105828969" style="zoom: 50%;" style=""> ##### List参数 ```java @RequestMapping("/user-list") public List<User> user(@RequestBody List<User> userList) { return userList; } ``` <img src="https://pic.soki.me/file/piclist/image-20251103110033328.png" alt="image-20251103110033328" style="zoom:50%;" style=""> #### 4、`@RestController` 联合注解:`@Controller`与`@ResponseBody`,相当于把这俩注解结合在一起。 ```java package cn.doooog.springboot.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/api") public class MyController { @GetMapping("/hello") public String hello() { return "Hello SpringBoot"; } @GetMapping("/params") public String params(@RequestParam(name = "name",defaultValue = "test") String name, @RequestParam(name = "age",required = false) Integer age) { return "name:" + name + "; age:" + age; } @PostMapping("/params") public String params2(@RequestParam(name = "name",defaultValue = "test") String name, @RequestParam(name = "age",required = false) Integer age) { return "name:" + name + "; age:" + age; } @GetMapping("/restful/{name}/{age}") public String restful(@PathVariable String name, @PathVariable Integer age) { return "name:" + name + "; age:" + age; } } ``` ## 五、整合MyBatis #### 1、添加依赖包 <img src="https://pic.soki.me/file/piclist/image-20251103110252354.png" alt="image-20251103110252354" style="zoom:50%;" style=""> #### 2、添加数据库配置 修改`application.properties`文件 ```properties spring.datasource.url=jdbc:mysql://localhost:3306/database?characterEncoding=utf-8 spring.datasource.username=username spring.datasource.password=password spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver ``` #### 3、po层 创建`po/Emp.java` ```java package cn.doooog.springboot.po; import java.util.Objects; public class Emp { private Integer EMPno; private String ename; private String job; private Integer mgr; private String hiredate; private Double sal; private Double comm; private Integer DEPTno; public Emp() { } public Emp(Integer EMPno) { this.EMPno = EMPno; } public Emp(Integer EMPno, String ename, String job, Integer mgr, String hiredate, Double sal, Double comm, Integer DEPTno) { this.EMPno = EMPno; this.ename = ename; this.job = job; this.mgr = mgr; this.hiredate = hiredate; this.sal = sal; this.comm = comm; this.DEPTno = DEPTno; } public Integer getDEPTno() { return DEPTno; } public void setDEPTno(Integer DEPTno) { this.DEPTno = DEPTno; } public Double getComm() { return comm; } public void setComm(Double comm) { this.comm = comm; } public Double getSal() { return sal; } public void setSal(Double sal) { this.sal = sal; } public String getHiredate() { return hiredate; } public void setHiredate(String hiredate) { this.hiredate = hiredate; } public Integer getMgr() { return mgr; } public void setMgr(Integer mgr) { this.mgr = mgr; } public String getJob() { return job; } public void setJob(String job) { this.job = job; } public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public Integer getEMPno() { return EMPno; } public void setEMPno(Integer EMPno) { this.EMPno = EMPno; } @Override public String toString() { return "Emp{" + "EMPno=" + EMPno + ", ename='" + ename + '\'' + ", job='" + job + '\'' + ", mgr='" + mgr + '\'' + ", hiredate='" + hiredate + '\'' + ", sal=" + sal + ", comm=" + comm + ", DEPTno=" + DEPTno + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Emp emp)) return false; return Objects.equals(getEMPno(), emp.getEMPno()) && Objects.equals(getEname(), emp.getEname()) && Objects.equals(getJob(), emp.getJob()) && Objects.equals(getMgr(), emp.getMgr()) && Objects.equals(getHiredate(), emp.getHiredate()) && Objects.equals(getSal(), emp.getSal()) && Objects.equals(getComm(), emp.getComm()) && Objects.equals(getDEPTno(), emp.getDEPTno()); } @Override public int hashCode() { return Objects.hash(getEMPno(), getEname(), getJob(), getMgr(), getHiredate(), getSal(), getComm(), getDEPTno()); } } ``` #### 4、mapper层 创建`mapper/EmpMapper.java`接口 ```java package cn.doooog.springboot.mapper; import cn.doooog.springboot.po.Emp; import cn.doooog.springboot.provider.EmpProvider; import org.apache.ibatis.annotations.*; import java.util.List; public interface EmpMapper { @Select("select * from EMP limit #{page},#{size}") List<Emp> listEmpAll(@Param("page") int page,@Param("size") int size); @Select("select * from EMP where EMPno=#{EMPno}") Emp getEmpById(Integer EMPno); @Delete("delete from EMP where EMPno=#{EMPno}") int deleteEmpById(Integer EMPno); @InsertProvider(type = EmpProvider.class, method = "addEmp") @Options(useGeneratedKeys = true, keyProperty = "EMPno", keyColumn = "EMPno") int addEmp(Emp emp); @UpdateProvider(type = EmpProvider.class, method = "updateEmpById") int updateEmpById(Emp emp); } ``` 修改`/Application.java` ```java package cn.doooog.springboot; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @MapperScan("cn.doooog.springboot.mapper") public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` **注意**:必须在类名上方添加`@Mapper`,或在SpringBoot启动类添加注解`@MapperSacn("mapper层的包路径")` 创建`provider/EmpProvider.java` ```java package cn.doooog.springboot.provider; import cn.doooog.springboot.po.Emp; import org.apache.ibatis.jdbc.SQL; public class EmpProvider { public String addEmp(Emp emp) { return new SQL() {{ INSERT_INTO("EMP"); if (emp.getEMPno() != null) VALUES("EMPno", emp.getEMPno() + ""); if (emp.getEname() != null && !emp.getEname().isEmpty()) VALUES("ename", "'" + emp.getEname() + "'"); if (emp.getJob() != null && !emp.getJob().isEmpty()) VALUES("job", "'" + emp.getJob() + "'"); if (emp.getMgr() != null) VALUES("mgr", emp.getMgr() + ""); if (emp.getHiredate() != null && !emp.getHiredate().isEmpty()) VALUES("hiredate", "'" + emp.getHiredate() + "'"); if (emp.getSal() != null) VALUES("sal", emp.getSal() + ""); if (emp.getComm() != null) VALUES("comm", emp.getComm() + ""); if (emp.getDEPTno() != null) VALUES("DEPTno", emp.getDEPTno() + ""); }}.toString(); } public String updateEmpById(Emp emp) { return new SQL() {{ UPDATE("EMP"); if (emp.getEname() != null && !emp.getEname().isEmpty()) SET("ename=#{ename}"); if (emp.getJob() != null && !emp.getJob().isEmpty()) SET("job=#{job}"); if (emp.getMgr() != null) SET("mgr=#{mgr}"); if (emp.getHiredate() != null && !emp.getHiredate().isEmpty()) SET("hiredate=#{hiredate}"); if (emp.getSal() != null) SET("sal=#{sal}"); if (emp.getComm() != null) SET("comm=#{comm}"); if (emp.getDEPTno() != null) SET("DEPTno=#{DEPTno}"); WHERE("EMPno=#{EMPno}"); }}.toString(); } } ``` #### 5、格式化返回数据 创建`po/ResponseData.java`类 ```java package cn.doooog.springboot.po; public class ResponseData<T> { private Integer code; private String msg; private T data; public ResponseData(int code, String msg, T data) { this.code = code; this.msg = msg; this.data = data; } public ResponseData() { } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public Object getData() { return data; } public void setData(T data)、 { this.data = data; } } ``` #### 6、service层 创建`service/EmpService.java` ```java package cn.doooog.springboot.service; import cn.doooog.springboot.mapper.EmpMapper; import cn.doooog.springboot.po.Emp; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class EmpService { @Autowired private EmpMapper empMapper; public List<Emp> listEmpAll() { return listEmpAll(1, 20); } public List<Emp> listEmpAll(int page, int size) { return empMapper.listEmpAll((page - 1) * size, size); } public Emp getEmpById(Integer EMPno) { if (EMPno == null || EMPno <= 0) return null; return empMapper.getEmpById(EMPno); } public int addEmp(Emp emp) { if (emp == null || emp.equals(new Emp())) return 0; int res = empMapper.addEmp(emp); if (res < 1) return 0; return emp.getEMPno(); } public int updateEmpById(Emp emp) { if (emp == null || emp.equals(new Emp()) || emp.getEMPno() == null || emp.getEMPno() <= 0) return 0; return empMapper.updateEmpById(emp); } public int deleteEmpById(Integer EMPno) { if (EMPno == null || EMPno <= 0) return 0; return empMapper.deleteEmpById(EMPno); } } ``` #### 7、controller层 创建`controller/EmpController.java` ```java package cn.doooog.springboot.controller; import cn.doooog.springboot.po.Emp; import cn.doooog.springboot.po.ResponseData; import cn.doooog.springboot.service.EmpService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping("/api/emp") public class EmpController { @Autowired private EmpService empService; @RequestMapping("/list-all") public ResponseData<List<Emp>> listEmpAll() { List<Emp> list = empService.listEmpAll(); if (list != null && !list.isEmpty()) return new ResponseData<>(200, "查询成功", list); return new ResponseData<>(203, "查询失败", null); } @GetMapping("/id") public ResponseData<Emp> getEmpById(@RequestBody @RequestParam("id") Integer EMPno) { if (EMPno == null || EMPno <= 0) return new ResponseData<>(203, "id不合法", null); Emp emp = empService.getEmpById(EMPno); if (emp != null) return new ResponseData<>(200, "查询成功", emp); return new ResponseData<>(203, "未找到该id", null); } @PostMapping("/id") public ResponseData<Emp> addEmp(@RequestBody Emp emp) { if (emp == null || emp.equals(new Emp())) return new ResponseData<>(203, "新增内容不能为空", null); int res = empService.addEmp(emp); if (res < 1) return new ResponseData<>(203, "新增失败", null); return new ResponseData<>(200, "新增成功", emp); } @PutMapping("/id") public ResponseData<Emp> updateEmp(@RequestBody Emp emp) { if (emp == null || emp.getEMPno() == null || emp.getEMPno() <= 0) return new ResponseData<>(203, "id不合法", null); if (emp.equals(new Emp(emp.getEMPno()))) return new ResponseData<>(203, "更改内容不能为空", null); int res = empService.updateEmpById(emp); if (res < 1) return new ResponseData<>(203, "修改失败", null); return new ResponseData<>(200, "修改成功", empService.getEmpById(emp.getEMPno())); } @PatchMapping("/id") public ResponseData<Emp> updateEmp2(@RequestBody Emp emp) { if (emp == null || emp.getEMPno() == null || emp.getEMPno() <= 0){ return new ResponseData<>(203, "id不合法", null);} if (emp.equals(new Emp(emp.getEMPno()))) return new ResponseData<>(203, "更改内容不能为空", null); int res = empService.updateEmpById(emp); if (res < 1) return new ResponseData<>(203, "修改失败", null); return new ResponseData<>(200, "修改成功", empService.getEmpById(emp.getEMPno())); } @DeleteMapping("/id") public ResponseData<Emp> deleteEmp(@RequestBody Emp emp) { if (emp.getEMPno() == null || emp.getEMPno() <= 0) return new ResponseData<>(203, "id不合法", null); Emp emp2 = empService.getEmpById(emp.getEMPno()); if (emp2 == null || emp2.equals(new Emp())) return new ResponseData<>(203, "未找到该id", null); int res = empService.deleteEmpById(emp.getEMPno()); if (res < 1) return new ResponseData<>(203, "删除失败", null); return new ResponseData<>(200, "删除成功", emp2); } } ``` 成功如下  #### 8、映射`.XML`文件 修改`application.properties`配置,添加别名 ```properties # MyBatisConfig mybatis.type-aliases-package=cn.doooog.[project].po mybatis.mapper-locations=cn.doooog.[project].mapper.*.xml ``` 在`resources`文件夹下创建与项目包全名路径相同的目录,比如`cn/doooog/springboot/mapper/EmpMapper.xml` ## 六、解决跨域访问 #### 1、配置单个请求 在处理器上添加`@CrossOrigin("*")` ```java @CrossOrigin("*") @RequestMapping("/list-all") public ResponseData<List<Emp>> listEmpAll(@RequestParam(name = "page", defaultValue = "1") int page, @RequestParam(name = "size", defaultValue = "10") int size) { List<Emp> list = empService.listEmpAll(page, size); if (list != null && !list.isEmpty()) return new ResponseData<>(200, "查询成功", list); return new ResponseData<>(203, "查询失败", null); } ``` #### 2、过滤器 创建`util/GlobalCorsConfig.java` ```java package cn.doooog.springboot.util; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class GlobalCorsConfig { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { // 重写父类提供的跨域请求处理的接口 @Override public void addCorsMappings(CorsRegistry registry) { // 添加映射路径 registry.addMapping("/**") .allowedOriginPatterns("*") // 放行哪些域名,可以多个 .allowCredentials(true) // 是否发送Cookie信息 .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS", "PATCH") // 放行哪些请求方式 .allowedHeaders("*") // 放行哪些原始域(头部信息) .exposedHeaders("Header1", "Header2") // 暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息) .maxAge(3600); // 预请求的结果有效期,默认1800分钟,3600是一小时 } }; } } ``` #### 3、拦截器 创建`util/WebMvcConfig.java` ```java package cn.doooog.springboot.util; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { /* * addMapping:配置可以被跨域的路径,可以任意配置,可以具体到直接请求路径。 * allowCredentials:是否开启Cookie * allowedMethods:允许的请求方式,如:POST、GET、PUT、DELETE等。 * allowedOrigins:允许访问的url,可以固定单条或者多条内容 * allowedHeaders:允许的请求header,可以自定义设置任意请求头信息。 * maxAge:配置预检请求的有效时间 */ registry.addMapping("/**") .allowedOriginPatterns("*") // 放行哪些域名,可以多个 .allowCredentials(true) // 是否发送Cookie信息 .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS", "PATCH") // 放行哪些请求方式 .allowedHeaders("*") // 放行哪些原始域(头部信息) .exposedHeaders("Header1", "Header2") // 暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息) .maxAge(3600); } } ``` 最后修改:2025 年 11 月 04 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 👆请简单粗暴地爱我。