SpringBoot开发流程

1、新建项目

Spring Web + MySQL Driver + Dev Tools添加后三个选项

修改配置文件为yml格式

端口设置为80 方便访问

手动导入Mybatis Plus 和 Druid连接池

这里遇到一个问题,就是修改MP或druid版本号会报错?

2、创建数据库表对应的实体类

开发实体类

@Data替代了get/set方法,toString方法,hasCode方法,equals方法等

3、数据层开发(dao层)

主流的数据层技术:Mybatis、MP(Mybatis Plus)、Hibernate

(1)导入MP和Druid对应的依赖(第一步已完成)

完成druid的配置:

yml中输入data然后提示中选择driver-class-name,然后前面添加druid即可

然后再对MP的表前缀进行配置(Mybatis plus完成配置):

mybatis-plus:
  global-config:
    db-config:
      table-prefix: tbl_

(2)然后创建数据层接口:

New新建 dao.BookDao接口

@Mapper
public interface BookDao extends BaseMapper<Book> {
}
//泛型 填写对应的实体类

 然后在Test文件夹下,建立相应dao的测试类,类上添加注解:@SpringBootTest

New dao.BookDaoTestCase

在这个测试类中测试了CRUD:

import com.bo.pojo.Book;
import lombok.AllArgsConstructor;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

/**
 * 
 * @date 2022/4/26 - 14:34
 */
@SpringBootTest
public class BookDaoTestCase {
    @Autowired
    private BookDao bookDao;

    //查询操作
    //根据id查询
    @Test
    void testGetById(){
        System.out.println(bookDao.selectById(2));
    }


    //增加记录
    //不设置id字段会报错,mybatis系统异常,MP默认生成id策略由他自己设置,雪花算法
    //我们想要使用表的自增策略,需要在yml中配置  id-type: auto
    @Test
    void testSave(){
        Book book = new Book();
        book.setType("测试数据123");
        book.setName("测试数据123");
        book.setDescription("测试数据123");
        bookDao.insert(book);
    }

    //更新操作,修改操作
    @Test
    void testUpdate(){
        Book book = new Book();
        book.setId(2);
        book.setType("测试数据Update");
        book.setName("测试数据Update");
        book.setDescription("测试数据Update");
        bookDao.updateById(book);
    }

    //删除
    @Test
    void testDelete(){
        bookDao.deleteById(2);
    }

    //查询所有的数据
    //所有查询都以select开头
    @Test
    void testGetAll(){
        System.out.println(bookDao.selectList(null));
    }
}

(3)在yml文件中开启MP运行日志:

mybatis-plus:
  global-config:
    db-config:
      table-prefix: tbl_
      id-type: auto
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

辅助debug,服务器上线时不要开启!!!

(4)实现分页查询

IPage是一个接口,Page是它的实现类,新建IPage接口对象,第一个参数为第几页(从1开始),第二个参数介绍每页有多少行记录(从1开始)

page对象中封装了分页操作中的所有数据:

数据、当前页码、每页数据总量、最大页码值、数据总量

最主要的是添加MP的拦截器!!!才能实现分页功能(也就是为sql语句拼接上limit)

@Test
    void testGetPage(){
        //IPage是一个接口
        //哪一页的数据,一页显示多少数据(1,5) 第一页,一页显示5条
        //分页功能实现 select * from tbl_book limit ?.?
        //分页若想使用,必须使用拦截器实现
        //返回值还是IPage对象 page
        //返回的数据存在了page对象内
        IPage page = new Page(2,5);
        bookDao.selectPage(page,null);
        //需要调用page对象的方法取出
        System.out.println(page.getCurrent());
        System.out.println(page.getSize());
        System.out.println(page.getTotal());
        System.out.println(page.getPages());
        System.out.println(page.getRecords());
    }

 MP的分页拦截器:

New config.MPConfig

功能就是为SQL语句拼接部分内容 limit ....

@Configuration
public class MPConfig {

    //交给spring一个bean
    //bean是MP的拦截器
    //这个拦截器里面里面添加了PaginationInnerInterceptor,添加了一个分页的子拦截器
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }
}

 (4)添加按条件查询的功能

上面的所有方法都可以添加查询条件!

 @Test
    void testGetBy(){
        //QueryWrapper<>就是查询条件 泛型可写可不写QueryWrapper与QueryWrapper<>均可
        //设置条件
        //like 包括 就是sql中的like
        //eq  等于
        //ne  不等于
        //lt  小于
        //...
        // QueryWrapper<Book> qw = new QueryWrapper<Book>();
        //问题一:
        // "name"是手写的,假如写错了怎么解决,属性容易写错
        // qw.like("name","Spring"); name写错了会出错
        //解决方法:
        // qw.like(Book::getName(),name);
        // 调用Book的getName方法
        //问题二:
        //如果name为null,会直接把null当作"null"拼接
        //方法一:if判断再连接 if(name!=null) lqw.like(Book::getName,name);
        //方法二:lqw.like(name!=null,Book::getName,name);
        String name = null;
        LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<Book>();
        lqw.like(name!=null,Book::getName,name);
        bookDao.selectList(lqw);
    }

4、业务层开发(service层)

业务层接口关注的是业务的名称,login(String username, String password)适合业务层的登录业务,而相同功能的selectByUserNamePassword(String username, String password)适合数据层接口。

如果是业务方法,要定义为业务名,如果只是一般的增删改查,就写增删改查即可。

创建业务层接口-->创建业务层实现类-->在实现的方法调用dao中的方法(而该方法又是BaseMapper定义好的)

New service.BookService 接口

/**
 * @date 2022/4/26 - 16:35
 */
//业务方法就叫业务名login()
//一些操作就叫操作名
public interface BookService {

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

定义完业务层接口,接着创建实现类,在service包下新建impl包,在该包下面:

New BookServiceImpl类

/**
 * @date 2022/4/26 - 16:39
 */
@Service  //定义为业务层对应的bean
public class BookServiceImpl implements BookService {
    @Autowired
    private BookDao bookDao;

    @Override
    public Boolean save(Book book) {
        //大于0操作成功
        //小于=0操作失败
        return bookDao.insert(book) > 0;
    }

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

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

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

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

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

下面进行测试:

Test文件夹下 New service.BookServiceTestCase

/**
 * @date 2022/4/26 - 16:44
 */
@SpringBootTest
public class BookServiceTestCase {

    @Autowired
    private BookService bookService;
    @Test
    void getById(){
        System.out.println(bookService.getById(4));
    }
    @Test
    void testSave(){
        Book book = new Book();
        book.setType("测试数据123");
        book.setName("测试数据123");
        book.setDescription("测试数据123");
        System.out.println(bookService.save(book));
    }

    //更新操作
    @Test
    void testUpdate(){
        Book book = new Book();
        book.setId(3);
        book.setType("id2AAAA");
        book.setName("测试数据Update");
        book.setDescription("测试数据Update");
        System.out.println(bookService.update(book));
    }

    //删除
    @Test
    void testDelete(){
        System.out.println(bookService.delete(3));
    }

    //查询所有的数据
    //所有查询都以select开头
    @Test
    void testGetAll(){
        System.out.println(bookService.getAll());
    }

    @Test
    void testGetPage(){
        IPage<Book> page = bookService.getPage(2, 5);
        //需要调用page对象的方法取出
        System.out.println(page.getCurrent());
        System.out.println(page.getSize());
        System.out.println(page.getTotal());
        System.out.println(page.getPages());
        System.out.println(page.getRecords());
    }
}

上面的步骤过于繁琐,如何简化?步骤如下

快速开发方案:使用MyBatisPlus提供业务层通用接口(IService<T>)与业务层通用实现类(ServiceImpl<M,T>),在通用类基础上做功能重载或功能追加,注意重载时不要覆盖原始操作,避免原始提供的功能丢失。

第一步--创建service接口,继承IServic<xxx>  xxx填写对应的实体类

 第二步--实现类定义

5、表现层开发(Controller层)

在该层完成表现层处理:

@RestController
@RequestMapping("/books")
public class BookController {
    @Autowired
    private IBookService iBookService;

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

    //传的是json数据
    @PostMapping
    public Boolean save(@RequestBody Book book){
        return iBookService.save(book);
    }

    @PutMapping
    public Boolean update(@RequestBody Book book){
        return iBookService.modify(book);
    }

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

    @GetMapping("{id}")
    public Book getById(@PathVariable Integer id){
        return iBookService.getById(id);
    }

    @GetMapping("{currentPage}/{pageSize}")
    public IPage<Book> getPage(@PathVariable int currentPage, @PathVariable int pageSize){
        return iBookService.getPage(currentPage,pageSize);
    }
}

但是返回给前端的数据格式多种多样,前端处理起来很麻烦,所以需要统一一下后端的返回格式:

这里在utils包下面新增R类(Result),作为我们返回值的统一格式;

然后对Controller做修改:

@RestController
@RequestMapping("/books")
public class BookController2 {
    @Autowired
    private IBookService iBookService;

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

    //传的是json数据
    @PostMapping
    public R save(@RequestBody Book book){
        return new R(iBookService.save(book));
    }

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

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

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

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

6、前后端结合

前后端分离结构设计中页面归属前端服务器,这里暂时采用了单体工程

单体工程中页面放置在resour目录下的static目录中(建议执行clean)

 在vue的数据模型中,dataList存储当前页要展示的列表数据;下面两个控制表单是否可见,formData用来记录表单数据,修改和新增用同一个表单数据。

导入前端页面后,然后在vue页面中利用axios发起异步请求,这里测试能否发起一个请求,在钩子函数created()中调用getAll()方法,刷新页面时自动执行。axios.xxx()发送请求,then接受数据后做处理。

查询全部数据并展示:

 

实现新增功能:

首先要弹出添加对话框,同时还要清除formData里面的旧数据

 然后,点击确定之后,提交表单数据到后台,实现添加功能(当前操作失败的时候,不要关闭对话框):

 点击取消按钮,会关闭添加或编辑窗口:

 实现删除操作(then确认,catch取消):

修改操作:

相当于列表功能+新增功能组合,首先要弹出编辑窗口,并且要将准备修改的数据展示出来:

然后修改之后,提交到后台接口,确定提交:

异常消息处理:

如果后台出现异常,则会产生另一种消息格式给前端:

尽管代码出异常,我们也要返回给前端统一的格式,在springMVC中提供的专用的异常处理器:

可以使用ControllerAdvice注解或者RestControllerAdvice注解;

运行处异常之后,被异常拦截器拦截,然后返回一个R对象,所以修改R对象,添加一个msg消息:

 R.class

@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;
    }
}

 现在页面上的消息,有在页面写的,还有在代码上写的,所以需要统一在后端添加:

 现在所有的消息统一由后台处理,保存消息前端展示,前端使用res.data.msg使用即可,方便后面进行国际化。

分页功能:

 直接在getAll()方法里面改:

 点击修改页码,响应换页操作:

某一页只有最后一条数据,删除之后依然在本页面,如何解决?如果要查看页码大于总页码值,重新执行查询操作,使用最大页码值作为当前页码值,修改Controller:

按条件查询:

在执行分页的时候这些条件都得带走:

这几个数据在哪?

这三个数据是跟着分页走的,每次分页查询这三个条件都得带走,所以绑定在分页数据模型中:

修改分页查询操作,

 修改Controller接口,但是缺少getPage(currentPage,pageSize, book)接口,所以需要添加

 

 修改service实现类:

 对于条件查询,把它作为分页中的一部分数据,当前页码值和size是条件,type和name等也是查询条件。请求的路径参数,直接写参数(对应名称)就能接,如果有对应的实体类,直接封装为实体类。

  • 9
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
springboot开发流程包括以下几个步骤: 1. 创建maven项目:使用Maven工具创建一个新的项目,将其作为springboot项目的基础。 2. 引用依赖:在项目的pom.xml文件中添加所需的依赖。依赖包括起步依赖和项目依赖,起步依赖包含了常用的依赖库,而项目依赖是根据具体需求添加的其他依赖。 3. 创建启动类:在项目中创建一个启动类,使用@SpringBootApplication注解标记,并在该类中添加main方法用于启动springboot应用。 4. 配置文件:在项目中创建一个配置文件,通常是application.yml或application.properties文件,用于配置应用的相关属性。可以在配置文件中设置一些属性,如激活特定的配置文件。 5. 编写业务代码:根据需求编写业务代码,包括定义数据传输对象(DTO)和控制器(Controller)等。 6. 进行restful测试:使用工具(如Postman)进行restful接口的测试,验证业务代码的正确性。 7. 部署应用:打包应用并将其部署到目标环境中。可以使用Maven插件将应用打包成可执行的jar文件,并使用服务器或容器来运行应用。 综上所述,springboot开发流程包括创建maven项目、引用依赖、创建启动类、配置文件、编写业务代码、进行restful测试和部署应用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [springboot开发流程](https://blog.csdn.net/m0_67393039/article/details/126515331)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值