@[toc]
1、项目连接数据库
Springboot项目引入Mysql以及MyBatisPlus等服务。
1.1、引入依赖信息
首先在父类中引入相关依赖,并规定依赖版本信息
<!-- 版本控制 -->
<properties>
<!--===================== 数据库相关依赖版本 =========================-->
<mysql.version>8.0.29</mysql.version>
<mybatis-plus.version>3.4.2</mybatis-plus.version>
</properties>
<!-- 依赖管理 -->
<dependencyManagement>
<dependencies>
<!--===================== 数据库相关依赖 =========================-->
<!-- mysql8 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- MybatisPlus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
在common模块中引入对应依赖
<!--===================== 数据库相关依赖 =========================-->
<!-- mysql8 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- MybatisPlus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
1.2、编写配置文件
server:
port: 9000
spring:
application:
name: 木字楠博客后台服务
# Database Configuration
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://[ip]:[port]/blog?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
username: [用户名]
password: [密码]
# MybatisPlus Configuration
mybatis-plus:
mapper-locations: classpath*:/mapper/*.xml
global-config:
db-config:
logic-delete-field: isDeleted
logic-delete-value: 1
logic-not-delete-value: 0
1.3、新增数据库配置类
/**
* @author 木字楠
* @version 1.0
* @description MyBatisPlus配置文件
* @date 2022/8/11
*/
@Configuration
@MapperScan("space.muzinan.mapper.**")
public class MybatisPlusConfig {
/**
* MyBatisPlus 分页插件
* @return PaginationInterceptor
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
1.4、代码生成器编写
public class MpGenerator {
/**
* <p>
* MySQL 生成演示
* </p>
*/
public static void main(String[] args) {
//1. 全局配置
GlobalConfig config = new GlobalConfig();
//是否支持AR模式
config.setActiveRecord(true)
.setAuthor("MuZiNan") //作者
.setOutputDir("D:\\project\\MuZiNan\\MuZiNan-Server\\src\\main\\java") //生成路径
.setFileOverride(true)//是否文件覆盖,如果多次
.setServiceName("%sService") //设置生成的service接口名首字母是否为I
.setIdType(IdType.AUTO) //主键策略
.setBaseResultMap(true)
.setBaseColumnList(true)
.setDateType(DateType.ONLY_DATE)
.setSwagger2(true);
//2. 数据源配置
DataSourceConfig dsConfig = new DataSourceConfig();
dsConfig.setDbType(DbType.MYSQL)
.setUrl("jdbc:mysql://[ip]:[port]/blog?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true")
.setDriverName("com.mysql.cj.jdbc.Driver")
.setUsername("[用户名]")
.setPassword("[密码]");
//3.策略配置
StrategyConfig stConfig = new StrategyConfig();
stConfig.setCapitalMode(true) // 全局大写命名
.setNaming(NamingStrategy.underline_to_camel)// 数据库表映射到实体的命名策略
.setColumnNaming(NamingStrategy.underline_to_camel)
.setInclude("article_view") //生成的表
.setTablePrefix("")
.setControllerMappingHyphenStyle(true)
.setEntityLombokModel(true)
.setRestControllerStyle(true); // 表前缀
//4.包名策略
PackageConfig pkConfig = new PackageConfig();
pkConfig.setParent("space.muzinan")//父包名
.setController("controller")
.setEntity("entity")
.setService("service")
.setMapper("mapper")
.setServiceImpl("service.impl");
//5.整合配置
AutoGenerator ag = new AutoGenerator().setGlobalConfig(config)
.setDataSource(dsConfig)
.setStrategy(stConfig)
.setPackageInfo(pkConfig);
ag.execute();
}
}
2、通用枚举类编写
/**
* @author 木字楠
* @version 1.0
* @date 2022/8/11
*/
@Getter
@AllArgsConstructor
public enum HttpCodeEnum {
/**
* 登陆超时
*/
USER_LOGIN_TIME_OUT(100, "登陆超时"),
/**
* 用户未登录
*/
USER_NOT_LOGIN(101, "用户未登录"),
/**
* 账户被禁用,请联系管理员解决
*/
ACCOUNT_IS_DISABLED(102, "账户被禁用,请联系管理员解决"),
/**
* 参数格式不合法
*/
PARAMETER_VALID_ERROR(103, "参数格式不合法"),
/**
* 用户名不能为空
*/
USERNAME_CAN_NOT_BE_EMPTY(104, "用户名不能为空"),
/**
* 用户名或密码错误
*/
USERNAME_OR_PASSWORD_ERROR(104, "用户名或密码错误"),
/**
* 验证码错误
*/
CAPTCHA_ERROR(105, "验证码错误"),
/**
* 验证码过期
*/
CAPTCHA_ALREADY_EXPIRE(106, "验证码已过期"),
/**
* 用户名已存在
*/
USERNAME_ALREADY_EXISTED(107, "用户名已存在"),
/**
* 用户登录成功
*/
USER_LOGIN_SUCCESS(108, "用户登录成功"),
/**
* 用户注销成功
*/
USER_LOGOUT_SUCCESS(109, "用户注销成功"),
/**
* 操作成功
*/
OPERATOR_IS_SUCCESS(200, "操作成功"),
/**
* 没有权限
*/
PERMISSION_NOT_DEFINED(403, "您没有操作权限"),
/**
* 操作失败
*/
OPERATOR_IS_FAILED(500, "操作失败");
/**
* 状态码
*/
private int code;
/**
* 返回信息
*/
private String message;
}
/**
* @author 木字楠
* @version 1.0
* @description 请求类型枚举
* @date 2022/8/11
*/
@Getter
@AllArgsConstructor
public enum RequestTypeEnum {
/**
* Get请求
*/
GET_REQUEST_FIRST_UPPER_CASE("Get"),
/**
* Post请求
*/
POST_REQUEST_FIRST_UPPER_CASE("Post"),
/**
* Put请求
*/
PUT_REQUEST_FIRST_UPPER_CASE("Put"),
/**
* Delete请求
*/
DELETE_REQUEST_FIRST_UPPER_CASE("Delete"),
/**
* GET请求
*/
GET_REQUEST_ALL_UPPER_CASE("GET"),
/**
* POST请求
*/
POST_REQUEST_ALL_UPPER_CASE("POST"),
/**
* PUT请求
*/
PUT_REQUEST_ALL_UPPER_CASE("PUT"),
/**
* DELETE请求
*/
DELETE_REQUEST_ALL_UPPER_CASE("DELETE"),
/**
* get请求
*/
GET_REQUEST_ALL_LOWER_CASE("get"),
/**
* post请求
*/
POST_REQUEST_ALL_LOWER_CASE("post"),
/**
* put请求
*/
PUT_REQUEST_ALL_LOWER_CASE("put"),
/**
* delete请求
*/
DELETE_REQUEST_ALL_LOWER_CASE("delete");
/**
* 请求类型
*/
private final String REQUEST_TYPE;
}
3、统一结果集处理器
/**
* @author 木字楠
* @version 1.0
* @description 统一结果集处理器
* @date 2022/8/11
*/
@Data
public class ResponseResult<T> {
/**
* 状态码
*/
private Integer code;
/**
* 是否请求成功
*/
private Boolean success;
/**
* 响应消息
*/
private String message;
/**
* 响应数据
*/
private T data;
/**
* 私有构造
*
* @param success 请求状态
* @param code 状态码
* @param message 状态信息
* @param data 数据
* @param <T> 泛型数据
* @return 结果集处理器
*/
private static <T> ResponseResult<T> response(Boolean success, Integer code, String message, T data) {
ResponseResult<T> result = new ResponseResult<>();
result.setSuccess(success);
result.setCode(code);
result.setMessage(message);
result.setData(data);
return result;
}
/**
* 请求成功返回(一)
*
* @param code 状态码
* @param message 状态信息
* @param data 数据
* @param <T> 泛型数据
* @return 结果集处理器
*/
public static <T> ResponseResult<T> success(Integer code, String message, T data) {
return response(true, code, message, data);
}
/**
* 请求成功返回(二)
*
* @param message 状态信息
* @param data 数据
* @param <T> 泛型数据
* @return 结果集处理器
*/
public static <T> ResponseResult<T> success(String message, T data) {
return response(true, HttpCodeEnum.OPERATOR_IS_SUCCESS.getCode(), message, data);
}
/**
* 请求成功返回(三)
*
* @param message 状态信息
* @param <T> 泛型数据
* @return 结果集处理器
*/
public static <T> ResponseResult<T> success(String message) {
return response(true, HttpCodeEnum.OPERATOR_IS_SUCCESS.getCode(), message, null);
}
/**
* 请求成功返回(四)
*
* @param httpCodeEnum 状态枚举
* @param <T> 泛型数据
* @return 结果集处理器
*/
public static <T> ResponseResult<T> success(HttpCodeEnum httpCodeEnum) {
return response(true, httpCodeEnum.getCode(), httpCodeEnum.getMessage(), null);
}
/**
* 请求成功返回(五)
*
* @param httpCodeEnum 状态枚举
* @param data 数据
* @param <T> 泛型数据
* @return 结果集处理器
*/
public static <T> ResponseResult<T> success(HttpCodeEnum httpCodeEnum, T data) {
return response(true, httpCodeEnum.getCode(), httpCodeEnum.getMessage(), data);
}
/**
* 请求成功返回(六)
* @param data 数据
* @return 结果集处理器
* @param <T> 泛型数据
*/
public static <T> ResponseResult<T> success( T data) {
return response(true, HttpCodeEnum.OPERATOR_IS_SUCCESS.getCode(),HttpCodeEnum.OPERATOR_IS_SUCCESS.getMessage(), data);
}
/**
* 请求失败返回(一)
*
* @param code 状态码
* @param message 状态信息
* @param data 数据
* @param <T> 泛型数据
* @return 结果集处理器
*/
public static <T> ResponseResult<T> fail(Integer code, String message, T data) {
return response(false, code, message, data);
}
/**
* 请求失败返回(二)
*
* @param message 状态信息
* @param data 数据
* @param <T> 泛型数据
* @return 结果集处理器
*/
public static <T> ResponseResult<T> fail(String message, T data) {
return response(false, HttpCodeEnum.OPERATOR_IS_FAILED.getCode(), message, data);
}
/**
* 请求失败返回(三)
*
* @param message 状态信息
* @param <T> 泛型数据
* @return 结果集处理器
*/
public static <T> ResponseResult<T> fail(String message) {
return response(false, HttpCodeEnum.OPERATOR_IS_FAILED.getCode(), message, null);
}
/**
* 请求失败返回(四)
*
* @param httpCodeEnum 状态枚举
* @param <T> 泛型数据
* @return 结果集处理器
*/
public static <T> ResponseResult<T> fail(HttpCodeEnum httpCodeEnum) {
return response(false, httpCodeEnum.getCode(), httpCodeEnum.getMessage(), null);
}
}
/**
* @author 木字楠
* @version 1.0
* @description 分页结果集
* @date 2022/8/11
*/
@Data
@AllArgsConstructor
public class PageResult<T> {
/**
* 总数据量
*/
private long totalCount;
/**
* 数据列表
*/
private List<T> dataList;
}
4、其他工具类
4.1、Bean拷贝工具类
/**
* @description 复制对象或集合属性
* @author 木字楠
* @date 2022/8/11
* @version 1.0
*/
public class BeanCopyUtils {
/**
* 复制对象
*
* @param source 源
* @param target 目标
* @return {@link T}
*/
public static <T> T copyObject(Object source, Class<T> target) {
T temp = null;
try {
temp = target.newInstance();
if (null != source) {
BeanUtils.copyProperties(source, temp);
}
} catch (Exception e) {
e.printStackTrace();
}
return temp;
}
/**
* 拷贝集合
*
* @param source 源
* @param target 目标
* @return {@link List<T>} 集合
*/
public static <T, S> List<T> copyList(List<S> source, Class<T> target) {
List<T> list = new ArrayList<>();
if (null != source && source.size() > 0) {
for (Object obj : source) {
list.add(BeanCopyUtils.copyObject(obj, target));
}
}
return list;
}
}
4.2、Ip查询工具类
/**
* ip工具类
*
* @author 11921
*/
@SuppressWarnings("all")
public class IpUtils {
/**
* 获取用户ip地址
*
* @param request 请求
* @return ip地址
*/
public static String getIpAddress(HttpServletRequest request) {
String ipAddress = null;
try {
ipAddress = request.getHeader("x-forwarded-for");
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("WL-Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getRemoteAddr();
if ("127.0.0.1".equals(ipAddress)) {
// 根据网卡取本机配置的IP
InetAddress inet = null;
try {
inet = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
ipAddress = inet.getHostAddress();
}
}
// 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
if (ipAddress != null && ipAddress.length() > 15) {
// = 15
if (ipAddress.indexOf(",") > 0) {
ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
}
}
} catch (Exception e) {
ipAddress = "";
}
return ipAddress;
}
/**
* 解析ip地址
*
* @param ipAddress ip地址
* @return 解析后的ip地址
*/
public static String getIpSource(String ipAddress) {
try {
URL url = new URL("http://opendata.baidu.com/api.php?query=" + ipAddress + "&co=&resource_id=6006&oe=utf8");
BufferedReader reader = new BufferedReader(new InputStreamReader(url.openConnection().getInputStream(), "utf-8"));
String line = null;
StringBuffer result = new StringBuffer();
while ((line = reader.readLine()) != null) {
result.append(line);
}
reader.close();
Map map = JSON.parseObject(result.toString(), Map.class);
List<Map<String, String>> data = (List) map.get("data");
return data.get(0).get("location");
} catch (Exception e) {
return "";
}
}
/**
* 获取访问设备
*
* @param request 请求
* @return {@link UserAgent} 访问设备
*/
public static UserAgent getUserAgent(HttpServletRequest request){
return UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
}
}
5、统一异常处理
5.1、自定义异常处理
/**
* @author 木字楠
* @description 基础异常处理类
* @version 1.0
*/
@Getter
public class BaseException extends RuntimeException {
/**
* 所属模块
*/
private final String moudle;
/**
* 状态码
*/
private final Integer code;
/**
* 报错信息
*/
private final String message;
/**
* 全参构造方法
*
* @param moudle 所属模块
* @param code 状态码
* @param message 报错信息
*/
public BaseException(String moudle, Integer code, String message) {
this.moudle = moudle;
this.code = code;
this.message = message;
}
}
5.2、全局异常处理
/**
* @author 木字楠
* @version 1.0
* @description 全局异常处理
* @date 2022/6/29
*/
@Slf4j
@RestControllerAdvice
public class GlobalException {
/**
* 全局异常处理
*
* @param e 异常信息
* @return 错误信息
*/
@ExceptionHandler(Exception.class)
public ResponseResult<?> globalException(Exception e) {
log.error("异常信息 => {}", e.getMessage());
return ResponseResult.fail(HttpCodeEnum.OPERATOR_IS_FAILED.getMessage());
}
/**
* 基础异常处理
*
* @param baseException 基础异常信息类
* @return 错误结果
*/
@ExceptionHandler(BaseException.class)
public ResponseResult<?> baseException(BaseException baseException) {
log.error("{}:异常信息 => {}", null == baseException.getMoudle() ? "未知" : baseException.getMoudle(), baseException.getMessage());
return ResponseResult.fail(baseException.getMessage());
}
}