SpringBoot(基础篇)

news2024/11/17 7:47:04

SpringBoot基础篇

入门案例

在创建SpringBoot项目时,会出现以下不需要的文件,如果每次都手动删除的话,就会很麻烦。

img

教你一招

在setting设置中找到Editor,选择File Types–>Ignored Files and Folders–>点击+号,输入要隐藏的文件/文件夹

img

这样以后每次创建SpringBoot项目时,其他文件就不会再出现

快速上手SpringBoot

SpringBoot简介

  • SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的初始搭建以及开发过程
    • Spring程序缺点
      • 依赖设置繁琐
      • 配置繁琐
    • SpringBoot程序优点
      • 起步依赖(简化依赖配置)
      • 自动配置(简化常用工程相关配置)
      • 辅助功能(内置服务器)

依赖解析(解决配置问题)

  • starter

    • SpringBoot中常见项目名称,定义了当前项目使用的所有坐标,以达到减少依赖配置的目的
  • parent

    • 所有SpringBoot项目要继承的项目,定义了若干个坐标版本号(依赖管理,而非依赖),以达到减少依赖冲突的目的
    • spring-boot-starter-parent各版本间存在诸多坐标版本不同
  • 实际开发

    • 使用任意坐标时,仅书写GAV中的G和A,v由SpringBoot提供,除非SpringBoot未提供对应版本v
    • 如发生坐标错误,再指定Version(小心版本冲突)

说明:

  • GAV
    • groupId:定义当前maven组织的项目名称
    • artifactId:定义实际项目名称
    • version:定义当前项目的当前版本

引导类

启动方式

img

  • SpringBoot的引导类是Boot工程的执行入口,运行main方法就可以启动项目
  • SpringBoot工程运行后初始化Spring容器,扫描引导类所在包加载bean

内嵌tomcat

使用maven依赖管理变更起步依赖项

img

Jetty比tomcat更轻量级,可扩展性更强(相较于Tomcat),谷歌应用引擎(GAE)已经全面切换为Jetty

内置服务器

  • Tomcat(默认):apache出品,粉丝多,应用面广,负载了若干较重的组件
  • jetty:更轻量级,负载性能远不及tomcat
  • undertow:undertow,负载性能勉强跑赢tomcat

REST开发

REST(Representational State Transfer),表现形式状态转换

  • 传统风格资源描述形式
    • http://localhost/user/getById?id=1
    • http://localhost/user/saveUser
  • REST风格描述形式
    • http://localhost/user/1
    • http://localhost/user

优点:

  • 隐藏资源的访问行为,无法通过地址得知对资源是何种操作
  • 书写简化

REST风格简介

按照REST风格访问资源时使用行为动作区分对资源进行了何种操作

  • http://localhost/users:查询全部用户信息 GET(查询)
  • http://localhost/users/1:查询指定用户信息 GET(查询)
  • http://localhost/users:添加用户信息 POST(新增/保存)
  • http://localhost/users:修改用户信息 PUT(修改/更新)
  • http://localhost/users/1:删除用户信息 DELETE(删除)

注意事项

上述行为是约定方式,约定不是规范,可以打破,所以称REST风格,而不是REST规范

描述模块的名称通常使用复数,也就是加s的格式描述,表示此类资源,而非单个资源,例如:users、books、accounts…

REST入门案例

POST请求:

@Controller
public class UserController {

    @PostMapping("/users")
    // @RequestMapping(value = "/users", method = Request.POST)
    @ResponseBody
    public String save() {
        System.out.println("user save ...");
        return "{'model' : 'user save '}";
    }
}

效果:

img

DELET请求:

@DeleteMapping("/users/{id}")
    // @RequestMapping(value = "/users/{id}", method = RequestMethod.DELETE)
    @ResponseBody
    public String delete(@PathVariable Integer id){
        System.out.println("users delete 。。。" + id);
        return "{'model' : 'user delete '}";
    }

效果:

img

PUT请求:

@PutMapping("/users")
    // @RequestMapping(value = "/users", method = RequestMethod.PUT)
    @ResponseBody
    public String update(@RequestBody User user) {
        System.out.println("users update 。。。" + user);
        return "{'model' : 'user update '}";
    }

效果:

img

GET请求(单个):

@GetMapping("/users/{id}")
    // @RequestMapping(value = "/users/{id}", method = RequestMethod.GET)
    @ResponseBody
    public String getById(@PathVariable Integer id) {
        System.out.println("users getById 。。。" + id);
        return "{'model' : 'user getById '}";
    }

效果:

img

GET请求(全部):

ResponseBody
    public String getAll() {
        System.out.println("users getAll 。。。");
        return "{'model' : 'user getAll '}";
    }

效果:

img

步骤

  1. 设定http请求动作(POST、GET…)
  2. 设定请求参数(路径变量 如:/users/{id})

注解介绍

@RequestMapping

类型:方法注解

位置:SpringMVC控制器方法定义上方

作用:设置当前控制器方法请求访问路径

属性:value(默认):请求访问路径

method:http请求动作,标准动作(GET/POST/PUT/DELETE)

@PathVariable

类型:形参注解

位置:SpringMVC控制器方法形参定义前面

作用:绑定路径参数与处理器方法形参间的关系,要求路径参数名与形参名一一对应

@RequestBody、@RequestPara、@PathVariable

区别:

  • @RequestParam用于接收url地址传参或表单传参
  • @RequestBody用于接收json数据
  • @PathVariable用于接收路径参数,使用(参数名称)描述路径参数

应用:

  • 后期开发中,发送请求参数超过1个小时,以json格式为主,@RequestBody应用较广
  • 如果发送非json格式数据,选用@RequestParam接收请求参数
  • 采用RESTful进行开发,当参数数据较少时,例如1个,可以采用@PathVariable接收请求路径变量,通常用于传输id值
@RestController

类型:类注解

位置:基于SpringMVC的RESTful开发控制器类定义上方

作用:设置当前控制器类为RESTful风格,等同于@Controller与@ResponseBody两个注解组合功能

属性:value(默认): 请求访问路径

基础配置

教你一招

  • 原则
    • 保留工程基础结构
    • 抹掉原始工程痕迹

过程:

  1. 在工作空间中复制对应工程,并修改工程名称
  2. 删除与Idea相关配置文件,仅保留src目录与pom.xml文件
  3. 修改pom.xml中的artifactId与新工程/模块名相同
  4. 删除name标签(可选)
  5. 保留备份工程供后期使用

属性配置

修改服务器端口

SpringBoot默认配置文件application.properties,通过键值对配置对应属性

server.port=80
关闭运行日志图标
spring,main.banner-mode=off
设置日志相关
logging.level.root=debug
SpringBoot提供了多种属性配置方式
  • application.properties

    server.port=80
    
  • application.yml

    server:
      port: 81
    
  • application.yaml

    server:
      port: 82
    

加载顺序:

properties > yml > yaml

常用的配置文件种类:

application.yml

教你一招:自动提示功能消失解决方案

img

yaml

YAML(YAML Ain’t Markup Language),一种数据序列化格式

优点:

  • 容易阅读
  • 容易与脚本语言交互
  • 以数据为核心,重数据轻格式

yaml扩展名

  • .yml(主流)
  • .yaml
语法规则
  • 大小写敏感

  • 属性层级关系使用多行描述,每行结尾使用冒号结束

  • 使用缩进表示层级关系,同层级左侧对齐,只允许使用空格(不允许使用tab键)

  • 属性值前面添加空格(属性名与属性值之间使用冒号+空格作为分隔)

  • #表示注释

  • 核心规则:数据前面要加空格与冒号隔开

  • 字面值表示方式

    boolean: TRUE			#TRUE、true、True,FALSE,false.False均可
    float: 3.14				#支持科学计数法
    int: 123              	   #支持二进制、八进制、十六进制
    null: ~                	    #使用~表示null
    string: HelloWorld             #字符串直接书写
    string2: "Hello World"          #可以使用双引号包裹特殊字符
    date: 2018-02-17            #日期必须使用yyyy-MM-dd格式
    datetime: 2018-02-17T15:02:31+08:00 #时间和日期之间使用T连接,最后使用+代表时区
    
  • 数组表示方式

img

img

yaml数据读取

使用@Value读取单个数据,属性名引用方式:${一级属性名.二级属性名…}

    @Value("${country}")
    private String country;

    @Value("${user2.name}")
    private String name1;

    @Value("${likes[1]}")
    private String like;

    @Value("${users[1].age}")
    private String age;


    @GetMapping("/users")
    // @RequestMapping(value = "/users", method = RequestMethod.GET)
    @ResponseBody
    public String getAll() {
        System.out.println("users getAll 。。。");
        System.out.println("country =" + country);
        System.out.println("user.name =" + name1);
        System.out.println("like =" + like);
        System.out.println("age =" + age);
        return "{'model' : 'user getAll '}";
    }

在配置文件中可以使用属性名引用方式引用属性

baseDir: C:\windows

tempDir: ${baseDir}\emp
@Value("${tempDir}")
private String tempDir;
@GetMapping("/users")
// @RequestMapping(value = "/users", method = RequestMethod.GET)
@ResponseBody
public String getAll() {
    System.out.println("users getAll 。。。");
    System.out.println("tempDir =" + tempDir);
    return "{'model' : 'user getAll '}";
}

属性值中如果出现转移字符,需要使用双引号包裹

lesson: "Spring\tboot\nlesson"
@Value("${lesson}")
private String lesson;

@GetMapping("/users")
// @RequestMapping(value = "/users", method = RequestMethod.GET)
@ResponseBody
public String getAll() {
    System.out.println("users getAll 。。。");
    System.out.println("lesson =" + lesson);
    return "{'model' : 'user getAll '}";
}

封装全部数据到Environment对象

// 使用自动装配将所有的数据封装到一个对象environment中
@Autowired
private Environment environment;
@GetMapping("/users")
// @RequestMapping(value = "/users", method = RequestMethod.GET)
@ResponseBody
public String getAll() {
    System.out.println("users getAll 。。。"); 			          System.out.println(environment.getProperty("users[0].name"));
    return "{'model' : 'user getAll '}";
}

自定义对象封装指定数据的作用

yml配置文件:

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test
    username: root
    password: root

MyDataSource类:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Component
@ConfigurationProperties(prefix = "spring.datasource")
public class MyDataSource {

    private String driverClassName;
    private String url;
    private String userName;
    private String password;
}

UserController类:

@Autowired
private MyDataSource dataSource;

@GetMapping("/users")
// @RequestMapping(value = "/users", method = RequestMethod.GET)
@ResponseBody
public String getAll() {
  System.out.println("datasource =" + dataSource);
    return "{'model' : 'user getAll '}";
}

整合第三方技术

整合JUnit

@SpringBootTest
class Springboot07JunitApplicationTests {
	@Autowired
	private BookService bookService;
	@Test
	public void testSave(){
    	bookService.save();
    }
}

@SpringBootTest

类型:测试类注解

位置:测试类定义上方

作用:设置JUnit加载的SpringBoot启动类

范例:

@SpringBootTest(classes = Springboot05JUnitApplication.class)
class Springboot07JUnitApplicationTests {}

相关属性:

​ classes:设置SpringBoot启动类

注意事项

如果测试类在SpringBoot启动类的包或子包中,可以省略启动类的设置,也就是省略classes的设定

整合MyBatis

  • 核心配置:数据库相关信息(连什么?连谁?什么权限)
  • 映射配置:SQL映射(XML/注解)

步骤:

1、在创建项目时,选择模块MyBatis Framework、MySQL Driver

2、设置数据源参数

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test
    username: root
    password: root

注意事项

SpringBoot版本低于2.4.3(不含),Mysql驱动版本大于8.0时,需要在url中配置时区

jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC

或在MySQL数据库端配置时区解决问题

3、定义数据层接口与映射配置

@Mapper
public interface UserMapper {

    @Select("select * from stu where id = #{id}")
    User getById(Integer id);
}

4、测试类中注入mapper接口,测试功能

@SpringBootTest
public class MpTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void testGetById() {
        User byId = userMapper.getById(1);
        System.out.println(byId);
    }
}

整合MyBatis-Plus

MyBatis-Plus与MyBatis区别

  • 导入坐标不同
  • 数据层实现简化

步骤:

1、手动添加SpringBoot整合MyBatis-Plus的坐标,可以通过mvnrepository获取

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.1.1</version>
</dependency>

注意事项

由于SpringBoot中未收录MyBatis-Plus的坐标版本,需要指定对应的version

2、定义数据层接口与映射配置,继承BaseMapper

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

3、在User实体类中添加注解@TableName()

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("stu")
public class User {

    private Integer id;
    private String name;
    private Integer age;
}

4、测试

@SpringBootTest
public class MpTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void testGetById() {
        User byId = userMapper.selectById(1);
        System.out.println(byId);
    }
}

整合Druid

导入依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.8</version>
</dependency>

指定数据源类型

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource

spring:
  datasource:
    druid:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test
    username: root
    password: root

SSMP整合案例

实体类开发

导入lombok(一个Java类库,提供了一组注解,简化了POJO实体类开发,版本由SpringBoot提供)

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

实体类:

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("stu")
public class User {

    private Integer id;
    private String name;
    private Integer age;
}
数据层开发

技术实现方案:

  • MyBatisPlus
  • Druid

导入MyBatisPlus与Druid对应的starter

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

配置数据源与MyBatisPlus对应的基础配置(id生成策略使用数据库自增策略)

spring:
  datasource:
    druid:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test
    username: root
    password: root
#    type: com.alibaba.druid.pool.DruidDataSource

mybatis-plus:
  global-config:
    db-config:
      id-type: auto

继承BaseMapper并指定泛型

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

制作测试类测试结果

@Slf4j
@SpringBootTest
public class MpTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void testSave() {
        User user = new User();
        user.setAge(20);
        user.setName("张三");
        int insert = userMapper.insert(user);
    }

    @Test
    void testGetById(){
        System.out.println(userMapper.selectById(26));
    }
}

为了方便调试,可以开启MyBatisPlus的日志

log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
数据层开发——分页功能

分页操作需要设定分页对象IPage

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

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

分页操作是在mybatisplus的常规操作基础上增强得到的,内部是动态拼写SQL语句,因此需要增强对应的功能,使用MyBatisPlus拦截器实现

@Configuration
public class MpConfig {

    @Bean
    public MybatisPlusInterceptor mpInterceptor() {
        // 1、定义MP拦截器
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        // 2、添加具体的拦截器
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}

注意:这里如果MybatisPlusInterceptor没法导包,应该是MyBatisPlus中版本号太低,换成3.4.3.1即可

测试:

@Test
void testGetPage() {
    IPage page = new Page(1, 5);
    IPage iPage = userMapper.selectPage(page, null);
    System.out.println(iPage);
}
条件查询功能

使用QueryWrapper对象封装查询条件,推荐使用LambdaQueryWrapper对象,所有查询操作封装成方法调用

@Test
void testGetByCondition() {
    IPage page = new Page(1, 10);
    LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
    lqw.like(User::getName, "张三");
    IPage iPage = userMapper.selectPage(page, lqw);
    System.out.println(iPage);
}
@Test
void testGetByCondition1() {
    QueryWrapper<User> qw = new QueryWrapper<>();
    qw.like("name", "张三");
    List<User> users = userMapper.selectList(qw);
    for (User user : users) {
        System.out.println(user);
    }
}

支持动态拼写查询条件

@Test
void testGetByCondition2() {
    String name = "张三";
    IPage page = new Page(1, 10);
    LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
    lqw.like(Strings.isNotEmpty(name), User::getName, "张三");
    IPage iPage = userMapper.selectPage(page, lqw);
    System.out.println(iPage);
}

注意

like()方法中,如果Strings.isNotEmpty(name)返回是true,继续匹配后续条件,如果返回为false,后续条件不再匹配

业务层开发

Service层接口定义与数据层接口定义具有较大区别,不要混用

快速开发方案

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

service接口

public interface UserService extends IService<User> {

    public Boolean insert(User user);

    public Boolean modify(User user);

    public Boolean delete(Integer id);

    public User get(Integer id);
}

serviceImpl实现类

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    public Boolean insert(User user) {
        return userMapper.insert(user) > 0;
    }

    public Boolean modify(User user) {
        return userMapper.updateById(user) > 0;
    }

    public Boolean delete(Integer id) {
        return userMapper.deleteById(id) > 0;
    }

    public User get(Integer id) {
        return userMapper.selectById(id);
    }
}

测试:

@SpringBootTest
public class TestService {

    @Autowired
    private UserService userService;

    @Test
    void testInsert() {
        User byId = userService.getById(1);
        System.out.println(byId);
    }

    @Test
    void testUpdate(){
        User user = new User();
        user.setName("zhangsan");
        user.setId(1);
        boolean update = userService.modify(user);
        System.out.println(update);
    }
}
表现层开发

方案:

  • 基于Restful进行表现层接口开发
  • 使用Postman测试表现层接口功能

首先,要对表现层信息进行一致性处理

创建工具类Result

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Result {

    // 响应码 1代表成功 0代表失败
    private Integer code;
    // 相应信息 描述字符串
    private String msg;
    // 返回的数据
    private Object data;

    // 增删改,成功响应
    public static Result success() {
        return new Result(1, "success", null);
    }

    // 查询成功响应
    public static Result success(Object data) {
        return new Result(1, "success", data);
    }

    // 查询失败
    public static Result error(String msg) {
        return new Result(0, msg, null);
    }

}

表现层

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping
    public Result getAll() {
        return Result.success(userService.list());
    }

    @DeleteMapping("/{id}")
    public Result delete(@PathVariable Integer id){
        Boolean delete = userService.delete(id);
        return Result.success("删除成功");
    }

    @GetMapping("/{id}")
    public Result getById(@PathVariable Integer id) {
        User byId = userService.getById(id);
        return Result.success(byId);
    }
}

查询结果:

img

删除结果:

img

前后端协议联调
  • 前后端分离结构设计中页面归属前端服务器
  • 单体工程中页面放置在resources目录下的static目录中(建议执行clean)

前端页面:

<!DOCTYPE html>

<html>

<head>

    <!-- 页面meta -->

    <meta charset="utf-8">

    <meta http-equiv="X-UA-Compatible" content="IE=edge">

    <title>基于SpringBoot整合SSM案例</title>

    <meta content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no" name="viewport">

    <!-- 引入样式 -->

    <link rel="stylesheet" href="../plugins/elementui/index.css">

    <link rel="stylesheet" href="../plugins/font-awesome/css/font-awesome.min.css">

    <link rel="stylesheet" href="../css/style.css">

</head>

<body class="hold-transition">

<div id="app">

    <div class="content-header">

        <h1>图书管理</h1>

    </div>

    <div class="app-container">

        <div class="box">

            <div class="filter-container">
                <el-input placeholder="年龄" v-model="pagination.age" style="width: 200px;" class="filter-item"></el-input>
                <el-input placeholder="名字" v-model="pagination.name" style="width: 200px;" class="filter-item"></el-input>
                <el-input placeholder="描述" style="width: 200px;" class="filter-item"></el-input>
                <el-button @click="getAll()" class="dalfBut">查询</el-button>
                <el-button type="primary" class="butT" @click="handleCreate()">新建</el-button>
            </div>

            <el-table size="small" current-row-key="id" :data="dataList" stripe highlight-current-row>

                <el-table-column type="index" prop="id" align="center" label="序号"></el-table-column>

                <el-table-column prop="age" label="年龄" align="center"></el-table-column>

                <el-table-column prop="name" label="名字" align="center"></el-table-column>

                <el-table-column prop="description" label="描述" align="center"></el-table-column>

                <el-table-column label="操作" align="center">

                    <template slot-scope="scope">

                        <el-button type="primary" size="mini" @click="handleUpdate(scope.row)">编辑</el-button>

                        <el-button type="danger" size="mini" @click="handleDelete(scope.row)">删除</el-button>

                    </template>

                </el-table-column>

            </el-table>

            <!--分页组件-->
            <div class="pagination-container">

                <el-pagination
                        class="pagiantion"

                        @current-change="handleCurrentChange"

                        :current-page="pagination.currentPage"

                        :page-size="pagination.pageSize"

                        layout="total, prev, pager, next, jumper"

                        :total="pagination.total">

                </el-pagination>

            </div>

            <!-- 新增标签弹层 -->

            <div class="add-form">

                <el-dialog title="新增图书" :visible.sync="dialogFormVisible">

                    <el-form ref="dataAddForm" :model="formData" :rules="rules" label-position="right" label-width="100px">

                        <el-row>

                            <el-col :span="12">

                                <el-form-item label="年龄" prop="age">

                                    <el-input v-model="formData.age"/>

                                </el-form-item>

                            </el-col>

                            <el-col :span="12">

                                <el-form-item label="名字" prop="name">

                                    <el-input v-model="formData.name"/>

                                </el-form-item>

                            </el-col>

                        </el-row>


                        <el-row>

                            <el-col :span="24">

                                <el-form-item label="描述">

                                    <el-input v-model="formData.description" type="textarea"></el-input>

                                </el-form-item>

                            </el-col>

                        </el-row>

                    </el-form>

                    <div slot="footer" class="dialog-footer">

                        <el-button @click="cancel()">取消</el-button>

                        <el-button type="primary" @click="handleAdd()">确定</el-button>

                    </div>

                </el-dialog>

            </div>

            <!-- 编辑标签弹层 -->

            <div class="add-form">

                <el-dialog title="编辑检查项" :visible.sync="dialogFormVisible4Edit">

                    <el-form ref="dataEditForm" :model="formData" :rules="rules" label-position="right" label-width="100px">

                        <el-row>

                            <el-col :span="12">

                                <el-form-item label="年龄" prop="age">

                                    <el-input v-model="formData.age"/>

                                </el-form-item>

                            </el-col>

                            <el-col :span="12">

                                <el-form-item label="名字" prop="name">

                                    <el-input v-model="formData.name"/>

                                </el-form-item>

                            </el-col>

                        </el-row>

                        <el-row>

                            <el-col :span="24">

                                <el-form-item label="描述">

                                    <el-input v-model="formData.description" type="textarea"></el-input>

                                </el-form-item>

                            </el-col>

                        </el-row>

                    </el-form>

                    <div slot="footer" class="dialog-footer">

                        <el-button @click="cancel()">取消</el-button>

                        <el-button type="primary" @click="handleEdit()">确定</el-button>

                    </div>

                </el-dialog>

            </div>

        </div>

    </div>

</div>

</body>

<!-- 引入组件库 -->

<script src="../js/vue.js"></script>

<script src="../plugins/elementui/index.js"></script>

<script type="text/javascript" src="../js/jquery.min.js"></script>

<script src="../js/axios-0.18.0.js"></script>

<script>
    var vue = new Vue({
        el: '#app',
        data:{
            dataList: [],//当前页要展示的列表数据
            dialogFormVisible: false,//添加表单是否可见
            dialogFormVisible4Edit:false,//编辑表单是否可见
            formData: {},//表单数据
            rules: {//校验规则
                type: [{ required: true, message: '图书类别为必填项', trigger: 'blur' }],
                name: [{ required: true, message: '图书名称为必填项', trigger: 'blur' }]
            },
            pagination: {//分页相关模型数据
                currentPage: 1,//当前页码
                pageSize:10,//每页显示的记录数
                total:0,//总记录数
                name:""
            }
        },

        //钩子函数,VUE对象初始化完成后自动执行
        created() {
            this.getAll();
        },

        methods: {

            /*getAll() {
                axios.get("/user").then((res)=>{
                    this.dataList = res.data.data;
                })
            },*/
            //列表
            getAll() {
                param = "?name=" + this.pagination.name;
                axios.get("/user/" + this.pagination.currentPage + "/" + this.pagination.pageSize + param).then((res)=>{
                    this.pagination.total = res.data.data.total;
                    this.pagination.currentPage = res.data.data.current;
                    this.pagination.pageSize = res.data.data.size;
                    this.dataList = res.data.data.records;
                })
            },

            //弹出添加窗口
            handleCreate() {
                this.dialogFormVisible = true;
                this.resetForm();
            },

            //重置表单
            resetForm() {
                this.formData = {};
            },

            //添加
            handleAdd () {
                axios.post("/user", this.formData).then((res)=>{
                    // 如果操作成功,关闭弹层,显示数据
                    if (res.data.code == 1) {
                        this.dialogFormVisible = false;
                        this.$message.success("添加成功");
                    } else {
                        this.$message.error("添加失败");
                    }
                }).finally(()=>{
                    this.getAll();
                })
            },

            //取消
            cancel(){
                this.dialogFormVisible = false;
                this.dialogFormVisible4Edit = false;
                this.$message.info("操作取消");
            },
            // 删除
            handleDelete(row){
                // 弹出提示框
                this.$confirm("此操作永久删除当前数据,是否继续?","提示",{
                    type: 'info'
                }).then(()=>{
                    axios.delete("/user/"+row.id).then((res)=> {
                        if (res.data.code == 1) {
                            this.$message.success("删除成功");
                        } else {
                            this.$message.error("删除失败");
                        }
                    }).finally(()=>{
                        this.getAll();
                    });
                }).catch(()=>{
                    // 取消删除
                    this.$message.info("取消删除操作")
                })
            },

            //弹出编辑窗口
            handleUpdate(row) {
                axios.get("/user/"+row.id).then((res)=>{
                    if (res.data.code == 1) {
                        // 展示弹层,加载数据
                        this.formData = res.data.data;
                        this.dialogFormVisible4Edit = true;
                    } else {
                        this.$message.error("数据同步失败,自动刷新")
                    }
                })
            },

            //修改
            handleEdit() {
                axios.put("/user", this.formData).then((res)=>{
                    // 如果操作成功,关闭弹层并刷新页面
                    if (res.data.code == 1) {
                        this.dialogFormVisible4Edit = false;
                        this.$message.success("修改成功");
                    } else {
                        this.$message.error("修改失败");
                    }
                }).finally(()=>{
                    this.getAll();
                })
            },

            //分页查询

            //切换页码
            handleCurrentChange(currentPage) {
                // 修改页码为当前选中的页码值
                this.pagination.currentPage = currentPage;
                // 执行查询
                this.getAll();
            },

            //条件查询
        }
    })

</script>

</html>

列表页:

getAll() {
    axios.get("/user").then((res)=>{
        this.dataList = res.data.data;
    })
}

弹出添加窗口

//弹出添加窗口
handleCreate() {
    this.dialogFormVisible = true;
    // 重置表单
    this.resetForm();
}

添加

//添加
handleAdd () {
    axios.post("/user", this.formData).then((res)=>{
        // 如果操作成功,关闭弹层,显示数据
        if (res.data.code == 1) {
            this.dialogFormVisible = false;
            this.$message.success("添加成功");
        } else {
            this.$message.error("添加失败");
        }
    }).finally(()=>{
        this.getAll();
    })
}

取消添加

cancel(){
    this.dialogFormVisible = false;
    this.dialogFormVisible4Edit = false;
    this.$message.info("操作取消");
}

删除

// 删除
handleDelete(row){
    // 弹出提示框
    this.$confirm("此操作永久删除当前数据,是否继续?","提示",{
        type: 'info'
    }).then(()=>{
        axios.delete("/user/"+row.id).then((res)=> {
            if (res.data.code == 1) {
                this.$message.success("删除成功");
            } else {
                this.$message.error("删除失败");
            }
        }).finally(()=>{
            this.getAll();
        });
    }).catch(()=>{
        // 取消删除
        this.$message.info("取消删除操作")
    })
}

弹出修改窗口

handleUpdate(row) {
    axios.get("/user/"+row.id).then((res)=>{
        if (res.data.code == 1) {
            // 展示弹层,加载数据
            this.formData = res.data.data;
            this.dialogFormVisible4Edit = true;
        } else {
            this.$message.error("数据同步失败,自动刷新")
        }
    })
}

修改

//修改
handleEdit() {
    axios.put("/user", this.formData).then((res)=>{
        // 如果操作成功,关闭弹层并刷新页面
        if (res.data.code == 1) {
            this.dialogFormVisible4Edit = false;
            this.$message.success("修改成功");
        } else {
            this.$message.error("修改失败");
        }
    }).finally(()=>{
        this.getAll();
    })
}

分页操作

//列表
getAll() {
    param = "?name=" + this.pagination.name;
    axios.get("/user/" + this.pagination.currentPage + "/" + this.pagination.pageSize + param).then((res)=>{
        this.pagination.total = res.data.data.total;
        this.pagination.currentPage = res.data.data.current;
        this.pagination.pageSize = res.data.data.size;
        this.dataList = res.data.data.records;
    })
}

userServiceImpl类

public IPage<User> getPage(Integer currentPage, Integer pageSize, User queryUser) {
    IPage page = new Page(currentPage, pageSize);
    LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
    lqw.like(Strings.isNotEmpty(queryUser.getName()), User::getName, queryUser.getName());

    return userMapper.selectPage(page, lqw);
}

userController类

@GetMapping("{currentPage}/{pageSize}")
public Result getAll(@PathVariable int currentPage, @PathVariable int pageSize, User user) {
    IPage<User> page = userService.getPage(currentPage, pageSize, user);
    System.out.println(page);
    return Result.success(page);
}

分页页码值切换

//切换页码
handleCurrentChange(currentPage) {
    // 修改页码为当前选中的页码值
    this.pagination.currentPage = currentPage;
    // 执行查询
    this.getAll();
}

总结

介于SpringBoot的SSMP整合案例的步骤:
  1. pom.xml

    配置起步依赖

  2. applicaiton.yml

    设置数据源、端口、框架技术相关配置等

  3. mapper

    继承BaseMapper、设置@Mapper

  4. mapper测试类

  5. service

    调用数据层接口或Mybatis-plus提供的接口快速开发

  6. controller

    基于Restful开发,使用postman测试跑通功能

  7. 页面

    放置在resources目录下的static目录中

img

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/642224.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

pycharm使用之torch_geometric安装

正式安装之前要先查看一下torch的版本 一、查看torch版本 1、winR &#xff0c;输入cmd 2、输入python 3、 输入import torch&#xff0c;然后输入torch.__version__&#xff0c;最后回车 可以看到我的torch版本是1.10.0 二、下载合适的版本 1、打开链接 https://pytorch-…

千万级入口服务[Gateway]框架设计(一)

本文将以技术调研模式编写&#xff0c;非技术同学可跳过。 文章目录 背景问题[不涉及具体业务]目标技术选型语言框架模式实现一&#xff1a;go 原生组件Demo 实现Benchwork 基准性能小结实现二&#xff1a;开源 go-plugin 附录入口服务演变 背景 在历史架构的迭代中&#xff…

Elasticsearch:部署 ELSER - Elastic Learned Sparse EncoderR

警告&#xff1a;此功能处于技术预览阶段&#xff0c;可能会在未来的版本中更改或删除。 Elastic 将尽最大努力修复任何问题&#xff0c;但技术预览中的功能不受官方 GA 功能的支持 SLA 约束。 Elastic Learned Sparse EncodeR - 或 ELSER - 是由 Elastic 训练的检索模型&#…

Python程序员必会技能:如何在Python中连接数据库获取数据

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 想要成为一名数据分析师&#xff0c;一个最基础的技能就是&#xff1a;提取数据。 数据是数据分析的基础。 因此&#xff0c;掌握各种获取数据的技能一定是一个合格的数据分析师的必备技能。 而我们的需要进行提取的…

总结排查服务器上传下载慢的几种手段与查看服务器带宽的具体方法

一、排查服务器上传下载 最近出现的一个情况&#xff0c;服务器上传和下载比较慢&#xff0c;因此我排查了种种手段&#xff0c;特此记录下几种常见的手段。 1、使用speedtest-cli 测试网速&#xff1a; 该方法是测试网速的速度怎么样&#xff0c;看看是否真的慢&#xff1f; …

python中os库用法详解(总结)

os库主要是对文件和文件夹进行操作&#xff0c;在Python中对⽂件和⽂件夹的操作要借助os模块⾥⾯的相关功能。 具体步骤如下&#xff1a; 1. 导⼊os模块 import os 2. 使⽤ os 模块相关功能 os.函数名() 1、⽂件重命名 os.rename(⽬标⽂件名, 新⽂件名) 示例代码&#…

使用Docker从0开始在Linuex部署springboot项目(图文并茂)

一、前言 在腾讯云新买的洁白如新的云服务器&#xff0c;想要使用docker去部署springboot项目&#xff0c;特此记录&#xff01; 二、安装jdk 参考博客&#xff1a;https://blog.csdn.net/weixin_45853881/article/details/123402891 2.1 检查jdk 直接在腾讯云平台登陆云服…

软件测试进阶知识 —— 自动化测试总结

自动化测试 自动化测试的定义&#xff1a;使用一种自动化测试工具来验证各种软件测试的需求&#xff0c;它包括测试活动的管理与实施、测试脚本的开发与执行。 自动化测试只是测试工作的一部分&#xff0c;是对手工测试的一种补充; 自动化测试绝不能代替手工测试;多数情况下&a…

怎样高效率备考PMP

一方面由于这些考试的知识&#xff0c;在准备考试前我们大部分很少接触&#xff0c;大部分人考试的目的也未必是感兴趣&#xff0c;更多是因为考试结果能给我们带来的收益。因此长时间的学习不熟悉甚至不感兴趣的很容易疲倦&#xff0c;这不像我们工作或生活中的一些技能&#…

怎样用U盘重装Win10系统?用U盘重装Win10系统教程

怎样用U盘重装Win10系统&#xff1f;有些新手用户在问怎样用U盘才能完成Win10系统的重装&#xff0c;这时候用户需要准备一个U盘、一个能够正常联网的电脑&#xff0c;然后按照以下分享的用U盘重装Win10系统教程操作&#xff0c;就能轻轻松松完成Win10系统的重装。 准备工作&am…

482576-74-9,Fmoc-Thr(Ac4Manα1-2Ac3Manα1-2Ac3Manα)-OH,肽链中可以糖基化的主要是Ser和Thr

【产品描述】 Fmoc-Thr(Ac4Manα1-2Ac3Manα1-2Ac3Manα)-OH&#xff08;CAS:482576-74-9&#xff09;中肽链中可以糖基化的主要是Ser和Thr&#xff0c;此外还有酪氨酸、羟赖氨酸和羟脯氨酸糖基化修饰的糖肽&#xff0c;链接的位点是这些残基侧链上的羟基氧原子。连接的糖为半乳…

Element常用组件之 表单组件 form

1. 建立form.vue <template><el-form ref"form" :model"form" label-width"80px"><el-form-item label"活动名称"><el-input v-model"form.name"></el-input></el-form-item><el-f…

Pandas的窗口函数rolling和expanding用法说明

Pandas的窗口函数rolling和expanding 1、rolling 移动窗口 rolling() 移动窗口函数&#xff0c;它可以与 mean、count、sum、median、std 等聚合函数一起使用。为了使用方便&#xff0c;Pandas 为移动函数定义了专门的方法聚合方法&#xff0c;比如 rolling_mean()、rolling_…

ArduPilot之H743自动PID调节

ArduPilot之H743自动PID调节 1. 源由2. 涉及参数2.1 AUTOTUNE_*2.2 RCx_OPTION 3. 自动校准3.1 预准备3.2 参数配置3.3 操作步骤 4. 实操&总结5. 参考资料6. 补充视频 1. 源由 ArduCopter可以自动通过算法来对PID进行调优&#xff0c;不过这里有个前提是模型噪声要比较少。…

Mysql数据库的初体验

数据库管理系统是一个由因相互关联的数据的集合和一组用访问这些数据的程序组成&#xff0c;这个数据集合通常称作数据库&#xff0c;其中包含了关于某个企业的信息。DBMS的主要目标就是提供一种可以方便高效的存取数据库信息的途径。 一、数据库的基本概念 1.数据库的组成 ①…

一文让你了解appium自动化的工作原理

目录 前言&#xff1a; 一、Appium加载的过程图解 二、初步认识appium工作过程 三、bootstrap介绍 四、所使用的技术 五、Capabilities 六、自我理解的工作原理 前言&#xff1a; Appium是一个流行的开源自动化测试框架&#xff0c;支持移动应用程序的自动化测试。 一…

Varnish开源HTTP反向代理缓存服务器

第三阶段基础 时 间&#xff1a;2023年6月13日 参加人&#xff1a;全班人员 内 容&#xff1a; Varnish 目录 Varnish 端口号&#xff1a;TCP/6081 TCP/6082 配置文件&#xff1a;/etc/varnish/default.vcl 安装部署&#xff1a; 测试功能&#xff1a; Varnish V…

6月14日晚 19:00公开课直播 | 入门必看:40min 掌握低代码基础功能

大家好&#xff0c;新一期「ONEIN 公开课」要和大家见面啦&#xff01; Onein 公开课介绍 Onein 公开课&#xff0c;是万应低代码开设的直播课堂&#xff0c;专注低代码领域&#xff0c;希望帮助每一位用户更好的使用万应低代码。 随着低代码的兴起&#xff0c;低代码这一名词…

从小白到大神之路之学习运维第39天---第三阶段---MongoDB非关系型数据库(概述、安装、设置管理员、简单操作、配置文件说明,备份和还原)

第三阶段基础 时 间&#xff1a;2023年6月13日 参加人&#xff1a;全班人员 内 容&#xff1a; 目录 MongoDB概述 端口号&#xff1a;TCP/27017 配置文件&#xff1a;/etc/mongod.conf MongoDb安装部署 MongoDB设置密码 MongoDB操作命令与说明 配置文件说明 备份操作 1. 热备…

chatgpt赋能python:Python怎么居中对齐

Python怎么居中对齐 在Python中&#xff0c;输出对齐是一项基本功能。当我们想要打印表格或美化输出时&#xff0c;居中对齐是一个常见的要求。本文将介绍如何使用Python进行居中对齐&#xff0c;以及一些相关的技术和应用。 如何居中对齐&#xff1f; 要在Python中实现居中…