Spring Boot

553 阅读10分钟

注解

@Override

  • 表明子类中的方法重写了父类中的方法或者实现了接口中的方法。
  • 它主要是为了增强代码的可读性和可靠性。

@RestController

表示该类是一个RESTful控制器

这是一个组合注解,相当于 @Controller 和 @ResponseBody 的合集。它用于标记一个类为RESTful控制器,意味着这个类中的所有方法都会返回一个对象,而不是视图。Spring会自动将返回的对象转换为JSON或XML格式的响应体。

‌@RequestMapping("/RewriteArticleClassController")

注解指定了该控制器的根路径为 /RewriteArticleClassController

用于映射Web请求到特定的处理程序类或方法。在这里,它表示这个控制器类中的所有方法都将处理以 /RewriteArticleClassController 为前缀的URL请求。

其中 @PostMapping、@GetMapping、@PutMapping、@DeleteMapping

这是几个组合注解,相当于 @RequestMapping(method = RequestMethod.POST)。它用于映射HTTP POST请求到特定的方法。

参数注解

@RequestParam

@RequestBody

@PathVariable

是Spring框架中用于处理HTTP请求参数的注解

@RequestParam用于获取请求参数值,@RequestBody用于获取请求体内容,@PathVariable用于获取请求路径中的参数值。

@RequestParam: 用于获取请求参数的值。它可以用来接收GET、POST等请求方式中的参数,并且可以设置参数的默认值、是否必填等属性。

@GetMapping("/example")
public String example(@RequestParam(name = "name", defaultValue = "Guest") String name) {
    return "Hello, " + name;
} 
// 请求:/example?name=John
// 输出结果:Hello, John
// 请求:/example
// 输出结果:Hello, Guest

@RequestBody: 用于绑定请求体的内容到方法参数上。它用于接收POST请求中的请求体,并将请求体的内容转换成对应的对象或数据类型。通常用于接收JSON或XML格式的数据。

@PostMapping("/example")
public String example(@RequestBody User user) {
    return "Hello, " + user.getName();
} 
// 请求体:{"name":"John"}
// 输出结果:Hello, John

@PathVariable: 用于获取请求路径中的参数值。它可以通过在服务端路径中设置占位符来获取RESTful风格的URL中的参数值。

@GetMapping("/example/{id}")
public String example(@PathVariable("id") int id) {
    return "ID: " + id;
} 
// 请求:/example/123
// 输出结果:ID: 123

lombok 常见注解

1@data  
    使用这个注解,就不用再去手写Getter,Setter,equals,canEqual,hasCode,toString等方法了,
    注解后在编译时会自动加进去。
2)@AllArgsConstructor
    使用后添加一个构造函数,该构造函数含有所有已声明字段属性参数
3)@NoArgsConstructor
    使用后创建一个无参构造函数
4)@Builder
    关于Builder较为复杂一些,Builder的作用之一是为了解决在某个类有很多构造函数的情况,
    也省去写很多构造函数的麻烦,在设计模式中的思想是:
    用一个内部类去实例化一个对象,避免一个类出现过多构造函数
@Data //生成getter,setter等函数
@AllArgsConstructor //生成全参数构造函数
@NoArgsConstructor//生成无参构造函数
@Builder
public class test1 {
    String name;
    String age;
    String sex;
}


 public static void main(String[] args) {
 //使用@Builder注解后,可以直接通过Builder设置字段参数
        test1 t1=new test1.test1Builder()
                .name("wang")
                .age("12")
                .sex("man")
                .build();

        System.out.println("name is"+t1.getName()+'\n'+"age is :"+t1.getAge());

    }

@Autowired

是Spring框架提供的一个注解,用于自动装配Bean。通过标注这个注解,Spring容器会自动查找和注入符合条件的Bean实现,以满足依赖需求。这种方式极大地简化了开发过程,减少了手动配置的麻烦。

直接注入,直接在类的字段上使用, 这种方式虽然简洁,但不推荐过度使用,因为它不利于对类的可测试性进行管理。

 @Autowired //注入
 private BookDao bookDao;//数据层 

可以使用构造方法中注入

private final BookDao bookDao; // 数据层

@Autowired //注入
public BookServiceImpl(BookDao bookDao) {
    this.bookDao = bookDao;
} 

通过Setter方法进行依赖注入。这种方式可以在实例化后更新依赖,具有更好的灵活性。

private final BookDao bookDao;
@Autowired
public void setBookDao(BookDao bookDao) {
    this.bookDao = bookDao
} 

tips:

@Autowrited 默认是必须的,如果没有找到匹配的Bean,会抛出异常,可以设置为可选

@Autowired(required = false)
private OptionalDe optionalDe

当存在多个符合条件的Bean时,应该使用@Qualifier注解来指定具体的Bean

@Autowired
@Qualifier("specificUserRepository")
private UserRepository userRepository

@Mapper

MyBatis框架中,@Mapper是一个标记接口,用于标记一个接口作为映射器接口。映射器接口是MyBatis的核心概念之一,它将Java方法与SQL语句关联起来。每个映射器接口方法对应于一个SQL语句,该SQL语句在映射器XML文件或使用@Select, @Update, @Insert, @Delete等注解在接口方法中直接定义。

@SpringBootApplication

注解所在的类视为主类

这个注解实际上是@Configuration@EnableAutoConfiguration@ComponentScan三个注解的组合,是Spring Boot项目的基石。

@Service

使用 @Service 注解标识的类表示它是服务层组件,即业务逻辑的实现类

@Api(tags = {"写作-写作文章管理接口"})

这是Swagger的注解,用于提供API文档的元数据。tags 属性用于指定API的标签或分类,这有助于在生成的API文档中组织和过滤API。

@ApiOperation(value = "分页查询文章列表", notes = "分页查询文章列表")

这是Swagger的注解,用于提供关于特定API操作的详细信息。value 属性描述了操作的简短标题,而 notes 属性提供了更详细的描述。

restfull

package com.zjz.controller; 
import org.springframework.web.bind.annotation.*;
import java.awt.print.Book; 
//@RestController 注解:这个注解用于标记这是一个RESTful风格的控制器,它是一个便利的快捷方式,相当于同时使用了@Controller和@ResponseBody注解。
// 这意味着这个控制器中的所有方法都会返回一个响应体,而不是视图。
@RestController
//这个注解用于为整个控制器类提供一个基本的请求路径。在这个例子中,所有的请求都会以/books开头。
@RequestMapping("/books")
public class BookController {
    //请求方式
    @PostMapping
    public String save(@RequestBody Book book) {
        return "新增";
    }

    @DeleteMapping("/{id}")
    public String delete(@PathVariable int id) {
        return "删除";
    }

    @PutMapping
    public String update(@RequestBody Book book) {
        return "更新";
    }

    @GetMapping("/{id}")
    public  String getById(@PathVariable int id){
        System.out.println("springboot is running");
        return "查询单个";
    }

    @GetMapping
    public String getAll(){
        System.out.println("springboot is running");
        return "查询全部";
    }

} 

配置

三种配置方式

  • application.properties
  • application.yaml (主流格式)
  • application.yml

以上三种配置文件都存在时,application.properties>yml>yaml

相同属性加载优先级, 不相同的属性,同时保留

//application.properties
//服务的端口配置
server.port=80  
//application.yaml  application.yml
//服务的端口配置
server:
    port:81

yaml 文件 语法规则

  1. 大小写敏感
  2. 属性层级关系使用多行描述,每行结尾使用冒号结束
  3. 使用缩进表示层级关系,同层级左侧对齐,只允许使用空格(不允许使用Tab键)
  4. 属性值前面添加空格 (属性名和属性值之间使用冒号+空格作为分隔)
  5. #表示注释
//键值对
name: zjz
//对象
enterprise:
    name: zjz
    age: 16
    tel: 8888888
    
//数组
likes:
    - game
    - music
    - sleep
likes: [game,music,sleep]
//多维数组
users:
    - name: zjz
      age: 20
    - name: zzz
      age: 18
users2:
    - 
      name: zjz
      age: 20
    - 
      name: zzz
      age: 18
 user3:[{name:zhangsan,age:19},{name:lisi,age:30}]

读取yml 数据

@GetMapping
public String getAll(){
    System.out.println("springboot is running"+port);
    System.out.println(env.getProperty("server.port")); //读取配置数据
    return "查询全部 base_configuration";
}


//读取application.yml 配置文件中的数据
@Value("${server.port}")
private String port;


//读取    application.yml 配置文件中的所有数据
@Autowired
private Environment env; 

整合第三方技术

整合JUnit

整合MyBatis

数据层 业务层 表现层

ssmp

新建模块

image.png

添加依赖

image.png

手动配置

image.png

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.2</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.9</version>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency 

yml配置

image.png

server:
  port: 80
spring:
  datasource:
    druid:
     driver-class-name: com.mysql.cj.jdbc.Driver
     url: jdbc:mysql://localhost:3306/db_test?serverTimezone=UTC
     username: root
     password: 1234

mybatis-plus:
  global-config:
    db-config:
      table-prefix: tb_
      id-type: auto
      
#  展示执行操作 ,会把执行的sql语句打印到控制台上 
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 

实体类

image.png

数据服务操作

image.png

编写测试类

image.png

业务层开发

业务层接口定义

image.png

package com.zjz.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zjz.domain.Book;

import java.util.List;

public interface BookService {
    Boolean save(Book book);
    Boolean update(Book book);
    Boolean delete(int id);
    Book getById(int id);
    List<Book> getAll();
    IPage<Book> getPage(int currentPage, int pageSize);
} 

业务层方法实现

image.png

package com.zjz.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zjz.dao.BookDao;
import com.zjz.domain.Book;
import com.zjz.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service //定义成业务层对应的bean
public class BookServiceImpl implements BookService {

//    不建议这么注入
//    @Autowired
//    private BookDao bookDao;//数据层

    private final BookDao bookDao; // 数据层
//    使用构造方法注入
    @Autowired
    public BookServiceImpl(BookDao bookDao) {
        this.bookDao = bookDao;
    }


    @Override
    public Boolean save(Book book) {
        return bookDao.insert(book) > 0;
    }

    @Override
    public Boolean update(Book book) {
        return bookDao.updateById(book) > 0;
    }

    @Override
    public Boolean delete(int id) {
        return bookDao.deleteById(id) > 0;
    }

    @Override
    public Book getById(int id) {
        return bookDao.selectById(id);
    }

    @Override
    public List<Book> getAll() {
        return bookDao.selectList(null);
    }

    @Override
    public IPage<Book> getPage(int currentPage, int pageSize) {
        IPage<Book> page = new Page<>(currentPage, pageSize);
        return bookDao.selectPage(page,null);
    }


} 

业务层快速开发

  1. 使用通用接口 (IServer < T >) 快速开发Service
  2. 使用通用类(ServiceImpl <M,T>) 快速开发 ServiceImpl
  3. 可以再通用接口基础上做功能重载或功能追加
  4. 注意重载时不要覆盖原始操作,避免原始提供的功能丢失

定义业务层接口

image.png

package com.zjz.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.zjz.domain.Book;
//业务层接口直接继承
public interface IBookService extends IService<Book> {
//    通用类不满足条件时,使用自定义方法
    boolean saveBook(Book book);
    boolean updateBook(Book book);
    boolean deleteBook(int id);
} 

业务层方法实现

image.png

package com.zjz.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zjz.dao.BookDao;
import com.zjz.domain.Book;
import com.zjz.service.IBookService;
import org.springframework.stereotype.Service;
//业务层 直接继承 ServiceImpl
@Service
public class IBookServiceImpl extends ServiceImpl<BookDao, Book> implements IBookService { 
//    继承中没有的方法   自定义方法  也就是  通用类中没有合适的方法时,做功能追加或功能重载

    //注入数据层
    private final BookDao bookDao; // 数据层
    public IBookServiceImpl(BookDao bookDao){
        this.bookDao = bookDao;
    }

    @Override
    public boolean saveBook(Book book) {
        return bookDao.insert(book) > 0;
    }

    @Override
    public boolean updateBook(Book book) {
        return false;
    }

    @Override
    public boolean deleteBook(int id) {
        return false;
    }
} 

表现层

基于Restful进行表现层接口开发

image.png

package com.zjz.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zjz.domain.Book;
import com.zjz.service.BookService;
import com.zjz.service.IBookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/books")
public class BookController {
    //注入业务层
    @Autowired
    private IBookService bookService;
    private int id;

    @GetMapping
    public List<Book> getAll() {
        return bookService.list();
    }

    @PostMapping
    public Boolean save(@RequestBody Book book) {
        return bookService.save(book);
    }

    @PutMapping
    public Boolean update(@RequestBody Book book) {
        return bookService.updateById(book);
    }

    @DeleteMapping("{id}")
    public Boolean delete(@PathVariable int id) {
        return bookService.removeById(id);
    }

    @GetMapping("{id}")
    public Book getById(@PathVariable int id) {
        this.id = id;
        return bookService.getById(id);
    }
 
    @GetMapping("{currentPage}/{pageSize}")
    public IPage<Book> getPage(@PathVariable int currentPage, @PathVariable int pageSize){
        return bookService.getPage(currentPage,pageSize);
    } 
} 

表现层消息一致性处理

设计同一的返回值类型,便于前端接口联调

定义一个返回类型

image.png

package com.zjz.controller.utils;

import lombok.Data;

//使用@Data get set 就不用写了
@Data
public class R {
    private Boolean flag;
    private Object data;

    public R() {}

    public R(Boolean flag) {
        this.flag = flag;
    }
    public R(Boolean flag, Object data) {
        this.flag = flag;
        this.data = data;
    }
} 

修改表现层

package com.zjz.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zjz.controller.utils.R;
import com.zjz.domain.Book;
import com.zjz.service.IBookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;

@RestController
@RequestMapping("/books")
public class BookController {
    //注入业务层
    @Autowired
    private IBookService bookService;

    @GetMapping
    public R getAll() { 
        return new R(true,bookService.list());
    }

    @PostMapping
    public R save(@RequestBody Book book) { 
        return new R(bookService.save(book));
    }

    @PutMapping
    public R update(@RequestBody Book book) {
        return new R(bookService.updateById(book)); 
    }

    @DeleteMapping("{id}")
    public R delete(@PathVariable int id) { 
        return new R(bookService.removeById(id));
    }


    @GetMapping("{id}")
    public R getById(@PathVariable int id) { 
        return new R(true,bookService.getById(id));
    }



    @GetMapping("{currentPage}/{pageSize}")
    public R getPage(@PathVariable int currentPage, @PathVariable int pageSize){ 
        return new R(true,bookService.getPage(currentPage,pageSize));
    }
} 

异常处理

image.png

package com.zjz.controller.utils;


import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

//异常处理器
//@ControllerAdvice
@RestControllerAdvice
public class ProjectExceptionAdvice {
    @ExceptionHandler(Exception.class)
    public R exceptionHandler(Exception ex){
        ex.printStackTrace();
        return new R("服务器故障,请稍后再试!");

    }
} 

R类添加消息 msg

package com.zjz.controller.utils;

import lombok.Data;

//使用@Data get set 就不用写了
@Data
public class R {
    private Boolean flag;
    private Object data;
    private String msg;

    public R() {}

    public R(Boolean flag) {
        this.flag = flag;
    }
    public R(Boolean flag, Object data) {
        this.flag = flag;
        this.data = data;
    }
    public R(Boolean flag, String msg) {
        this.flag = flag;
        this.msg = msg;
    }
    public R(String msg) {
        this.flag = false;
        this.msg = msg;
    }
} 

打包运行

image.png

进入到 .jar 文件 cmd 运行 java -jar ---.jar 文件名,运行

1、报错 SpringBott_ssmp-0.0.1-SNAPSHOT.jar中没有主清单属性

pom.xml 文件中 skip 要注释掉,重新打包

<configuration>
    <mainClass>com.zjz.SSMPApplication</mainClass>
    <!--<skip>true</skip>-->
</configuration>

2、打包的时候代码会测试运行,所以会产生一些测试数据,需要跳过测试流程

image.png

3、端口号被占用

window 端口号被占用

// 查询端口
netstat -ano 
// 查询指定端口
netstat -ano | findstr 80
// 查询指定端口
netstat -ano | findstr 8080
// 根据进程PID查询进程名称
tasklist | findstr "进程PID号"

//根据PID杀死任务

taskkill /F /PID "进程PID号"

// 根据进程名称杀死任务
taskkill /F /IM "进程名称"
taskkill -f -t -im "进程名称"

也可以使用临时端口号

java -jar ---.jar --server.port=8080

热部署