Spring Boot 2 + VSCode 学习笔记

1,188 阅读7分钟

写在最前面

用了10年+的 PHP 从原生到 ThinkPHP 又到 Laravel 真的很方便。 为了突破自己跳出舒适圈,决定从现在开始学习 Spring Boot 做后端。 至于为什么用 VSCode 而不是 IEDA ? 因为已经很熟悉 VSC 的界面和操作逻辑,等实在觉得 IEDA 很方便的时候再换坑吧,哈哈哈~~~

VSCode 搭建环境

Extension Pack for JavaSpring Boot Extension Pack 大礼包装就完事。

  1. marketplace.visualstudio.com/items?itemN… image.png
  2. marketplace.visualstudio.com/items?itemN… image.png

VSCode 新建项目

你可以在线 https://start.spring.io/ 配置项目。

当然我这里用的是 VSCode 自然编辑器里也可以直接配置。

初始依赖包

  1. F1 输入 Spring Initializr:Crate a Maven Project 肥册 image.png

  2. 依赖包选择,先安装 Spring Boot DevToolsSpring Web image.png

  3. 之后如果要追加依赖包,可以通过 https://mvnrepository.com/ 查询追加到 pom.xml<dependencies> 内部,也可以通过 VSCode 里的 MAVEN 工具栏搜索选择后自动添加如下图。 image.png

Hello World

  1. src\main\java\com\example\juejin 新建目录 controller 新建文件 IndexController.java
    package com.example.juejin.controller;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class IndexController {
        @RequestMapping("/")
        public String index(){
            return "Hello World";
        }
    }
    
  2. 右上角点击 Run Java 运行,或者安装插件 Spring Boot Dashboard 来运行
  3. 浏览器输入 http://localhost:8080Hello World 粗线了!
  4. 默认 8080 可以在 src\main\resources\application.properties 修改 server.port=8080

连接数据库

一. 安装依赖包

  1. MySQL Connector Java
  2. Spring Data JDBC
  3. Spring Boot Starter Data JPA
  4. Project Lombok

二. 配置数据库信息

src\main\resources\application.properties 追加

spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/spring_boot_juejin?useUnicode=true&characterEncoding=UTF-8&useSSL=true&serverTimezone=UTC
spring.datasource.username = root
spring.datasource.password = root

spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql = true

如果 MySQL Connector Java 安装的是 8.x MySQL 的版本也必须是 8.x 的

三. 数据返回JSON格式

  1. 实体类 在 src\main\java\com\example\juejin 新建目录 domain 新建文件 Users.java 和数据库表名一致,内部的属性名字和字段名保持一致。
    package com.example.juejin.domain;
    
    import javax.persistence.Entity;
    import javax.persistence.Id;
    
    import lombok.Data;
    
    @Entity
    @Data
    public class Users {
        @Id
        private Integer id;
        private String name;
        private Integer age;
        private String email;
    }
    
  2. 操作数据库类 在 src\main\java\com\example\juejin 新建目录 dao 新建文件 UsersRepository.java 这里文件名不强制和数据库表一致,只是强迫症。
    package com.example.juejin.dao;
    
    import java.util.List;
    
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.data.jpa.repository.Query;
    
    import com.example.juejin.domain.Users;
    
    public interface UsersRepository extends JpaRepository<Users, Integer> {
        @Query(value = "SELECT * FROM users", nativeQuery = true)
        List<Users> getAll();
    }
    
  3. src\main\java\com\example\juejin\controller\IndexController.java 完整版
    package com.example.juejin.controller;
    
    import java.util.List;
    
    import javax.annotation.Resource;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import com.example.juejin.dao.UsersRepository;
    import com.example.juejin.domain.Users;
    
    @RestController
    public class IndexController {
        @RequestMapping("/")
        public String index(){
            return "Hello World";
        }
    
        @Resource
        private UsersRepository usersRepository;
    
        @RequestMapping("/users")
        public List<Users> getUsers(){
            return usersRepository.getAll();
        }
    }
    
  4. 浏览器输入 http://localhost:8080/usersJSON 数据粗线了!

连接数据库(简约版)

使用了 MyBatis 更加方便!

一. 安装依赖包

  1. MySQL Connector Java
  2. MyBatis Spring
  3. Project Lombok

二. 配置数据库信息

src\main\resources\application.properties 追加

spring.datasource.url = jdbc:mysql://localhost:3306/spring_boot_juejin?useUnicode=true&characterEncoding=UTF-8&useSSL=true&serverTimezone=UTC
spring.datasource.username = root
spring.datasource.password = root

如果 MySQL Connector Java 安装的是 8.x MySQL 的版本也必须是 8.x 的

三. 数据返回JSON格式

  1. 【实体类对应数据库表】定义 entity 包,在 src\main\java\com\example\juejin 新建目录 entity 新建文件 Users.java 和数据库表名一致,内部的属性名字和字段名保持一致。
    package com.example.juejin.entity;
    
    import lombok.Data;
    
    @Data
    public class Users {
        private Integer id;
        private String name;
        private Integer age;
        private String email;
    }
    
  2. 【接口操作数据库】定义 mapper 包,在 src\main\java\com\example\juejin 新建目录 mapper 新建文件 UsersMapper.java 这里文件名不强制和数据库表一致,只是强迫症。
    package com.example.juejin.mapper;
    
    import java.util.List;
    
    import org.apache.ibatis.annotations.Select;
    
    import com.example.juejin.entity.Users;
    
    public interface UsersMapper {
        @Select("SELECT * FROM users")
        List<Users> findAll();
    }
    
  3. 【配置启动MyBatis】在 demoApplication 添加 @MapperScan("com.example.juejin.mapper")
    package com.example.juejin;
    
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    @MapperScan("com.example.juejin.mapper")
    public class JuejinApplication {
    
            public static void main(String[] args) {
                    SpringApplication.run(JuejinApplication.class, args);
            }
    
    }
    
  4. 【控制器】src\main\java\com\example\juejin\controller\UsersController.java
    package com.example.juejin.controller;
    
    import java.util.List;
    
    import javax.annotation.Resource;
    
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import com.example.juejin.entity.Users;
    import com.example.juejin.mapper.UsersMapper;
    
    @RestController
    @RequestMapping("/users")
    public class UsersController {
        @Resource
        UsersMapper usersMapper;
    
        @GetMapping
        public List<Users> getUsers(){
            return usersMapper.findAll();
        }
    }
    
  5. 浏览器输入 http://localhost:8080/usersJSON 数据粗线了!
增删改查(入门版)

只是简单实现 CRUD 功能,比如删除和修改功能没有做成功与否判断。

  1. 【接口操作数据库】src\main\java\com\example\juejin\mapper\UsersMapper.java
    package com.example.juejin.mapper;
    
    import java.util.List;
    
    import org.apache.ibatis.annotations.Delete;
    import org.apache.ibatis.annotations.Select;
    import org.apache.ibatis.annotations.Update;
    import org.springframework.transaction.annotation.Transactional;
    
    import com.example.juejin.entity.Users;
    
    public interface UsersMapper {
        // 获取 users 表全部数据
        @Select("SELECT * FROM `users`")
        List<Users> findAll();
    
        // 查询 指定 id 数据
        @Select("SELECT * FROM `users` WHERE `id` = #{id}")
        Users findById(Long id);
    
        // 添加
        @Update("INSERT INTO `users` (`name`, `age`, `email`) VALUES (#{name}, #{age}, #{email});")
        @Transactional
        void save(Users user);
    
        // 删除
        @Delete("DELETE FROM `users` WHERE `id` = #{id}")
        void deleteById(Long id);
    
        // 修改
        @Update("UPDATE `users` SET `name` = #{name}, `age` = #{age}, `email` = #{email} WHERE `id` = #{id};")
        @Transactional
        void updateById(Users user);
    }
    
  2. 【控制器】src\main\java\com\example\juejin\controller\UsersController.java
    package com.example.juejin.controller;
    
    import java.util.List;
    
    import javax.annotation.Resource;
    
    import org.springframework.web.bind.annotation.DeleteMapping;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.PutMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import com.example.juejin.entity.Users;
    import com.example.juejin.mapper.UsersMapper;
    
    @RestController
    @RequestMapping("/users")
    public class UsersController {
        @Resource
        UsersMapper usersMapper;
    
        // 获取 users 表全部数据
        @GetMapping
        public List<Users> getUsers(){
            return usersMapper.findAll();
        }
    
        // 查询 指定 id 数据
        @GetMapping("/{id}")
        public Users findById(@PathVariable("id") Long id){
            return usersMapper.findById(id);
        }
    
        // 添加
        @PostMapping
        public String addUser(@RequestBody Users user) {
            usersMapper.save(user);
            return "添加成功";
        }
    
        // 删除
        @DeleteMapping("/{id}")
        public String deleteUser(@PathVariable("id") Long id) {
            usersMapper.deleteById(id);
            return "删除成功";
        }
    
        // 修改
        @PutMapping
        public String updateUser(@RequestBody Users user) {
            usersMapper.updateById(user);
            return "修改成功";
        }
    }
    

连接数据库(MyBatis-Plus)

官方文档:baomidou.com

一. 安装 MyBatis-Plus (安装 MyBatis-Plus 就不需要安装 MyBatis 了,二者只安装一个。)

<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.2</version>
</dependency>

二. 配置文件 com\example\juejin\common\config\MybatisPlusConfig.java

package com.example.juejin.common.config;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;

@Configuration
@MapperScan("com.example.juejin.mapper")
public class MybatisPlusConfig {
    /**
     * 分页插件 不配置数据不会分页
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
        return interceptor;
    }
}

三. 数据库读取

  1. 【实体类对应数据库表】com\example\juejin\entity\User.java
    package com.example.juejin.entity;
    
    import com.baomidou.mybatisplus.annotation.IdType;
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableName;
    
    import lombok.Data;
    
    @TableName("user") // MyBatis-Plus
    @Data
    public class User {
        @TableId(type = IdType.AUTO) // MyBatis-Plus
        private Integer id;
        private String username;
        private String password;
        private String nickName;
        private Integer age;
        private String sex;
        private String address;
    }
    
  2. 【接口操作数据库】com\example\juejin\mapper\UserMapper.java
    package com.example.juejin.mapper;
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.example.juejin.entity.User;
    
    public interface UserMapper extends BaseMapper<User> { // MyBatis-Plus
    
    }
    
  3. 添加自定义 【Result】 工具类
    package com.example.juejin.common;
    
    public class Result<T> {
        private String code;
        private String msg;
        private T data;
    
        public String getCode() {
            return code;
        }
    
        public void setCode(String code) {
            this.code = code;
        }
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    
        public T getData() {
            return data;
        }
    
        public void setData(T data) {
            this.data = data;
        }
    
        public Result() {
        }
    
        public Result(T data) {
            this.data = data;
        }
    
        public static Result<?> success() {
            Result<?> result = new Result<>();
            result.setCode("0");
            result.setMsg("成功");
            return result;
        }
    
        public static <T> Result<T> success(T data) {
            Result<T> result = new Result<>(data);
            result.setCode("0");
            result.setMsg("成功");
            return result;
        }
    
        public static Result<?> error(String code, String msg) {
            Result<?> result = new Result<>();
            result.setCode(code);
            result.setMsg(msg);
            return result;
        }
    }
    
增删改查

【控制器】com\example\juejin\controller\UsersController.java 通过 Result 返回状态

package com.example.juejin.controller;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.juejin.common.Result;
import com.example.juejin.entity.User;
import com.example.juejin.mapper.UserMapper;

@RestController
@RequestMapping("/user")
public class UserController {
    @Resource
    UserMapper userMapper;

    // 添加
    @PostMapping
    public Result<?> save(@RequestBody User user){
        Integer res = userMapper.insert(user);
        if(res != 1 ){
            return Result.error("-1", "数据添加失败");
        }
        return Result.success(res);
    }

    // 删除
    @DeleteMapping("/{id}")
    public Result<?> delete(@PathVariable Long id){
        Integer res = userMapper.deleteById(id); // 成功 data 返回 1
        if(res == 0 ){
            return Result.error("-1", "数据不存在");
        }
        return Result.success(res);
    }

    // 修改
    @PutMapping
    public Result<?> update(@RequestBody User user){
        Integer res = userMapper.updateById(user); // 成功 data 返回 1
        if(res == 0 ){
            return Result.error("-1", "数据不存在");
        }
        return Result.success(user);
    }

    // 查询 user 表全部数据
    @GetMapping
    public Result<?> findAll(@RequestParam(defaultValue = "1") Integer pageNum, 
                             @RequestParam(defaultValue = "5") Integer pageSize){
        Page<User> userPage = userMapper.selectPage(new Page<>(pageNum, pageSize),null); // 分页查询
        // List<User> users = userMapper.selectList(null); // 查询全部记录
        return Result.success(userPage);
    }

    // 查询 指定 id 数据
    @GetMapping("/{id}")
    public Result<?> findById(@PathVariable Long id){
        User res = userMapper.selectById(id); // 成功 data 返回数据
        if(res == null){
            return Result.error("-1", "数据不存在");
        }
        return Result.success(res);
    }
}
注册和登录

注册判断是否已存在

package com.example.juejin.controller;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.juejin.common.Result;
import com.example.juejin.entity.User;
import com.example.juejin.mapper.UserMapper;

@RestController
@RequestMapping("/user")
public class UserController {
    @Resource
    UserMapper userMapper;
    
    // 登录
    @PostMapping("/login")
    public Result<?> login(@RequestBody User user){
        // 验证 username 和 password 是否匹配
        User res = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername, user.getUsername()).eq(User::getPassword, user.getPassword()));
        if(res == null){
            return Result.error("-1", "用户名或密码错误");
        }
        return Result.success(res);
    }

    // 注册
    @PostMapping("/register")
    public Result<?> register(@RequestBody User user){
        User res = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername, user.getUsername()));// 判断 username 是否已存在
        Integer res2 = userMapper.insert(user);
        if(res != null){
            return Result.error("-1", "用户名已存在");
        }
        if(res2 != 1 ){
            return Result.error("-1", "数据添加失败");
        }
        return Result.success(res);
    }
}
图片上传和读取

com\example\juejin\controller\FileController.java

package com.example.juejin.controller;

import java.io.IOException;
import java.io.OutputStream;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.example.juejin.common.Result;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;

@RestController
@RequestMapping("/files")
public class FileController {
    // 上传图片
    @PostMapping("/upload")
    public Result<?> upload(MultipartFile file) throws IOException{
        String originalFilename = file.getOriginalFilename();
        String uuid = IdUtil.fastSimpleUUID(); // hutool 需要重启
        String rootFilePath = System.getProperty("user.dir") + "/src/main/resources/files/" + uuid + "_" + originalFilename;
        FileUtil.writeBytes(file.getBytes(), rootFilePath); // hutool
        return Result.success(uuid + "_" + originalFilename);
    }

    // 读取图片
    @GetMapping("/{flag}")
    public void getFiles(@PathVariable String flag, HttpServletResponse response) {
        OutputStream os;  // 新建一个输出流对象
        String basePath = System.getProperty("user.dir") + "/src/main/resources/files/";  // 定于文件上传的根路径
        List<String> fileNames = FileUtil.listFileNames(basePath);  // 获取所有的文件名称
        String fileName = fileNames.stream().filter(name -> name.contains(flag)).findAny().orElse("");  // 找到跟参数一致的文件
        try {
            if (StrUtil.isNotEmpty(fileName)) {
                response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
                response.setContentType("application/octet-stream");
                byte[] bytes = FileUtil.readBytes(basePath + fileName);  // 通过文件的路径读取文件字节流
                os = response.getOutputStream();   // 通过输出流返回文件
                os.write(bytes);
                os.flush();
                os.close();
            }
        } catch (Exception e) {
            System.out.println("文件下载失败");
        }
    }
}

本番部署

安装 Maven
  1. maven.apache.org/download.cg… 解压到 C:\apache-maven-3.8.6
  2. VSCode Maven for Java 配置 C:\apache-maven-3.8.6\bin\mvn image.png
打包
  1. MAVEN - clear
  2. MAVEN - compile
  3. MAVEN - package 获得到 juejin\target\***.jar

如果在打包中出现报错,点击 MAVEN 右上角 重新加载所有 MAVEN 项目 按钮,再打包就不会报错了。

image.png

上传本番

持续更新