springboot を使い始めるのは簡単です

1. SpringBoot プロジェクトは、mysql データベースを作成および構成します。

プロジェクトを作成する

開発環境:アイデア

Spring Initializer を使用してSpring Boot アプリケーションを迅速に生成する

まず左上隅をクリックし、「ファイル」→「新規作成」→「プロジェクト」をクリックします。

画像-20230511110042756

プロジェクト情報を入力します。注: Java バージョン 8 を選択して、「次へ」をクリックします。

画像-20230511110427609

注: インストールする必要があるプラグイン

Developer Tools选项下的Spring Boot DevTools和Lombok
Web选项下的Spring Web
SQL选项下的MySQL Driver

画像-20230511111212840

プロジェクトを初期化するための進行状況バーが左下隅と右下隅に表示されず、右上隅に Springboot プロジェクトであることが認識されると、プロジェクトは正常に作成されます。

画像-20230511111518062

この時点でプロジェクトを起動して正常か確認すると、以下のメッセージが表示されれば正常に起動できます(ポート:8080)

画像-20230511111613762

ブラウザを使用して URL を開くと、次のインターフェイスが表示されます

localhost:8080

画像-20230511111707686

コントローラーテストの書き込み

新しいクラスを作成し、TestControllerサブパッケージcontrollerの下に置きます

画像-20230511112047982

画像-20230511112122798

新しいものを作成したら、次のコードを記述して追加します。

元のコード:

package com.example.mini_program_yln.controller;

public class TestController {
    
    
   
}

修正後

package com.example.mini_program_yln.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

//将数据以json格式返回给前端
@RestController
public class TestController {
    
    
    @GetMapping("/test")
    public String test() {
    
    
        return "Hello world!";
    }
}

次のプロジェクトを再開し、にアクセスしてください。

localhost:8080/test

画像-20230511112530389

構成データベース

リソースディレクトリに新しいapplication.ymlファイルを作成します

画像-20230511112755564

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mini_program?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: 111111

説明:

通常、データベース名、mysql アカウント、mysql パスワードを変更する必要があります。

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/数据库名字?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
    username: mysql的账号
    password: mysql的密码

ここでは、navicatを使用して事前に新しいデータベースを作成する必要があります

画像-20230511113449360

2. SpringBoot は mybatis-plus を統合します

公式サイト:https://www.baomidou.com/

mybatis-plus はデータベースを操作するための永続化レイヤー フレームワークです

データベースを初期化する

公式サイトによると: 運営

https://www.baomidou.com/pages/226c21/#%E5%88%9D%E5%A7%8B%E5%8C%96%E5%B7%A5%E7%A8%8B

navicat を開き (idea を使用して mysql に接続することも、hedisql などの他のツールを使用して接続することもできます)、クエリをクリックして、作成したばかりのデータベースを選択します

以下のコードを貼り付けて「実行」をクリックします

DROP TABLE IF EXISTS user;

CREATE TABLE user
(
    id BIGINT(20) NOT NULL COMMENT '主键ID',
    name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
    age INT(11) NULL DEFAULT NULL COMMENT '年龄',
    email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
    PRIMARY KEY (id)
);

DELETE FROM user;

INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, '[email protected]'),
(2, 'Jack', 20, '[email protected]'),
(3, 'Tom', 28, '[email protected]'),
(4, 'Sandy', 21, '[email protected]'),
(5, 'Billie', 24, '[email protected]');

画像-20230511115825061

この時点で、ユーザーテーブルが自動的に作成され、いくつかのサンプルデータが挿入されます

画像-20230511115935174

mybatis-plus をインストールする

1. pom.xml ファイルに依存関係を導入します。

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

画像-20230511120143287

2. 悪意のあるフルテーブル更新および削除を防ぐために、フルテーブル更新および削除防止プラグインを設定します。

update および delete ステートメントの場合: 悪意のあるテーブル全体の更新および削除を防止します。

次のパスの下に新しいパッケージを作成します: config

画像-20230511120420530

図のように作成されました

画像-20230511120503979

次に、 config パッケージの下に新しいMybatisPlusConfig クラスを作成します

次に、次のコードを追加し、関連クラスをインポートします。

@Configuration
public class MybatisPlusConfig {
    
    
  @Bean
  public MybatisPlusInterceptor mybatisPlusInterceptor() {
    
    
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
    return interceptor;
  }
}

成功例を追加

package com.example.mini_program_yln.config;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/*
* 针对 update 和 delete 语句 作用: 阻止恶意的全表更新删除
* */
@Configuration
public class MybatisPlusConfig {
    
    
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
    
    
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
        return interceptor;
    }
}

将来的にここにページネーション設定を追加することも可能です

mybatis-plus を介したインターフェースを介してデータベース データを表示します。

次のディレクトリに新しいエンティティ サブパッケージを作成します

画像-20230511121028366

次に、エンティティ パッケージの下に新しい User クラスを作成し、次のコードを追加します。

package com.example.mini_program_yln.entity;

import lombok.Data;

@Data
public class User {
    
    
    //表示id是主键,且插入数据时自增
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}


新しいマッパー サブパッケージを作成する

画像-20230511123445106

BaseMapper から継承する新しい UserMapper インターフェイスを作成する

package com.example.mini_program_yln.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.mini_program_yln.entity.User;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper extends BaseMapper<User> {
    
    



}

画像-20230511123633482

TestController.java ファイルに移動してマッパーをテストしましょう

package com.example.mini_program_yln.controller;

import com.example.mini_program_yln.entity.User;
import com.example.mini_program_yln.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

//将数据以json格式返回给前端
@RestController
public class TestController {
    
    
    @Autowired
    private UserMapper userMapper;

    @GetMapping("/testList")
    public List<User> testList() {
    
    
        return userMapper.selectList(null);
    }
}

Access http://localhost:8080/testList、データベース内のすべてのデータ User テーブルが返されます

画像-20230511124201282

3. SpringBoot の 3 層アーキテクチャ コントローラー、サービス、Dao

画像-20230511124751071

現在、私たちのプロジェクトはまだ貧弱で、サービスは作成されていません

画像-20230511124922074

作成後

画像-20230511125006504

サービス パッケージの下に新しいインターフェイスを作成しIUserService、次のコードを追加します。

画像-20230511125032285

package com.example.mini_program_yln.servicce;

import com.baomidou.mybatisplus.extension.service.IService;
import com.example.mini_program_yln.entity.User;

public interface IUserService extends IService<User> {
    
    
}

次に、サービス パッケージの下に新しい impl サブパッケージを作成し、 impl パッケージの下に新しいUserServiceImplクラスを作成します。

画像-20230511125228789

次のコードを追加します

ServiceImpl を継承し、カスタム IUserService を実装する必要がある

package com.example.mini_program_yln.servicce.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.mini_program_yln.entity.User;
import com.example.mini_program_yln.mapper.UserMapper;
import com.example.mini_program_yln.servicce.IUserService;

public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    
    
}

4. SpringBoot は Mabatis-plus を統合して、追加、削除、変更、およびクエリ インターフェイスを作成します

にコードを記述しIUserService.java、いくつかのインターフェースを定義します

package com.example.mini_program_yln.servicce;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.mini_program_yln.entity.User;

import java.util.List;

public interface IUserService extends IService<User> {
    
    

    Page<User> page(Integer current, Integer size, String username);

    boolean saveOrUpdateById(User user);

    boolean deleteBatchIds(List<Integer> ids);

}

UserServiceImpl.javaいくつかのインターフェイスを実装します

赤い波線の線上にマウスを置いてクリックする实现方法とメソッド本体が自動生成されます

画像-20230511131319493

package com.example.mini_program_yln.servicce.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.mini_program_yln.entity.User;
import com.example.mini_program_yln.mapper.UserMapper;
import com.example.mini_program_yln.servicce.IUserService;

import java.util.List;

public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    
    
    @Override
    public Page<User> page(Integer current, Integer size, String username) {
    
    
        return null;
    }

    @Override
    public boolean saveOrUpdateById(User user) {
    
    
        return false;
    }

    @Override
    public boolean deleteBatchIds(List<Integer> ids) {
    
    
        return false;
    }
}

ロジックの具体的な実装を書く

package com.example.mini_program_yln.servicce.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.injector.methods.DeleteBatchByIds;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.mini_program_yln.entity.User;
import com.example.mini_program_yln.mapper.UserMapper;
import com.example.mini_program_yln.servicce.IUserService;

import javax.annotation.Resource;
import java.util.List;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    
    
    @Override
    public Page<User> page(Integer current, Integer size, String username) {
    
    
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        if (!"".equals(username)) {
    
    
            //不为空
            //精确查询
            //wrapper.eq(User::getName,username);

            //模糊查询
            wrapper.like(User::getName, username);
        }
        Page<User> page = page(new Page<>(current, size), wrapper);
        return page;
    }

    @Override
    public boolean saveOrUpdateById(User user) {
    
    
        if (user.getId() != null) {
    
    
            //更新
            return updateById(user);
        } else {
    
    
            //新增
            return save(user);
        }
    }

    @Override
    public boolean deleteBatchIds(List<Integer> ids) {
    
    
        return removeByIds(ids);
    }
}

次に、コントローラー パッケージの下に新しい UserController.java クラスを作成します。

package com.example.mini_program_yln.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.mini_program_yln.entity.User;
import com.example.mini_program_yln.servicce.impl.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Description;
import org.springframework.web.bind.annotation.*;

import java.util.List;

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

    @Autowired
    private UserServiceImpl userService;

    @GetMapping("/page")
    @Description("分页列表-模糊查询")
    public Page<User> page(@RequestParam(defaultValue = "") String username, @RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer size) {
    
    
        return userService.page(current, size, username);
    }

    @PostMapping("/save")
    @Description("新增或更新")
    public boolean save(@RequestBody User user) {
    
    
        return userService.saveOrUpdateById(user);
    }

    @PostMapping("/delete")
    @Description("删除")
    public boolean delete(@RequestBody List<Integer> ids) {
    
    
        return userService.deleteBatchIds(ids);
    }

}

MybatisPlusConfig.javaまた、ページネーション設定項目を に追加する必要があります。次の行を追加します。

public class MybatisPlusConfig {
    
    
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
    
    
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());


        //分页配置
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));


        return interceptor;
    }
}

この時点で、postman を使用してインターフェイスをテストできます。

他の

ホットデプロイメントの統合

たとえば、コードを左の図から右の図に変更する場合、コンパイルして再起動する必要がありますが、これはリソースの無駄であり、時間がかかり、ホット デプロイメントが必要になります。

画像-20230511113951599

1. まず左上隅をクリックします: [ファイル] - [設定]

を見つけて构建、执行、部署コンパイラをクリックし、チェックを入れます自动构建项目

画像-20230511114143135

2. 次に、アイデアの動的自動コンパイルをオンにします (一部は自動的にオンになるため、操作は必要ありません)。

画像-20230511114411355

3. アイデアのホットデプロイ戦略を有効にする

右上隅の項目をクリック - 構成の編集

画像-20230511114527757

編集オプションをクリックします

画像-20230511114619574

执行更新操作时に変更されます更新类和资源

画像-20230511114646267

4. プラグインを pom ファイルに追加します

<plugin>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-maven-plugin</artifactId>
     <configuration>
      <fork>true</fork>
              <addResources>true</addResources>
     </configuration>
</plugin>

画像-20230511115105471

このとき、アイデアが 5 秒間フォーカスを失うと、リソースが自動的に更新され、ホット デプロイメントが完了します。

mybatis-plus ログの印刷

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启sql日志

画像-20230511135132103

クロスドメインの問題解決

方法 1: コントローラー クラスにアノテーションを追加する

@CrossOrigin("*")
画像-20230511135642302

Gradle プロジェクトではこれを使用する必要がある場合があります。

@CrossOrigin(value = "*",allowCredentials = "true")

方法 2: 解決するために新しいクロスドメイン構成アイテムを作成する

config パッケージの下に新しいCorsConfigクラスを作成します

package com.example.mini_program_yln.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration // 一定不能忽略此注解
public class CorsConfig {
    
    
    @Bean
    public CorsFilter corsFilter() {
    
    
        // 1.创建 CORS 配置对象
        CorsConfiguration config = new CorsConfiguration();
        // 支持域
        config.addAllowedOriginPattern("*");
        // 是否发送 Cookie
        config.setAllowCredentials(true);
        // 支持请求方式
        config.addAllowedMethod("*");
        // 允许的原始请求头部信息
        config.addAllowedHeader("*");
        // 暴露的头部信息
        config.addExposedHeader("*");
        // 2.添加地址映射
        UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
        corsConfigurationSource.registerCorsConfiguration("/**", config);
        // 3.返回 CorsFilter 对象
        return new CorsFilter(corsConfigurationSource);
    }
}

SpringBoot プロジェクト構成のマルチ環境

リソース ディレクトリに 2 つの新しいファイルを作成しますapplication-local.yamlapplication-dev.yaml

application.yaml

active は現在の環境を示します。local はローカル開発環境を示し、dev はオンライン環境を示します。

環境などに応じて異なる mysql アカウントのパスワードを設定できます。

spring:
  profiles:
    active: dev

application-local.yaml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mini_program?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启sql日志

application-dev.yaml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mini_program?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: 1234567
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启sql日志

SpringBoot によって返される結果は均一にカプセル化されます

バックエンドが RESTful API をフロントエンドに提供する場合、フロントエンド API 呼び出しが成功したかどうかに応答する必要があります。

  • 成功した場合、成功データは何ですか。その後、フロントエンドがデータをページにレンダリングします。
  • 失敗した場合、失敗の理由は何ですか。通常、フロントエンドはユーザーに理由をポップアップ表示します。

したがって、各インターフェイスが独自のスタイルを定義するのではなく、統一された応答が必要です。一般に、統合応答は次の情報を返します。

  • 成功した場合は、成功ステータスコードとデータを返します。
  • 失敗した場合は失敗したステータスコード+エラーメッセージを返す

新しい共通サブパッケージを作成する

画像-20230511150107275

commonサブパッケージの下にCommonResultクラスを作成する

package com.example.mini_program_yln.common;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class CommonResult<T> {
    
    
    /**
     * 错误码
     */
    private Integer code;
    /**
     * 返回数据
     */
    private T data;
    /**
     * 错误提示,用户可阅读
     */
    private String msg;


    public static <T> CommonResult<T> success(T data) {
    
    
        CommonResult<T> result = new CommonResult<>();
        result.code = 0;
        result.data = data;
        result.msg = "";
        return result;
    }


    public static <T> CommonResult<T> error(Integer code, String message) {
    
    
        CommonResult<T> result = new CommonResult<>();
        result.code = code;
        result.msg = message;
        return result;
    }

    public static <T> CommonResult<T> error() {
    
    
        CommonResult<T> result = new CommonResult<>();
        result.code = 1;
        result.msg = "系统错误,请联系管理员";
        return result;
    }

}

テストを受けてください

package com.example.mini_program_yln.controller;

import com.example.mini_program_yln.common.CommonResult;
import com.example.mini_program_yln.entity.User;
import com.example.mini_program_yln.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Description;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

//将数据以json格式返回给前端
@RestController
public class TestController {
    
    
    @Autowired
    private UserMapper userMapper;


    @Description("测试统一返回-成功")
    @GetMapping("/testResultSuccess")
    public CommonResult<List<User>> testResultSuccess() {
    
    
        return CommonResult.success(userMapper.selectList(null));
    }

    @Description("测试统一返回-失败")
    @GetMapping("/testResultError")
    public CommonResult<List<User>> testResultError() {
    
    
        return CommonResult.error(400, "失败了");
    }
}

ページングラッパー

共通パッケージの下に新しい PageParam.java クラスを作成します。

画像-20230511152152629
package com.example.mini_program_yln.common;

import lombok.Data;

import java.io.Serializable;

@Data
public class PageParam implements Serializable {
    
    

    private static final Integer PAGE_NO = 1;
    private static final Integer PAGE_SIZE = 10;

    private Integer pageNo = PAGE_NO;

    private Integer pageSize = PAGE_SIZE;

}

前のページの書き方

@GetMapping("/page")
@Description("分页列表-模糊查询")
public Page<User> page(@RequestParam(defaultValue = "") String username, @RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer size) {
    
    
    return userService.page(current, size, username);
}

現在の書き方

@PostMapping("/pageFZ")
@Description("分页列表-分页封装")
public CommonResult<Page<User>> page(@RequestBody PageParam pageInfo) {
    
    
    Page<User> page = userService.page(
            new Page<>(pageInfo.getPageNo(), pageInfo.getPageSize())
    );
    return CommonResult.success(page);
}

パラメータチェック

たとえば、上記のページング パッケージでは、pageSize には無限ではなく範囲が必要です。

pom ファイルに依存関係を導入する

画像-20230511154928859
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

次に、PageParam.java ファイルを変更します。

pageNo 最小ページ番号は 1 です

pageSize の最小値は 1、最大値は 100 です。

package com.example.mini_program_yln.common;

import lombok.Data;
import javax.validation.constraints.Min;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotNull;
import java.io.Serializable;

@Data
public class PageParam implements Serializable {

    private static final Integer PAGE_NO = 1;
    private static final Integer PAGE_SIZE = 10;

    @NotNull(message = "页码不能为空")
    @Min(value = 1, message = "页码最小值为 1")
    private Integer pageNo = PAGE_NO;

    @NotNull(message = "每页条数不能为空")
    @Min(value = 1, message = "每页条数最小值为 1")
    @Max(value = 100, message = "每页条数最大值为 100")
    private Integer pageSize = PAGE_SIZE;

}

テスト インターフェイスでは、検証できることがわかりましたが、大量のスタック情報が返されますが、これは良くなく、グローバル例外キャプチャは実行できます。

画像-20230511155102959

カスタム例外とグローバル例外キャプチャ

exceptionサブパッケージとGlobalExceptionHandler.javaクラスを作成する

画像-20230511155258021

package com.example.mini_program_yln.exception;

import com.example.mini_program_yln.common.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;

@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
    
    

    /*
     *
     * 运行时异常
     * */
    @ExceptionHandler(RuntimeException.class)
    @ResponseBody
    public CommonResult<?> ExceptionHandler() {
    
    
        return CommonResult.error();
    }


    /*
     *
     * 自定义异常
     * */
    @ExceptionHandler(CustomException.class)
    @ResponseBody
    public CommonResult<?> CustomExceptionHandler(CustomException e) {
    
    

        return CommonResult.error(400, e.getMessage());
    }

    /**
     * 处理 SpringMVC 参数校验不正确
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public CommonResult<?> methodArgumentNotValidExceptionExceptionHandler(MethodArgumentNotValidException ex) {
    
    
        FieldError fieldError = ex.getBindingResult().getFieldError();

        assert fieldError != null; // 断言,避免告警
        return CommonResult.error(400, String.format("请求参数不正确:%s:%s", fieldError.getField(), fieldError.getDefaultMessage()));
    }

    /**
     * 处理系统异常,兜底处理所有的一切
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public CommonResult<?> defaultExceptionHandler(HttpServletRequest req, Throwable ex) {
    
    
        // 返回 ERROR CommonResult
        return CommonResult.error(400, "未知异常,请联系管理员");
    }
}

このとき、ページングパラメータは誤って渡され、正常にキャプチャできます。

画像-20230511162052981

カスタム例外

例外の下に CustomException.java クラスを作成します。

package com.example.mini_program_yln.exception;

import lombok.Getter;

@Getter
public class CustomException extends RuntimeException {
    
    
    private Integer code;

    public CustomException(Integer code, String msg) {
    
    
        super(msg);
        this.code = code;
    }

    public CustomException( String msg) {
    
    
        super(msg);
        this.code = 400;
    }
}

で使用されるコード

@GetMapping("/page")
    @Description("分页列表-模糊查询")
    public Page<User> page(@RequestParam(defaultValue = "") String username, @RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer size) {
    
    
        throw new CustomException(404,"aaa");
//        return userService.page(current, size, username);
    }

画像-20230511162226132

エンティティエンティティクラスを自動生成する

utils パッケージの下に新しい SqlHelper クラスを作成します。

画像-20230511163031279

通常、使用前に packageOutPath、tablename、URL、NAME、PASS を変更する必要があります

package com.example.mini_program_yln.utils;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 从数据库表反射出实体类,自动生成实体类
 *
 * @author xxxx
 */
public class SqlHelper {
    
    
    //基本数据配置
    private String packageOutPath = "com.example.mini_program_yln.entity";// 指定实体生成所在包的路径,要修改
    private String authorName = "xxxx";// 作者名字
    private String tablename = "news";// 表名,要修改
    private String[] colnames; // 列名数组
    private String[] colTypes; // 列名类型数组
    private String version = "V0.01"; // 版本
    private int[] colSizes; // 列名大小数组
    private boolean f_util = false; // 是否需要导入包java.util.*
    private boolean f_sql = false; // 是否需要导入包java.sql.*
    private boolean f_lang = false; // 是否需要导入包java.sql.*
    private String defaultPath = "/src/main/java/";
    // 数据库连接
    private static final String URL = "jdbc:mysql://localhost:3306/mini_program?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC";//要修改
    private static final String NAME = "root";//要修改
    private static final String PASS = "123456";//要修改
    private static final String DRIVER = "com.mysql.jdbc.Driver";

    /*
     * 构造函数
     */
    public SqlHelper() {
    
    
        // 创建连接
        Connection con;
        // 查要生成实体类的表
        String sql = "select * from " + tablename;
        PreparedStatement pStemt = null;
        try {
    
    
            try {
    
    
                Class.forName(DRIVER);
            } catch (ClassNotFoundException e1) {
    
    
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            con = DriverManager.getConnection(URL, NAME, PASS);
            pStemt = con.prepareStatement(sql);
            ResultSetMetaData rsmd = pStemt.getMetaData();
            int size = rsmd.getColumnCount(); // 统计列
            colnames = new String[size];
            colTypes = new String[size];
            colSizes = new int[size];
            for (int i = 0; i < size; i++) {
    
    

                colnames[i] = rsmd.getColumnName(i + 1);
                colTypes[i] = rsmd.getColumnTypeName(i + 1);
                //自动生成包配置


                // if (colTypes[i].equalsIgnoreCase("datetime")) {
    
    
                // f_util = true;
                // }
                if (colTypes[i].equalsIgnoreCase("image") || colTypes[i].equalsIgnoreCase("text")
                        || colTypes[i].equalsIgnoreCase("datetime") || colTypes[i].equalsIgnoreCase("time")
                        || colTypes[i].equalsIgnoreCase("date") || colTypes[i].equalsIgnoreCase("datetime2")) {
    
    
                    f_sql = true;
                }
                // if (colTypes[i].equalsIgnoreCase("int")) {
    
    
                // f_lang = true;
                // }
                colSizes[i] = rsmd.getColumnDisplaySize(i + 1);
            }

            String content = parse(colnames, colTypes, colSizes);

            try {
    
    
                File directory = new File("");

                String path = this.getClass().getResource("").getPath();

                System.out.println(path);

                String outputPath = directory.getAbsolutePath() + this.defaultPath
                        + this.packageOutPath.replace(".", "/") + "/" + initcap(underlineToHump(tablename)) + ".java";
                System.out.println("执行完毕,生成路径为:" + outputPath);
                FileWriter fw = new FileWriter(outputPath);
                PrintWriter pw = new PrintWriter(fw);
                pw.println(content);
                pw.flush();
                pw.close();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }

        } catch (SQLException e) {
    
    
            e.printStackTrace();
        } finally {
    
    

        }
    }

    /**
     * 功能:生成实体类主体代码
     *
     * @param colnames
     * @param colTypes
     * @param colSizes
     * @return
     */
    private String parse(String[] colnames, String[] colTypes, int[] colSizes) {
    
    
        StringBuffer sb = new StringBuffer();
        // 生成package包路径
        sb.append("package " + this.packageOutPath + ";\r\n");
        // 判断是否导入工具包
        if (f_util) {
    
    
            sb.append("import java.util.Date;\r\n");
        }
        if (f_sql) {
    
    
            sb.append("import java.sql.*;\r\n");
        }
        if (f_lang) {
    
    
            sb.append("import java.lang.*;\r\n");
        }
        sb.append("import lombok.Data;\r\n");

        sb.append("\r\n");
        // 注释部分
        sb.append("   /**\r\n");
        sb.append("    * @文件名称:" + initcap(underlineToHump(this.tablename)) + ".java\r\n");
        sb.append("    * @创建时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "\r\n");
        sb.append("    * @创  建  人:" + this.authorName + " \r\n");
        sb.append("    * @文件描述:" + tablename + " 实体类\r\n");
        sb.append("    * @文件版本:" + this.version + " \r\n");
        sb.append("    */ \r\n");
        sb.append("\n\r\n@Data");
        // 实体部分
        sb.append("\npublic class " + initcap(underlineToHump(tablename)) + "{\r\n");
        processAllAttrs(sb);// 属性
//        processAllMethod(sb);// get set方法
        sb.append("}\r\n");

        // System.out.println(sb.toString());
        return sb.toString();
    }

    /**
     * 功能:生成所有属性
     *
     * @param sb
     */
    private void processAllAttrs(StringBuffer sb) {
    
    

        for (int i = 0; i < colnames.length; i++) {
    
    
            sb.append("\tprivate " + sqlType2JavaType(colTypes[i]) + " " + this.underlineToHump(colnames[i]) + ";\r\n");
        }

    }

    /**
     * 功能:生成所有方法
     *
     * @param sb
     */
//    private void processAllMethod(StringBuffer sb) {
    
    
//
//        for (int i = 0; i < colnames.length; i++) {
    
    
//            sb.append("\tpublic void set" + initcap(colnames[i]) + "(" + sqlType2JavaType(colTypes[i]) + " "
//                    + colnames[i] + "){\r\n");
//            sb.append("\tthis." + colnames[i] + "=" + colnames[i] + ";\r\n");
//            sb.append("\t}\r\n");
//            sb.append("\tpublic " + sqlType2JavaType(colTypes[i]) + " get" + initcap(colnames[i]) + "(){\r\n");
//            sb.append("\t\treturn " + colnames[i] + ";\r\n");
//            sb.append("\t}\r\n");
//        }
//
//    }

    /**
     * 功能:将输入字符串的首字母改成大写
     *
     * @param str
     * @return
     */
    private String initcap(String str) {
    
    

        char[] ch = str.toCharArray();
        if (ch[0] >= 'a' && ch[0] <= 'z') {
    
    
            ch[0] = (char) (ch[0] - 32);
        }

        return new String(ch);
    }

    /**
     * 功能:获得列的数据类型
     *
     * @param sqlType
     * @return
     */
    private String sqlType2JavaType(String sqlType) {
    
    

        if (sqlType.equalsIgnoreCase("bit")) {
    
    
            return "Boolean";
        } else if (sqlType.equalsIgnoreCase("decimal") || sqlType.equalsIgnoreCase("money")
                || sqlType.equalsIgnoreCase("smallmoney") || sqlType.equalsIgnoreCase("numeric")
                || sqlType.equalsIgnoreCase("bigint")) {
    
    
            return "Long";
        } else if (sqlType.equalsIgnoreCase("float")) {
    
    
            return "Double";
        } else if (sqlType.equalsIgnoreCase("int") || sqlType.equalsIgnoreCase("int identity")) {
    
    
            return "Integer";
        } else if (sqlType.equalsIgnoreCase("image") || sqlType.equalsIgnoreCase("varbinary(max)")
                || sqlType.equalsIgnoreCase("varbinary") || sqlType.equalsIgnoreCase("udt")
                || sqlType.equalsIgnoreCase("binary")) {
    
    
            return "Byte[]";
        } else if (sqlType.equalsIgnoreCase("nchar") || sqlType.equalsIgnoreCase("nvarchar(max)")
                || sqlType.equalsIgnoreCase("nvarchar") || sqlType.equalsIgnoreCase("nvarchar(ntext)")
                || sqlType.equalsIgnoreCase("uniqueidentifier") || sqlType.equalsIgnoreCase("xml")
                || sqlType.equalsIgnoreCase("char") || sqlType.equalsIgnoreCase("varchar(max)")
                || sqlType.equalsIgnoreCase("text") || sqlType.equalsIgnoreCase("varchar")) {
    
    
            return "String";
        } else if (sqlType.equalsIgnoreCase("real")) {
    
    
            return "Float";
        } else if (sqlType.equalsIgnoreCase("smallint") || sqlType.equalsIgnoreCase("tinyint")) {
    
    
            return "Short";
        } else if (sqlType.equalsIgnoreCase("date") || sqlType.equalsIgnoreCase("datetime")
                || sqlType.equalsIgnoreCase("time") || sqlType.equalsIgnoreCase("datetime2")
                || sqlType.equalsIgnoreCase("timestamp")) {
    
    
            return "Date";
        } else {
    
    
            System.out.println("数据类型异常,类型为:" + sqlType);
        }

        return null;
    }

    /**
     * 下划线转驼峰
     *
     * @String para
     */
    private String underlineToHump(String para) {
    
    
        StringBuilder result = new StringBuilder();
        String a[] = para.split("_");
        for (String s : a) {
    
    
            if (result.length() == 0) {
    
    
                result.append(s.toLowerCase());
            } else {
    
    
                result.append(s.substring(0, 1).toUpperCase());
                result.append(s.substring(1).toLowerCase());
            }
        }
        return result.toString();
    }


    /**
     * 出口 TODO
     *
     * @param args
     */
    public static void main(String[] args) {
    
    

        new SqlHelper();

    }
}


おすすめ

転載: blog.csdn.net/dzdzdzd12347/article/details/130879045