upd: 编码规范
This commit is contained in:
+1
-1
@@ -1,4 +1,4 @@
|
||||
<h1 style="text-align: center">ELADMIN 后台管理系统</h1>
|
||||
<h1 style="text-align: center">CuteJava 后台管理系统</h1>
|
||||
|
||||
#### 项目简介
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.annotation.rest;
|
||||
package cn.odboy.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.annotation.rest;
|
||||
package cn.odboy.annotation;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.annotation.rest;
|
||||
package cn.odboy.annotation;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.annotation.rest;
|
||||
package cn.odboy.annotation;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.annotation.rest;
|
||||
package cn.odboy.annotation;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.annotation.rest;
|
||||
package cn.odboy.annotation;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
+5
-1
@@ -18,7 +18,7 @@ import java.sql.Timestamp;
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class BaseEntity extends MyObject {
|
||||
public class MyEntity extends MyObject {
|
||||
|
||||
@CreatedBy
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
@@ -33,11 +33,15 @@ public class BaseEntity extends MyObject {
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
@ApiModelProperty(value = "创建时间: yyyy-MM-dd HH:mm:ss", hidden = true)
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
// @JSONField(format = "yyyy-MM-dd HH:mm:ss")
|
||||
// @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Timestamp createTime;
|
||||
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
@ApiModelProperty(value = "更新时间: yyyy-MM-dd HH:mm:ss", hidden = true)
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
// @JSONField(format = "yyyy-MM-dd HH:mm:ss")
|
||||
// @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Timestamp updateTime;
|
||||
|
||||
/* 分组校验 */
|
||||
@@ -0,0 +1,72 @@
|
||||
package cn.odboy.base;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.springframework.data.annotation.CreatedBy;
|
||||
import org.springframework.data.annotation.LastModifiedBy;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
/**
|
||||
* 逻辑删除通用模型
|
||||
*
|
||||
* @author odboy
|
||||
* @date 2025-01-12
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class MyLogicEntity extends MyObject {
|
||||
@CreatedBy
|
||||
@TableField(value = "create_by", fill = FieldFill.INSERT)
|
||||
@ApiModelProperty(value = "创建人", hidden = true)
|
||||
private String createBy;
|
||||
@LastModifiedBy
|
||||
@TableField(value = "update_by", fill = FieldFill.INSERT_UPDATE)
|
||||
@ApiModelProperty(value = "更新人", hidden = true)
|
||||
private String updateBy;
|
||||
@TableField(value = "create_time", fill = FieldFill.INSERT)
|
||||
@ApiModelProperty(value = "创建时间", hidden = true)
|
||||
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Timestamp createTime;
|
||||
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
|
||||
@ApiModelProperty(value = "更新时间", hidden = true)
|
||||
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Timestamp updateTime;
|
||||
@ApiModelProperty(value = "数据有效性", hidden = true)
|
||||
@TableLogic
|
||||
@TableField("available")
|
||||
private Integer available;
|
||||
|
||||
/* 分组校验 */
|
||||
public @interface Create {
|
||||
}
|
||||
|
||||
/* 分组校验 */
|
||||
public @interface Update {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
ToStringBuilder builder = new ToStringBuilder(this);
|
||||
Field[] fields = this.getClass().getDeclaredFields();
|
||||
try {
|
||||
for (Field f : fields) {
|
||||
f.setAccessible(true);
|
||||
builder.append(f.getName(), f.get(this)).append("\n");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
builder.append("toString builder encounter an error");
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2021-2025 Tian Jun
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.odboy.base;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 元数据选项
|
||||
*
|
||||
* @author odboy
|
||||
* @date 2025-01-13
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class MyMetaOption extends MyObject {
|
||||
private String label;
|
||||
private String value;
|
||||
private Map<String, Object> ext;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package cn.odboy.base;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 数据分页参数
|
||||
*
|
||||
* @author odboy
|
||||
* @date 2025-01-20
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PageArgs<T> implements Serializable {
|
||||
@NotNull(message = "参数page不能为空")
|
||||
@Min(value = 1, message = "参数page最小值为1")
|
||||
@ApiModelProperty(value = "页码", example = "1")
|
||||
private Integer page;
|
||||
@NotNull(message = "参数size不能为空")
|
||||
@Min(value = 1, message = "参数size最小值为1")
|
||||
@ApiModelProperty(value = "每页数据量", example = "10")
|
||||
private Integer size;
|
||||
private T args;
|
||||
}
|
||||
+1
-4
@@ -1,6 +1,5 @@
|
||||
package cn.odboy.util;
|
||||
package cn.odboy.base;
|
||||
|
||||
import cn.odboy.base.MyObject;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -16,8 +15,6 @@ import java.util.List;
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class PageResult<T> extends MyObject {
|
||||
|
||||
private List<T> content;
|
||||
|
||||
private long totalElements;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package cn.odboy.config.webConfig;
|
||||
|
||||
import org.apache.catalina.connector.Connector;
|
||||
import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* 允许在查询字符串中使用特定的特殊字符
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class QueryCustomizer implements TomcatConnectorCustomizer {
|
||||
|
||||
@Override
|
||||
public void customize(Connector connector) {
|
||||
connector.setProperty("relaxedQueryChars", "[]{}");
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.config;
|
||||
package cn.odboy.context;
|
||||
|
||||
import cn.odboy.util.SecurityUtil;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2021-2025 Tian Jun
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.odboy.context;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Bean加载完毕 监听
|
||||
*
|
||||
* @author odboy
|
||||
* @date 2025-01-16
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class BeanLoadFinishListener implements ApplicationListener<ContextRefreshedEvent> {
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
log.info("所有的Bean都加载完毕了");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2021-2025 Tian Jun
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.odboy.context;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
/**
|
||||
* 主要目的是输出应用的服务地址
|
||||
*
|
||||
* @author odboy
|
||||
* @date 2024-04-20
|
||||
*/
|
||||
@Slf4j
|
||||
public class BootApplication {
|
||||
@Bean
|
||||
public SpringBeanHolder springContextHolder() {
|
||||
return new SpringBeanHolder();
|
||||
}
|
||||
|
||||
protected static void inited(ConfigurableApplicationContext application) throws UnknownHostException {
|
||||
Environment env = application.getEnvironment();
|
||||
String ip = InetAddress.getLocalHost().getHostAddress();
|
||||
String port = env.getProperty("server.port");
|
||||
String path = StrUtil.isEmpty(env.getProperty("config.servlet.context-path")) ? "" : env.getProperty("config.servlet.context-path");
|
||||
log.info(
|
||||
"\n----------------------------------------------------------\n\t"
|
||||
+ "Application is running! Access URLs:\n\t"
|
||||
+ "Local: \t\thttp://localhost:" + port + path + "/\n\t"
|
||||
+ "External: \thttp://" + ip + ":" + port + path + "/\n\t"
|
||||
+ "Swagger文档: \thttp://" + ip + ":" + port + path + "/doc.html\n"
|
||||
+ "----------------------------------------------------------");
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.util;
|
||||
package cn.odboy.context;
|
||||
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.util;
|
||||
package cn.odboy.context;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeansException;
|
||||
+1
-1
@@ -3,7 +3,7 @@ package cn.odboy.exception.handler;
|
||||
import cn.odboy.exception.BadRequestException;
|
||||
import cn.odboy.exception.EntityExistException;
|
||||
import cn.odboy.exception.EntityNotFoundException;
|
||||
import cn.odboy.util.ThrowableUtil;
|
||||
import cn.odboy.exception.util.ThrowableUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2021-2025 Tian Jun
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.odboy.exception.util;
|
||||
|
||||
/**
|
||||
* 适配 logger 占位符
|
||||
*
|
||||
* @author odboy
|
||||
* @date 2025-01-13
|
||||
*/
|
||||
public class LogFmtUtil {
|
||||
/**
|
||||
* 替换字符串中的占位符 {} 为传入的参数
|
||||
*
|
||||
* @param message 消息模板
|
||||
* @param args 替换占位符的参数
|
||||
* @return 替换后的消息
|
||||
*/
|
||||
public static String format(String message, Object... args) {
|
||||
if (message == null || args == null || args.length == 0) {
|
||||
return message;
|
||||
}
|
||||
// 使用 String.format 替换占位符
|
||||
return String.format(message.replace("{}", "%s"), args);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// 示例用法
|
||||
String messageTemplate = "获取dingtalk accessToken失败, code={}, message={}";
|
||||
String formattedMessage = format(messageTemplate, 400, "Bad Request");
|
||||
// 输出: 获取dingtalk accessToken失败, code=400, message=Bad Request
|
||||
System.out.println(formattedMessage);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.util;
|
||||
package cn.odboy.exception.util;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2021-2025 Tian Jun
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.odboy.monitor;
|
||||
|
||||
import cn.odboy.annotation.AnonymousGetMapping;
|
||||
import io.swagger.annotations.Api;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 健康检查接口
|
||||
*
|
||||
* @author odboy
|
||||
* @date 2022-01-06
|
||||
*/
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/health")
|
||||
@Api(tags = "系统:健康检查接口")
|
||||
public class HealthCheckController {
|
||||
/**
|
||||
* 健康检查
|
||||
*/
|
||||
@AnonymousGetMapping(value = "/check")
|
||||
public ResponseEntity<?> doCheck() {
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 访问首页提示
|
||||
*/
|
||||
@AnonymousGetMapping("/")
|
||||
public String index() {
|
||||
return "success";
|
||||
}
|
||||
}
|
||||
+20
-7
@@ -1,7 +1,10 @@
|
||||
package cn.odboy.config.mybatis;
|
||||
package cn.odboy.mybatis.config;
|
||||
|
||||
import cn.odboy.mybatis.context.InsertBatchSqlInjector;
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -10,18 +13,28 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
public class MybatisPlusConfig {
|
||||
/**
|
||||
* MyBatisPlus拦截器(用于分页)
|
||||
*/
|
||||
@Bean
|
||||
public MybatisPlusInterceptor paginationInterceptor() {
|
||||
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
||||
// 添加MySQL的分页拦截器
|
||||
// MySQL的分页拦截器
|
||||
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
|
||||
paginationInnerInterceptor.setOptimizeJoin(true);
|
||||
paginationInnerInterceptor.setMaxLimit(500L);
|
||||
paginationInnerInterceptor.setOverflow(false);
|
||||
/// 这个配置会导致:当分页没数据时,游标从0开始,会导致无论page为什么值,就算分页超出最大页数,依然能够查询到
|
||||
/// paginationInnerInterceptor.setOverflow(true);
|
||||
paginationInnerInterceptor.setOptimizeJoin(true);
|
||||
interceptor.addInnerInterceptor(paginationInnerInterceptor);
|
||||
// 乐观锁
|
||||
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
|
||||
// 防全表更新与删除
|
||||
interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
|
||||
return interceptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mapper支持批量插入
|
||||
*/
|
||||
@Bean
|
||||
public InsertBatchSqlInjector insertBatchSqlInjector() {
|
||||
return new InsertBatchSqlInjector();
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.config;
|
||||
package cn.odboy.mybatis.config;
|
||||
|
||||
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
|
||||
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* <<
|
||||
* Davinci
|
||||
* ==
|
||||
* Copyright (C) 2016 - 2019 EDP
|
||||
* ==
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* >>
|
||||
*
|
||||
*/
|
||||
package cn.odboy.mybatis.constant;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author /
|
||||
*/
|
||||
@Slf4j
|
||||
@SuppressWarnings({"unchecked", "all"})
|
||||
public enum DataTypeEnum {
|
||||
/**
|
||||
* mysql
|
||||
*/
|
||||
MYSQL("mysql", "mysql", "com.mysql.jdbc.Driver", "`", "`", "'", "'"),
|
||||
/**
|
||||
* oracle
|
||||
*/
|
||||
ORACLE("oracle", "oracle", "oracle.jdbc.driver.OracleDriver", "\"", "\"", "\"", "\""),
|
||||
/**
|
||||
* sql config
|
||||
*/
|
||||
SQLSERVER("sqlserver", "sqlserver", "com.microsoft.sqlserver.jdbc.SQLServerDriver", "\"", "\"", "\"", "\""),
|
||||
/**
|
||||
* h2
|
||||
*/
|
||||
H2("h2", "h2", "org.h2.Driver", "`", "`", "\"", "\""),
|
||||
/**
|
||||
* phoenix
|
||||
*/
|
||||
PHOENIX("phoenix", "hbase phoenix", "org.apache.phoenix.jdbc.PhoenixDriver", "", "", "\"", "\""),
|
||||
/**
|
||||
* mongo
|
||||
*/
|
||||
MONGODB("mongo", "mongodb", "mongodb.jdbc.MongoDriver", "`", "`", "\"", "\""),
|
||||
/**
|
||||
* sql4es
|
||||
*/
|
||||
ELASTICSEARCH("sql4es", "elasticsearch", "nl.anchormen.sql4es.jdbc.ESDriver", "", "", "'", "'"),
|
||||
/**
|
||||
* presto
|
||||
*/
|
||||
PRESTO("presto", "presto", "com.facebook.presto.jdbc.PrestoDriver", "", "", "\"", "\""),
|
||||
/**
|
||||
* moonbox
|
||||
*/
|
||||
MOONBOX("moonbox", "moonbox", "moonbox.jdbc.MbDriver", "`", "`", "`", "`"),
|
||||
/**
|
||||
* cassandra
|
||||
*/
|
||||
CASSANDRA("cassandra", "cassandra", "com.github.adejanovski.cassandra.jdbc.CassandraDriver", "", "", "'", "'"),
|
||||
/**
|
||||
* click house
|
||||
*/
|
||||
CLICKHOUSE("clickhouse", "clickhouse", "ru.yandex.clickhouse.ClickHouseDriver", "", "", "\"", "\""),
|
||||
/**
|
||||
* kylin
|
||||
*/
|
||||
KYLIN("kylin", "kylin", "org.apache.kylin.jdbc.Driver", "\"", "\"", "\"", "\""),
|
||||
/**
|
||||
* vertica
|
||||
*/
|
||||
VERTICA("vertica", "vertica", "com.vertica.jdbc.Driver", "", "", "'", "'"),
|
||||
/**
|
||||
* sap
|
||||
*/
|
||||
HANA("sap", "sap hana", "com.sap.db.jdbc.Driver", "", "", "'", "'"),
|
||||
/**
|
||||
* impala
|
||||
*/
|
||||
IMPALA("impala", "impala", "com.cloudera.impala.jdbc41.Driver", "", "", "'", "'");
|
||||
private String feature;
|
||||
private String desc;
|
||||
private String driver;
|
||||
private String keywordPrefix;
|
||||
private String keywordSuffix;
|
||||
private String aliasPrefix;
|
||||
private String aliasSuffix;
|
||||
private static final String JDBC_URL_PREFIX = "jdbc:";
|
||||
|
||||
DataTypeEnum(String feature, String desc, String driver, String keywordPrefix, String keywordSuffix, String aliasPrefix, String aliasSuffix) {
|
||||
this.feature = feature;
|
||||
this.desc = desc;
|
||||
this.driver = driver;
|
||||
this.keywordPrefix = keywordPrefix;
|
||||
this.keywordSuffix = keywordSuffix;
|
||||
this.aliasPrefix = aliasPrefix;
|
||||
this.aliasSuffix = aliasSuffix;
|
||||
}
|
||||
|
||||
public static DataTypeEnum urlOf(String jdbcUrl) {
|
||||
String url = jdbcUrl.toLowerCase().trim();
|
||||
for (DataTypeEnum dataTypeEnum : values()) {
|
||||
if (url.startsWith(JDBC_URL_PREFIX + dataTypeEnum.feature)) {
|
||||
try {
|
||||
Class<?> aClass = Class.forName(dataTypeEnum.getDriver());
|
||||
if (null == aClass) {
|
||||
throw new RuntimeException("Unable to get driver instance for jdbcUrl: " + jdbcUrl);
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException("Unable to get driver instance: " + jdbcUrl);
|
||||
}
|
||||
return dataTypeEnum;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getFeature() {
|
||||
return feature;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public String getDriver() {
|
||||
return driver;
|
||||
}
|
||||
|
||||
public String getKeywordPrefix() {
|
||||
return keywordPrefix;
|
||||
}
|
||||
|
||||
public String getKeywordSuffix() {
|
||||
return keywordSuffix;
|
||||
}
|
||||
|
||||
public String getAliasPrefix() {
|
||||
return aliasPrefix;
|
||||
}
|
||||
|
||||
public String getAliasSuffix() {
|
||||
return aliasSuffix;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package cn.odboy.mybatis.constant;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 查询描述
|
||||
*
|
||||
* @date 2023-11-25
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MpQuery {
|
||||
/**
|
||||
* 基本对象的属性名
|
||||
*/
|
||||
String propName() default "";
|
||||
|
||||
/**
|
||||
* 查询方式
|
||||
*/
|
||||
QueryTypeEnum type() default QueryTypeEnum.EQUAL;
|
||||
|
||||
/**
|
||||
* 连接查询的属性名, 如User类中的dept
|
||||
*/
|
||||
String joinName() default "";
|
||||
|
||||
/**
|
||||
* 默认左连接
|
||||
*/
|
||||
Join join() default Join.LEFT;
|
||||
|
||||
/**
|
||||
* 多字段模糊搜索, 仅支持String类型字段, 多个用逗号隔开, 如@MpQuery(blurry = "email,username")
|
||||
*/
|
||||
String blurry() default "";
|
||||
|
||||
/**
|
||||
* 适用于简单连接查询, 复杂的请自定义该注解, 或者使用sql查询
|
||||
*/
|
||||
enum Join {
|
||||
/**
|
||||
* 左连接
|
||||
*/
|
||||
LEFT,
|
||||
/**
|
||||
* 右连接
|
||||
*/
|
||||
RIGHT,
|
||||
/**
|
||||
* 内连接
|
||||
*/
|
||||
INNER
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package cn.odboy.mybatis.constant;
|
||||
|
||||
/**
|
||||
* 动态查询 枚举
|
||||
*/
|
||||
public enum QueryTypeEnum {
|
||||
/**
|
||||
* 相等
|
||||
*/
|
||||
EQUAL
|
||||
/**
|
||||
* 大于等于
|
||||
*/
|
||||
, GREATER_THAN
|
||||
/**
|
||||
* 小于等于
|
||||
*/
|
||||
, LESS_THAN
|
||||
/**
|
||||
* 中模糊查询
|
||||
*/
|
||||
, INNER_LIKE
|
||||
/**
|
||||
* 左模糊查询
|
||||
*/
|
||||
, LEFT_LIKE
|
||||
/**
|
||||
* 右模糊查询
|
||||
*/
|
||||
, RIGHT_LIKE
|
||||
/**
|
||||
* 小于
|
||||
*/
|
||||
, LESS_THAN_NQ
|
||||
/**
|
||||
* 包含
|
||||
*/
|
||||
, IN
|
||||
/**
|
||||
* 不包含
|
||||
*/
|
||||
, NOT_IN
|
||||
/**
|
||||
* 不等于
|
||||
*/
|
||||
, NOT_EQUAL
|
||||
/**
|
||||
* between(注:被注解的属性一定得是数组或者集合, 长度大于等于2)
|
||||
*/
|
||||
, BETWEEN
|
||||
/**
|
||||
* 不为空
|
||||
*/
|
||||
, NOT_NULL
|
||||
/**
|
||||
* 为空
|
||||
*/
|
||||
, IS_NULL
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.config.mybatis;
|
||||
package cn.odboy.mybatis.context;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.p6spy.engine.spy.appender.MessageFormattingStrategy;
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2021-2025 Tian Jun
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.odboy.mybatis.context;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
|
||||
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.extension.injector.methods.AlwaysUpdateSomeColumnById;
|
||||
import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;
|
||||
import org.apache.ibatis.session.Configuration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 批量插入SQL注入器
|
||||
*
|
||||
* @author odboy
|
||||
* @date 2025-01-11
|
||||
*/
|
||||
public class InsertBatchSqlInjector extends DefaultSqlInjector {
|
||||
@Override
|
||||
public List<AbstractMethod> getMethodList(Configuration configuration, Class<?> mapperClass, TableInfo tableInfo) {
|
||||
List<AbstractMethod> methodList = super.getMethodList(configuration, mapperClass, tableInfo);
|
||||
// 新增自定义方法, InsertBatchSomeColumn这个方法Mp没有开放出来
|
||||
methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE));
|
||||
// 全量更新, 包括null字段
|
||||
methodList.add(new AlwaysUpdateSomeColumnById(i -> i.getFieldFill() != FieldFill.INSERT));
|
||||
return methodList;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.config.mybatis;
|
||||
package cn.odboy.mybatis.context;
|
||||
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.odboy.util.SecurityUtil;
|
||||
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright 2021-2025 Tian Jun
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.odboy.mybatis.interfaces;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.odboy.base.PageResult;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
|
||||
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
|
||||
import com.baomidou.mybatisplus.extension.conditions.update.UpdateChainWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.toolkit.ChainWrappers;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 公共抽象Mapper接口类
|
||||
*
|
||||
* @author odboy
|
||||
* @date 2022-04-03
|
||||
*/
|
||||
public interface EasyMapper<E> extends BaseMapper<E> {
|
||||
/**
|
||||
* 批量插入
|
||||
*
|
||||
* @param entityList List<E>
|
||||
* @return 影响的行数
|
||||
*/
|
||||
int insertBatchSomeColumn(List<E> entityList);
|
||||
|
||||
/**
|
||||
* 根据id全量更新
|
||||
*
|
||||
* @param entity E
|
||||
* @return 影响的行数
|
||||
*/
|
||||
int alwaysUpdateSomeColumnById(@Param("et") E entity);
|
||||
|
||||
default QueryChainWrapper<E> select() {
|
||||
return ChainWrappers.queryChain(this);
|
||||
}
|
||||
|
||||
default UpdateChainWrapper<E> update() {
|
||||
return ChainWrappers.updateChain(this);
|
||||
}
|
||||
|
||||
default LambdaQueryChainWrapper<E> lambdaSelect() {
|
||||
return ChainWrappers.lambdaQueryChain(this);
|
||||
}
|
||||
|
||||
default LambdaUpdateChainWrapper<E> lambdaUpdate() {
|
||||
return ChainWrappers.lambdaUpdateChain(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字典
|
||||
*
|
||||
* @param wrapper LambdaQueryWrapper<E>
|
||||
* @param keyName 键对应的列名称
|
||||
* @param valueName 值对应的列名称
|
||||
* @return Map<String, Object>
|
||||
*/
|
||||
default Map<String, Object> selectMap(LambdaQueryWrapper<E> wrapper, String keyName, String valueName) {
|
||||
Map<String, Object> result = new ConcurrentHashMap<>(1);
|
||||
List<E> list = this.selectList(wrapper);
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return new HashMap<>();
|
||||
}
|
||||
E tempObj = list.stream().findFirst().orElse(null);
|
||||
if (tempObj == null) {
|
||||
return new HashMap<>();
|
||||
}
|
||||
Field[] fields = ReflectUtil.getFields(tempObj.getClass());
|
||||
for (E e : list) {
|
||||
Field keyField = null;
|
||||
Field valueField = null;
|
||||
for (Field field : fields) {
|
||||
String fieldName = field.getName();
|
||||
if (fieldName.equals(keyName)) {
|
||||
keyField = field;
|
||||
} else if (fieldName.equals(valueName)) {
|
||||
valueField = field;
|
||||
break;
|
||||
}
|
||||
}
|
||||
String fieldKey = String.valueOf(ReflectUtil.getFieldValue(e, keyField));
|
||||
Object fieldValue = ReflectUtil.getFieldValue(e, valueField);
|
||||
if (fieldKey != null) {
|
||||
result.put(fieldKey, fieldValue);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件查询列表, 并返回期望的对象
|
||||
*
|
||||
* @param wrapper LambdaQueryWrapper<E>
|
||||
* @param clazz 期望的对象类型
|
||||
* @return List<T>
|
||||
*/
|
||||
default <T> List<T> selectList(LambdaQueryWrapper<E> wrapper, Class<T> clazz) {
|
||||
List<E> list = this.selectList(wrapper);
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return BeanUtil.copyToList(list, clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件查询列表, 并返回期望的对象
|
||||
*
|
||||
* @param wrapper LambdaQueryWrapper<E>
|
||||
* @param clazz 期望的对象类型
|
||||
* @return List<T>
|
||||
*/
|
||||
default <T> List<T> selectList(LambdaQueryChainWrapper<E> wrapper, Class<T> clazz) {
|
||||
List<E> list = wrapper.list();
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return BeanUtil.copyToList(list, clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件查询分页列表, 并返回期望的对象
|
||||
*
|
||||
* @param pageable 分页参数
|
||||
* @param wrapper LambdaQueryWrapper<E> wrapper
|
||||
* @param clazz 期望的对象类型
|
||||
* @return IPage<T>
|
||||
*/
|
||||
default <T> PageResult<T> selectPage(Pageable pageable, LambdaQueryWrapper<E> wrapper, Class<T> clazz) {
|
||||
int pageNumber = pageable.getPageNumber();
|
||||
int pageSize = pageable.getPageSize();
|
||||
pageNumber = pageNumber <= 0 ? 1 : pageNumber;
|
||||
pageSize = pageSize <= 0 ? 10 : pageSize;
|
||||
IPage<E> pageInfo = this.selectPage(new Page<>(pageNumber, pageSize), wrapper);
|
||||
if (CollUtil.isEmpty(pageInfo.getRecords())) {
|
||||
return new PageResult<>(new ArrayList<>(), pageInfo.getTotal());
|
||||
}
|
||||
return new PageResult<>(BeanUtil.copyToList(pageInfo.getRecords(), clazz), pageInfo.getTotal());
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件查询分页列表, 并返回期望的对象
|
||||
*
|
||||
* @param pageable 分页参数
|
||||
* @param wrapper LambdaQueryWrapper<E> wrapper
|
||||
* @param clazz 期望的对象类型
|
||||
* @return IPage<T>
|
||||
*/
|
||||
default <T> PageResult<T> selectPage(Pageable pageable, LambdaQueryChainWrapper<E> wrapper, Class<T> clazz) {
|
||||
int pageNumber = pageable.getPageNumber();
|
||||
int pageSize = pageable.getPageSize();
|
||||
pageNumber = pageNumber <= 0 ? 1 : pageNumber;
|
||||
pageSize = pageSize <= 0 ? 10 : pageSize;
|
||||
IPage<E> pageInfo = wrapper.page(new Page<>(pageNumber, pageSize));
|
||||
if (CollUtil.isEmpty(pageInfo.getRecords())) {
|
||||
return new PageResult<>(new ArrayList<>(), pageInfo.getTotal());
|
||||
}
|
||||
return new PageResult<>(BeanUtil.copyToList(pageInfo.getRecords(), clazz), pageInfo.getTotal());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取目标类
|
||||
*
|
||||
* @param wrapper LambdaQueryChainWrapper<E> wrapper
|
||||
* @param clazz 期望的对象类型
|
||||
* @return T
|
||||
*/
|
||||
default <T> T selectOne(LambdaQueryChainWrapper<E> wrapper, Class<T> clazz) {
|
||||
E e = this.selectOne(wrapper);
|
||||
if (e == null) {
|
||||
return null;
|
||||
}
|
||||
return BeanUtil.copyProperties(e, clazz);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2021-2025 Tian Jun
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.odboy.mybatis.interfaces;
|
||||
|
||||
import cn.odboy.base.PageResult;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 公共抽象Mapper接口类
|
||||
*
|
||||
* @author odboy
|
||||
* @date 2022-04-03
|
||||
*/
|
||||
public interface EasyService<T> extends IService<T> {
|
||||
LambdaQueryWrapper<T> quick();
|
||||
|
||||
<G> int quickSave(G resources);
|
||||
|
||||
<G> int quickSaveBatch(List<G> resources);
|
||||
|
||||
<G> int quickModifyById(G resources);
|
||||
|
||||
<G> boolean quickModifyBatchById(Collection<G> resources, int batchSize);
|
||||
|
||||
<G> G quickGetOneById(Serializable id, Class<G> targetClazz);
|
||||
|
||||
T quickGetOne(LambdaQueryWrapper<T> wrapper, SFunction<T, ?> orderColumn);
|
||||
|
||||
<G> G quickGetOne(LambdaQueryWrapper<T> wrapper, SFunction<T, ?> orderColumn, Class<G> clazz);
|
||||
|
||||
<G> List<G> quickListByIds(List<Serializable> ids, Class<G> targetClazz);
|
||||
|
||||
<Q> List<T> quickList(Q criteria);
|
||||
|
||||
List<T> quickList(LambdaQueryWrapper<T> wrapper);
|
||||
|
||||
<G, Q> List<G> quickList(Q criteria, Class<G> targetClazz);
|
||||
|
||||
<G> List<G> quickList(LambdaQueryWrapper<T> wrapper, Class<G> targetClazz);
|
||||
|
||||
PageResult<T> quickPage(LambdaQueryWrapper<T> wrapper, IPage<T> pageable);
|
||||
|
||||
<G> PageResult<G> quickPage(LambdaQueryWrapper<T> wrapper, IPage<T> pageable, Class<G> targetClazz);
|
||||
|
||||
<G, Q> PageResult<G> quickPage(Q criteria, IPage<T> pageable, Class<G> targetClazz);
|
||||
|
||||
<Q> PageResult<T> quickPage(Q criteria, IPage<T> pageable);
|
||||
|
||||
int quickUpdate(LambdaQueryWrapper<T> wrapper, T entity);
|
||||
|
||||
int quickDelete(LambdaQueryWrapper<T> wrapper);
|
||||
}
|
||||
+260
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Copyright 2021-2025 Tian Jun
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.odboy.mybatis.interfaces.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.odboy.base.PageResult;
|
||||
import cn.odboy.exception.BadRequestException;
|
||||
import cn.odboy.mybatis.interfaces.EasyMapper;
|
||||
import cn.odboy.mybatis.util.MybatisHelper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.enums.SqlMethod;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.apache.ibatis.binding.MapperMethod;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 公共抽象Mapper接口类
|
||||
*
|
||||
* @author odboy
|
||||
* @date 2022-04-03
|
||||
*/
|
||||
public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M, T> {
|
||||
public LambdaQueryWrapper<T> quick() {
|
||||
return new LambdaQueryWrapper<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 快速插入
|
||||
*
|
||||
* @param resources /
|
||||
*/
|
||||
public <G> int quickSave(G resources) {
|
||||
return this.getBaseMapper().insert(BeanUtil.copyProperties(resources, this.getEntityClass()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 快速批量插入
|
||||
*
|
||||
* @param resources /
|
||||
*/
|
||||
public <G> int quickSaveBatch(List<G> resources) {
|
||||
return this.getBaseMapper().insertBatchSomeColumn(BeanUtil.copyToList(resources, this.getEntityClass()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 快速更新
|
||||
*
|
||||
* @param resources /
|
||||
*/
|
||||
public <G> int quickModifyById(G resources) {
|
||||
return this.getBaseMapper().updateById(BeanUtil.copyProperties(resources, this.getEntityClass()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 快速批量更新
|
||||
*
|
||||
* @param resources /
|
||||
* @param batchSize 每批数量
|
||||
*/
|
||||
public <G> boolean quickModifyBatchById(Collection<G> resources, int batchSize) {
|
||||
String sqlStatement = this.getSqlStatement(SqlMethod.UPDATE_BY_ID);
|
||||
return this.executeBatch(resources, batchSize, (sqlSession, entity) -> {
|
||||
MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>();
|
||||
param.put("et", BeanUtil.copyProperties(entity, this.getEntityClass()));
|
||||
sqlSession.update(sqlStatement, param);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id查询
|
||||
*
|
||||
* @param id /
|
||||
* @param targetClazz 目标类型
|
||||
*/
|
||||
public <G> G quickGetOneById(Serializable id, Class<G> targetClazz) {
|
||||
T entity = this.getById(id);
|
||||
return entity == null ? null : BeanUtil.copyProperties(entity, targetClazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查一条数据
|
||||
*
|
||||
* @param wrapper 制造条件
|
||||
*/
|
||||
public T quickGetOne(LambdaQueryWrapper<T> wrapper, SFunction<T, ?> orderColumn) {
|
||||
if (orderColumn == null) {
|
||||
throw new BadRequestException("参数orderColumn(排序的列)必填");
|
||||
}
|
||||
if (wrapper == null) {
|
||||
wrapper = new LambdaQueryWrapper<>();
|
||||
}
|
||||
wrapper.last("limit 1");
|
||||
wrapper.orderByDesc(orderColumn);
|
||||
List<T> ts = baseMapper.selectList(wrapper);
|
||||
if (ts.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return ts.stream().findFirst().get();
|
||||
}
|
||||
|
||||
public <G> G quickGetOne(LambdaQueryWrapper<T> wrapper, SFunction<T, ?> orderColumn, Class<G> clazz) {
|
||||
if (orderColumn == null) {
|
||||
throw new BadRequestException("参数orderColumn(排序的列)必填");
|
||||
}
|
||||
if (wrapper == null) {
|
||||
wrapper = new LambdaQueryWrapper<>();
|
||||
}
|
||||
wrapper.last("limit 1");
|
||||
wrapper.orderByDesc(orderColumn);
|
||||
List<T> ts = baseMapper.selectList(wrapper);
|
||||
if (ts.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return BeanUtil.copyProperties(ts.stream().findFirst().get(), clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id集合查询
|
||||
*
|
||||
* @param ids /
|
||||
* @param targetClazz 目标类型
|
||||
*/
|
||||
public <G> List<G> quickListByIds(List<Serializable> ids, Class<G> targetClazz) {
|
||||
List<T> entitys = this.listByIds(ids);
|
||||
return entitys == null || entitys.isEmpty() ? CollUtil.newArrayList() : BeanUtil.copyToList(entitys, targetClazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查有关的数据
|
||||
*
|
||||
* @param criteria 动态条件
|
||||
*/
|
||||
public <Q> List<T> quickList(Q criteria) {
|
||||
QueryWrapper<T> predicate = MybatisHelper.build(criteria);
|
||||
return baseMapper.selectList(predicate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查有关的数据
|
||||
*
|
||||
* @param wrapper 制造条件
|
||||
*/
|
||||
public List<T> quickList(LambdaQueryWrapper<T> wrapper) {
|
||||
if (wrapper == null) {
|
||||
wrapper = new LambdaQueryWrapper<>();
|
||||
}
|
||||
return baseMapper.selectList(wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查有关的数据并转成目标类型的数据
|
||||
*
|
||||
* @param criteria 动态条件
|
||||
* @param targetClazz 目标类型
|
||||
*/
|
||||
public <G, Q> List<G> quickList(Q criteria, Class<G> targetClazz) {
|
||||
QueryWrapper<T> predicate = MybatisHelper.build(criteria);
|
||||
List<T> data = baseMapper.selectList(predicate);
|
||||
return BeanUtil.copyToList(data, targetClazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查有关的数据并转换为目标类型
|
||||
*
|
||||
* @param wrapper 制造条件
|
||||
* @param targetClazz 目标类型
|
||||
*/
|
||||
public <G> List<G> quickList(LambdaQueryWrapper<T> wrapper, Class<G> targetClazz) {
|
||||
if (wrapper == null) {
|
||||
wrapper = new LambdaQueryWrapper<>();
|
||||
}
|
||||
return BeanUtil.copyToList(baseMapper.selectList(wrapper), targetClazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查有关的分页数据
|
||||
*
|
||||
* @param wrapper 制造条件
|
||||
* @param pageable 分页参数
|
||||
*/
|
||||
public PageResult<T> quickPage(LambdaQueryWrapper<T> wrapper, IPage<T> pageable) {
|
||||
if (wrapper == null) {
|
||||
wrapper = new LambdaQueryWrapper<>();
|
||||
}
|
||||
IPage<T> originPageData = baseMapper.selectPage(pageable, wrapper);
|
||||
return new PageResult<>(originPageData.getRecords(), originPageData.getTotal());
|
||||
}
|
||||
|
||||
/**
|
||||
* 查有关的分页数据
|
||||
*
|
||||
* @param wrapper 制造条件
|
||||
* @param pageable 分页参数
|
||||
* @param targetClazz 目标类型
|
||||
*/
|
||||
public <G> PageResult<G> quickPage(LambdaQueryWrapper<T> wrapper, IPage<T> pageable, Class<G> targetClazz) {
|
||||
if (wrapper == null) {
|
||||
wrapper = new LambdaQueryWrapper<>();
|
||||
}
|
||||
IPage<T> originPageData = baseMapper.selectPage(pageable, wrapper);
|
||||
return new PageResult<>(BeanUtil.copyToList(originPageData.getRecords(), targetClazz), originPageData.getTotal());
|
||||
}
|
||||
|
||||
public <G, Q> PageResult<G> quickPage(Q criteria, IPage<T> pageable, Class<G> targetClazz) {
|
||||
QueryWrapper<T> wrapper = MybatisHelper.build(criteria);
|
||||
IPage<T> originPageData = baseMapper.selectPage(pageable, wrapper);
|
||||
return new PageResult<>(BeanUtil.copyToList(originPageData.getRecords(), targetClazz), originPageData.getTotal());
|
||||
}
|
||||
|
||||
public <Q> PageResult<T> quickPage(Q criteria, IPage<T> pageable) {
|
||||
QueryWrapper<T> wrapper = MybatisHelper.build(criteria);
|
||||
IPage<T> originPageData = baseMapper.selectPage(pageable, wrapper);
|
||||
return new PageResult<>(originPageData.getRecords(), originPageData.getTotal());
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件更新
|
||||
*
|
||||
* @param wrapper 制造条件
|
||||
* @param entity 更新内容
|
||||
*/
|
||||
public int quickUpdate(LambdaQueryWrapper<T> wrapper, T entity) {
|
||||
if (wrapper == null) {
|
||||
throw new BadRequestException("参数wrapper必填");
|
||||
}
|
||||
return baseMapper.update(entity, wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件删除
|
||||
*
|
||||
* @param wrapper 制造条件
|
||||
*/
|
||||
public int quickDelete(LambdaQueryWrapper<T> wrapper) {
|
||||
if (wrapper == null) {
|
||||
throw new BadRequestException("参数wrapper必填");
|
||||
}
|
||||
return baseMapper.delete(wrapper);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright 2021-2025 Tian Jun
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.odboy.mybatis.util;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
|
||||
import com.baomidou.mybatisplus.generator.config.*;
|
||||
import com.baomidou.mybatisplus.generator.config.querys.MySqlQuery;
|
||||
import com.baomidou.mybatisplus.generator.config.rules.DateType;
|
||||
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
|
||||
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
|
||||
import com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine;
|
||||
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
|
||||
import com.baomidou.mybatisplus.generator.keywords.MySqlKeyWordsHandler;
|
||||
import lombok.Data;
|
||||
|
||||
import java.sql.Types;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* 代码生成器入口
|
||||
*
|
||||
* @author odboy
|
||||
* @date 2025-01-11
|
||||
*/
|
||||
@Data
|
||||
public class CmdGenHelper {
|
||||
/**
|
||||
* 数据库类型 MySQL
|
||||
*/
|
||||
private static final IDbQuery DB_QUERY = new MySqlQuery();
|
||||
/**
|
||||
* 类型转换
|
||||
*/
|
||||
private static final String TYPE_TINY_INT = "tinyint";
|
||||
private static final String TYPE_DATETIME = "datetime";
|
||||
private static final String TYPE_DATE = "date";
|
||||
private String databaseUrl;
|
||||
private String databaseUsername;
|
||||
private String databasePassword;
|
||||
private String driverClassName;
|
||||
private String parentPackageName;
|
||||
private String parentPackageModuleName;
|
||||
|
||||
/**
|
||||
* 代码生成函数
|
||||
*
|
||||
* @param tablePrefix 表前缀(可空)
|
||||
* @param tableNames 表名称, 多个用逗号分隔
|
||||
*/
|
||||
public void gen(String tablePrefix, List<String> tableNames) {
|
||||
// 1.数据库配置
|
||||
DataSourceConfig.Builder dataSourceConfigBuilder = new DataSourceConfig
|
||||
.Builder(this.databaseUrl, this.databaseUsername, this.databasePassword)
|
||||
.driverClassName(this.driverClassName);
|
||||
dataSourceConfigBuilder.dbQuery(DB_QUERY);
|
||||
dataSourceConfigBuilder.keyWordsHandler(new MySqlKeyWordsHandler());
|
||||
// 1.1.快速生成器
|
||||
FastAutoGenerator fastAutoGenerator = FastAutoGenerator.create(dataSourceConfigBuilder);
|
||||
// 2.全局配置
|
||||
// 自定义类型转换
|
||||
fastAutoGenerator.dataSourceConfig(getDataSourceConfigConsumer());
|
||||
// 覆盖已生成文件
|
||||
// 添加swagger注解
|
||||
// 设置注释的作者
|
||||
// 设置注释的日期格式
|
||||
// 使用java8新的时间类型
|
||||
fastAutoGenerator.globalConfig(getGlobalConfigConsumer());
|
||||
// 3.包配置
|
||||
// 设置父包名
|
||||
// 设置父包模块名
|
||||
// 设置MVC下各个模块的包名
|
||||
// 设置XML资源文件的目录
|
||||
fastAutoGenerator.packageConfig(getPackageConfigConsumer());
|
||||
// 4.模板配置
|
||||
// 使用Freemarker引擎模板, 默认的是Velocity引擎模板
|
||||
AbstractTemplateEngine templateEngine = new FreemarkerTemplateEngine();
|
||||
fastAutoGenerator.templateEngine(templateEngine);
|
||||
// 5.策略配置
|
||||
// 设置需要生成的表名
|
||||
// 设置过滤表前缀
|
||||
fastAutoGenerator.strategyConfig(getStrategyConfigConsumer(tableNames)
|
||||
);
|
||||
if (tablePrefix != null) {
|
||||
// 表前缀, 可多个
|
||||
fastAutoGenerator.strategyConfig(strategyConfigBuilder -> strategyConfigBuilder.addTablePrefix(tablePrefix));
|
||||
}
|
||||
// 5.1.Entity策略配置
|
||||
// 生成实体时生成字段的注解, 包括@TableId注解等
|
||||
// 数据库表和字段映射到实体的命名策略, 为下划线转驼峰
|
||||
// 全局主键类型为None
|
||||
// 实体名称格式化为XXXEntity
|
||||
fastAutoGenerator.strategyConfig(getEntityConfigConsumer());
|
||||
// 5.2.Controller策略配置
|
||||
// 开启生成@RestController控制器
|
||||
fastAutoGenerator.strategyConfig(strategyConfigBuilder -> strategyConfigBuilder.controllerBuilder().enableRestStyle());
|
||||
// 如果不需要生成Controller
|
||||
// fastAutoGenerator.templateConfig(templateConfig -> templateConfig.controller(""));
|
||||
// 5.3.Service策略配置
|
||||
// 格式化service接口和实现类的文件名称, 去掉默认的ServiceName前面的I
|
||||
fastAutoGenerator.strategyConfig(strategyConfigBuilder -> strategyConfigBuilder
|
||||
.serviceBuilder()
|
||||
.formatServiceFileName("%sService")
|
||||
.formatServiceImplFileName("%sServiceImpl"));
|
||||
// 5.4.Mapper策略配置
|
||||
// 格式化 mapper文件名,格式化xml实现类文件名称
|
||||
fastAutoGenerator.strategyConfig(getStrategyConfigConsumer());
|
||||
// 6.生成代码
|
||||
fastAutoGenerator.execute();
|
||||
}
|
||||
|
||||
private static Consumer<StrategyConfig.Builder> getEntityConfigConsumer() {
|
||||
return strategyConfigBuilder -> strategyConfigBuilder
|
||||
.entityBuilder()
|
||||
.enableLombok()
|
||||
// 如果不需要生成注解, 去掉.enableTableFieldAnnotation()
|
||||
.enableTableFieldAnnotation()
|
||||
.enableFileOverride()
|
||||
.naming(NamingStrategy.underline_to_camel)
|
||||
.columnNaming(NamingStrategy.underline_to_camel)
|
||||
.idType(IdType.AUTO);
|
||||
}
|
||||
|
||||
private static Consumer<StrategyConfig.Builder> getStrategyConfigConsumer(List<String> tableNames) {
|
||||
return strategyConfigBuilder -> strategyConfigBuilder
|
||||
.enableCapitalMode()
|
||||
.enableSkipView()
|
||||
.disableSqlFilter()
|
||||
.addInclude(tableNames)
|
||||
.mapperBuilder()
|
||||
.build();
|
||||
}
|
||||
|
||||
private Consumer<PackageConfig.Builder> getPackageConfigConsumer() {
|
||||
return packageConfigBuilder -> packageConfigBuilder
|
||||
.parent(this.parentPackageName == null ? "cn.codegen" : this.parentPackageName)
|
||||
.moduleName(this.parentPackageModuleName == null ? "moduleName" : this.parentPackageModuleName)
|
||||
.entity("domain")
|
||||
.service("service")
|
||||
.mapper("mapper")
|
||||
.serviceImpl("service.service")
|
||||
.controller("rest")
|
||||
.pathInfo(Collections.singletonMap(OutputFile.xml, (System.getProperty("os.name").toLowerCase().contains("win") ? "C:\\CodeGen\\resources\\mapper" : "/tmp/CodeGen/resources/mapper")));
|
||||
}
|
||||
|
||||
private static Consumer<GlobalConfig.Builder> getGlobalConfigConsumer() {
|
||||
return globalConfigBuilder -> globalConfigBuilder
|
||||
.enableSwagger()
|
||||
.outputDir((System.getProperty("os.name").toLowerCase().contains("win") ? "C:\\CodeGen" : "/tmp/CodeGen"))
|
||||
.author("codegen")
|
||||
.commentDate("yyyy-MM-dd")
|
||||
.dateType(DateType.TIME_PACK);
|
||||
}
|
||||
|
||||
private static Consumer<StrategyConfig.Builder> getStrategyConfigConsumer() {
|
||||
return strategyConfigBuilder -> strategyConfigBuilder
|
||||
.mapperBuilder()
|
||||
.formatMapperFileName("%sMapper")
|
||||
.formatXmlFileName("%sMapper");
|
||||
}
|
||||
|
||||
private static Consumer<DataSourceConfig.Builder> getDataSourceConfigConsumer() {
|
||||
return builder -> builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
|
||||
int typeCode = metaInfo.getJdbcType().TYPE_CODE;
|
||||
if (typeCode == Types.SMALLINT) {
|
||||
return DbColumnType.INTEGER;
|
||||
}
|
||||
if (typeCode == Types.DATE) {
|
||||
return DbColumnType.DATE;
|
||||
}
|
||||
if (typeCode == Types.TIME) {
|
||||
return DbColumnType.DATE;
|
||||
}
|
||||
if (typeCode == Types.TIMESTAMP) {
|
||||
return DbColumnType.DATE;
|
||||
}
|
||||
return typeRegistry.getColumnType(metaInfo);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
package cn.odboy.mybatis.util;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.odboy.base.MyEntity;
|
||||
import cn.odboy.exception.BadRequestException;
|
||||
import cn.odboy.mybatis.constant.MpQuery;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 查询条件创建工具
|
||||
*/
|
||||
@Slf4j
|
||||
public class MybatisHelper {
|
||||
public static <R, Q> QueryWrapper<R> build(Q query) {
|
||||
QueryWrapper<R> queryWrapper = new QueryWrapper<>();
|
||||
if (query == null) {
|
||||
return queryWrapper;
|
||||
}
|
||||
Class<?> clazz = query.getClass();
|
||||
try {
|
||||
List<Field> fields = getAllFields(clazz, new ArrayList<>());
|
||||
for (Field field : fields) {
|
||||
if (!field.canAccess(clazz)) {
|
||||
field.setAccessible(true);
|
||||
MpQuery q = field.getAnnotation(MpQuery.class);
|
||||
if (q != null) {
|
||||
String propName = q.propName();
|
||||
String blurry = q.blurry();
|
||||
String attributeName = StrUtil.isBlank(propName) ? field.getName() : propName;
|
||||
attributeName = humpToUnderline(attributeName);
|
||||
Object fieldVal = field.get(query);
|
||||
if (ObjectUtil.isNull(fieldVal) || "".equals(fieldVal)) {
|
||||
continue;
|
||||
}
|
||||
if (ObjectUtil.isNotEmpty(blurry)) {
|
||||
handleBlurryQuery(queryWrapper, blurry, fieldVal);
|
||||
continue;
|
||||
}
|
||||
handleWrapper(q, queryWrapper, attributeName, fieldVal);
|
||||
}
|
||||
field.setAccessible(false);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("组装SQL失败", e);
|
||||
}
|
||||
return queryWrapper;
|
||||
}
|
||||
|
||||
private static <R> void handleWrapper(MpQuery q, QueryWrapper<R> queryWrapper, String attributeName, Object fieldVal) {
|
||||
switch (q.type()) {
|
||||
case EQUAL:
|
||||
queryWrapper.eq(attributeName, fieldVal);
|
||||
break;
|
||||
case GREATER_THAN:
|
||||
queryWrapper.ge(attributeName, fieldVal);
|
||||
break;
|
||||
case LESS_THAN:
|
||||
queryWrapper.le(attributeName, fieldVal);
|
||||
break;
|
||||
case LESS_THAN_NQ:
|
||||
queryWrapper.lt(attributeName, fieldVal);
|
||||
break;
|
||||
case INNER_LIKE:
|
||||
queryWrapper.like(attributeName, fieldVal);
|
||||
break;
|
||||
case LEFT_LIKE:
|
||||
queryWrapper.likeLeft(attributeName, fieldVal);
|
||||
break;
|
||||
case RIGHT_LIKE:
|
||||
queryWrapper.likeRight(attributeName, fieldVal);
|
||||
break;
|
||||
case IN:
|
||||
handleInQuery(queryWrapper, attributeName, fieldVal);
|
||||
break;
|
||||
case NOT_IN:
|
||||
handleNotInQuery(queryWrapper, attributeName, fieldVal);
|
||||
break;
|
||||
case NOT_EQUAL:
|
||||
queryWrapper.ne(attributeName, fieldVal);
|
||||
break;
|
||||
case NOT_NULL:
|
||||
queryWrapper.isNotNull(attributeName);
|
||||
break;
|
||||
case IS_NULL:
|
||||
queryWrapper.isNull(attributeName);
|
||||
break;
|
||||
case BETWEEN:
|
||||
handleBetweenQuery(queryWrapper, fieldVal, attributeName);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static <R> void handleBetweenQuery(QueryWrapper<R> queryWrapper, Object fieldVal, String finalAttributeName) {
|
||||
if (fieldVal instanceof List) {
|
||||
List<Object> between = new ArrayList<>((List<?>) fieldVal);
|
||||
if (CollectionUtil.isNotEmpty(between)) {
|
||||
if (between.size() >= 2) {
|
||||
queryWrapper.between(finalAttributeName, between.get(0), between.get(1));
|
||||
} else {
|
||||
throw new BadRequestException("BETWEEN类型的对象列表长度必须 >= 2");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new BadRequestException("BETWEEN类型的对象必须是一个List子集合");
|
||||
}
|
||||
}
|
||||
|
||||
private static <R> void handleNotInQuery(QueryWrapper<R> queryWrapper, String finalAttributeName, Object fieldVal) {
|
||||
Collection<?> wrapNotInVal = (Collection<?>) fieldVal;
|
||||
if (CollectionUtil.isNotEmpty(wrapNotInVal)) {
|
||||
Optional<?> anyValOptional = wrapNotInVal.stream().findAny();
|
||||
if (anyValOptional.isPresent()) {
|
||||
Object o = anyValOptional.get();
|
||||
if (o instanceof Long) {
|
||||
queryWrapper.notIn(finalAttributeName, fieldVal);
|
||||
} else if (o instanceof Integer) {
|
||||
queryWrapper.notIn(finalAttributeName, fieldVal);
|
||||
} else {
|
||||
throw new BadRequestException("NOT_IN类型的对象属性值必须是Long/Integer类型集合");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* IN查询
|
||||
*
|
||||
* @param queryWrapper /
|
||||
* @param fieldVal /
|
||||
* @param finalAttributeName /
|
||||
* @param <R> /
|
||||
*/
|
||||
private static <R> void handleInQuery(QueryWrapper<R> queryWrapper, String finalAttributeName, Object fieldVal) {
|
||||
Collection<?> wrapInVal = (Collection<?>) fieldVal;
|
||||
if (CollectionUtil.isNotEmpty(wrapInVal)) {
|
||||
Optional<?> anyValOptional = wrapInVal.stream().findAny();
|
||||
if (anyValOptional.isPresent()) {
|
||||
Object o = anyValOptional.get();
|
||||
if (o instanceof Long) {
|
||||
queryWrapper.in(finalAttributeName, fieldVal);
|
||||
} else if (o instanceof Integer) {
|
||||
queryWrapper.in(finalAttributeName, fieldVal);
|
||||
} else {
|
||||
throw new BadRequestException("IN类型的对象属性值必须是Long/Integer类型集合");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 模糊多字段
|
||||
*
|
||||
* @param queryWrapper /
|
||||
* @param blurry /
|
||||
* @param fieldVal /
|
||||
* @param <R> /
|
||||
*/
|
||||
private static <R> void handleBlurryQuery(QueryWrapper<R> queryWrapper, String blurry, Object fieldVal) {
|
||||
List<String> blurryList = Arrays.stream(blurry.split(",")).filter(StrUtil::isNotBlank).distinct().collect(Collectors.toList());
|
||||
queryWrapper.and(wrapper -> {
|
||||
for (String blurryItem : blurryList) {
|
||||
String column = humpToUnderline(blurryItem);
|
||||
wrapper.or();
|
||||
wrapper.like(column, fieldVal.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static List<Field> getAllFields(Class<?> clazz, List<Field> fields) {
|
||||
if (clazz != null) {
|
||||
fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
|
||||
getAllFields(clazz.getSuperclass(), fields);
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
/***
|
||||
* 驼峰命名转为下划线命名
|
||||
*
|
||||
* @param para
|
||||
* 驼峰命名的字符串
|
||||
*/
|
||||
private static String humpToUnderline(String para) {
|
||||
return StrUtil.toUnderlineCase(para);
|
||||
}
|
||||
|
||||
@TableName("test_domain")
|
||||
private static class TestDomain {
|
||||
@NotNull(groups = MyEntity.Update.class)
|
||||
@TableId(value = "user_id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
@TableField(value = "dept_id")
|
||||
private Long deptId;
|
||||
@NotBlank
|
||||
private String username;
|
||||
@NotBlank
|
||||
private String nickName;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
QueryWrapper<TestDomain> query = new QueryWrapper<TestDomain>();
|
||||
//query.or();
|
||||
query.or(wrapper -> wrapper.eq("username", 1).or().eq("nickname", 2));
|
||||
//query.like("a",1);
|
||||
//query.or();
|
||||
//query.like("b",2);
|
||||
//query.and(wrapper->wrapper.eq("c",1));
|
||||
query.eq("id", 1);
|
||||
query.orderByDesc("id");
|
||||
// query.apply("left join student t1 on t1.id = t1.id");
|
||||
// query.last("left join student t1 on t1.id = t1.id");
|
||||
System.err.println("getSqlSelect=================================");
|
||||
System.err.println(query.getSqlSelect());
|
||||
System.err.println("getSqlSegment=================================");
|
||||
System.err.println(query.getSqlSegment());
|
||||
System.err.println("getSqlComment=================================");
|
||||
System.err.println(query.getSqlComment());
|
||||
System.err.println("getSqlSet=================================");
|
||||
System.err.println(query.getSqlSet());
|
||||
System.err.println("getTargetSql=================================");
|
||||
System.err.println(query.getTargetSql());
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.config.properties;
|
||||
package cn.odboy.properties;
|
||||
|
||||
import cn.odboy.constant.SystemConstant;
|
||||
import lombok.Data;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.config.properties;
|
||||
package cn.odboy.properties;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
+11
-2
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.config;
|
||||
package cn.odboy.redis;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONFactory;
|
||||
@@ -39,7 +39,10 @@ public class RedisConfiguration extends CachingConfigurerSupport {
|
||||
/**
|
||||
* 自动识别json对象白名单配置(仅允许解析的包名,范围越小越安全)
|
||||
*/
|
||||
private static final String[] WHITELIST_STR = {"cn.odboy"};
|
||||
private static final String[] WHITELIST_STR = {
|
||||
"org.springframework",
|
||||
"cn.odboy.model",
|
||||
};
|
||||
|
||||
/**
|
||||
* 设置 redis 数据默认过期时间,默认2小时
|
||||
@@ -158,6 +161,9 @@ public class RedisConfiguration extends CachingConfigurerSupport {
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
/**
|
||||
* 序列化
|
||||
*/
|
||||
@Override
|
||||
public byte[] serialize(T t) throws SerializationException {
|
||||
if (t == null) {
|
||||
@@ -166,6 +172,9 @@ public class RedisConfiguration extends CachingConfigurerSupport {
|
||||
return JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 反序列化
|
||||
*/
|
||||
@Override
|
||||
public T deserialize(byte[] bytes) throws SerializationException {
|
||||
if (bytes == null || bytes.length == 0) {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.config;
|
||||
package cn.odboy.redis;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.Data;
|
||||
+13
-2
@@ -1,6 +1,6 @@
|
||||
package cn.odboy.config.webConfig;
|
||||
package cn.odboy.server;
|
||||
|
||||
import cn.odboy.config.properties.FileProperties;
|
||||
import cn.odboy.properties.FileProperties;
|
||||
import com.alibaba.fastjson2.JSONWriter;
|
||||
import com.alibaba.fastjson2.support.config.FastJsonConfig;
|
||||
import com.alibaba.fastjson2.support.spring.http.converter.FastJsonHttpMessageConverter;
|
||||
@@ -67,7 +67,18 @@ public class ConfigurerAdapter implements WebMvcConfigurer {
|
||||
config.setDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
// 开启引用检测,枚举支持
|
||||
config.setWriterFeatures(
|
||||
// 是否输出值为null的字段
|
||||
// SerializerFeature.WriteMapNullValue,
|
||||
// 字段如果为null,输出为false,而非null
|
||||
// JSONWriter.Feature.WriteNullBooleanAsFalse,
|
||||
// 字段如果为null,输出为[],而非null
|
||||
// JSONWriter.Feature.WriteNullListAsEmpty,
|
||||
// 字符类型字段如果为null,输出为"",而非null
|
||||
// JSONWriter.Feature.WriteNullStringAsEmpty,
|
||||
// 太具体的数值会直接影响逻辑本身,所以不要这个
|
||||
// SerializerFeature.WriteNullNumberAsZero,
|
||||
JSONWriter.Feature.WriteEnumUsingToString,
|
||||
// SerializerFeature.DisableCircularReferenceDetect
|
||||
JSONWriter.Feature.ReferenceDetection
|
||||
);
|
||||
fastJsonConverter.setFastJsonConfig(config);
|
||||
+9
-4
@@ -1,5 +1,7 @@
|
||||
package cn.odboy.config.webConfig;
|
||||
package cn.odboy.server;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.web.servlet.MultipartConfigFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -8,20 +10,23 @@ import javax.servlet.MultipartConfigElement;
|
||||
import java.io.File;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class MultipartConfig {
|
||||
@Value("${spring.application.name}")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 文件上传临时路径
|
||||
*/
|
||||
@Bean
|
||||
MultipartConfigElement multipartConfigElement() {
|
||||
public MultipartConfigElement multipartConfigElement() {
|
||||
MultipartConfigFactory factory = new MultipartConfigFactory();
|
||||
String location = System.getProperty("user.home") + "/.eladmin/file/tmp";
|
||||
String location = System.getProperty("user.home") + "/." + name + "/tmp";
|
||||
File tmpFile = new File(location);
|
||||
if (!tmpFile.exists()) {
|
||||
if (!tmpFile.mkdirs()) {
|
||||
System.out.println("create was not successful.");
|
||||
log.error("创建临时文件失败");
|
||||
}
|
||||
}
|
||||
factory.setLocation(location);
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.config.webConfig;
|
||||
package cn.odboy.server;
|
||||
|
||||
import cn.odboy.util.AnonTagUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -64,8 +64,8 @@ public class SwaggerConfig {
|
||||
private ApiInfo apiInfo() {
|
||||
return new ApiInfoBuilder()
|
||||
.description("一个简单且易上手的 Spring boot 后台管理框架")
|
||||
.title("ELADMIN 接口文档")
|
||||
.version("1.6")
|
||||
.title("CuteJava 接口文档")
|
||||
.version("1.3.0")
|
||||
.build();
|
||||
}
|
||||
|
||||
+16
-10
@@ -1,5 +1,6 @@
|
||||
package cn.odboy.config;
|
||||
package cn.odboy.thread;
|
||||
|
||||
import com.alibaba.ttl.TtlRunnable;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -53,7 +54,7 @@ public class AsyncExecutor implements AsyncConfigurer {
|
||||
@Override
|
||||
public Executor getAsyncExecutor() {
|
||||
// 自定义工厂
|
||||
ThreadFactory factory = r -> new Thread(r, "el-async-" + new AtomicInteger(1).getAndIncrement());
|
||||
ThreadFactory factory = r -> new Thread(r, "default-async-" + new AtomicInteger(1).getAndIncrement());
|
||||
// 自定义线程池
|
||||
return new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveSeconds,
|
||||
TimeUnit.SECONDS, new ArrayBlockingQueue<>(queueCapacity), factory,
|
||||
@@ -63,18 +64,23 @@ public class AsyncExecutor implements AsyncConfigurer {
|
||||
/**
|
||||
* 自定义线程池,用法,注入到类中使用
|
||||
* private ThreadPoolTaskExecutor taskExecutor;
|
||||
*
|
||||
* @return ThreadPoolTaskExecutor
|
||||
*/
|
||||
@Bean("taskAsync")
|
||||
public ThreadPoolTaskExecutor taskAsync() {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
executor.setCorePoolSize(2);
|
||||
executor.setMaxPoolSize(4);
|
||||
executor.setQueueCapacity(20);
|
||||
executor.setKeepAliveSeconds(60);
|
||||
executor.setThreadNamePrefix("el-task-");
|
||||
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||
executor.setCorePoolSize(AsyncExecutor.corePoolSize);
|
||||
executor.setMaxPoolSize(AsyncExecutor.maxPoolSize);
|
||||
executor.setQueueCapacity(AsyncExecutor.queueCapacity);
|
||||
executor.setThreadNamePrefix("task-async-");
|
||||
executor.setKeepAliveSeconds(AsyncExecutor.keepAliveSeconds);
|
||||
// DiscardOldestPolicy,抛弃最早的任务,将新任务加入队列。
|
||||
// AbortPolicy,拒绝执行新任务,并抛出异常。
|
||||
// CallerRunsPolicy,交由调用者线程执行新任务,如果调用者线程已关闭,则抛弃任务。
|
||||
// DiscardPolicy,直接抛弃新任务。
|
||||
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
|
||||
// 设置包装器
|
||||
executor.setTaskDecorator(TtlRunnable::get);
|
||||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package cn.odboy.util;
|
||||
|
||||
import cn.odboy.annotation.rest.AnonymousAccess;
|
||||
import cn.odboy.annotation.AnonymousAccess;
|
||||
import cn.odboy.constant.RequestMethodEnum;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2021-2025 Tian Jun
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.odboy.util;
|
||||
|
||||
import cn.hutool.core.codec.Base64Encoder;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* 加密令牌生成工具
|
||||
*
|
||||
* @author odboy
|
||||
* @date 2022-11-16
|
||||
*/
|
||||
public class Base64SecretUtil {
|
||||
private Base64SecretUtil() {
|
||||
}
|
||||
|
||||
public static String build() {
|
||||
// 128位uuid
|
||||
return Base64Encoder.encode(getLongUuid(4).getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public static String getLongUuid(int bit) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (int i = 0; i < bit; i++) {
|
||||
result.append(IdUtil.simpleUUID());
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(build());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,279 @@
|
||||
/*
|
||||
* Copyright 2021-2025 Tian Jun
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.odboy.util;
|
||||
|
||||
import cn.odboy.base.MyMetaOption;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 集合工具
|
||||
*
|
||||
* @author odboy
|
||||
* @date 2022-11-09
|
||||
*/
|
||||
public class CollUtil extends cn.hutool.core.collection.CollUtil {
|
||||
/**
|
||||
* 连接器
|
||||
*/
|
||||
private static final Joiner JOINER = Joiner.on(",").skipNulls();
|
||||
/**
|
||||
* 分割器
|
||||
*/
|
||||
private static final Splitter SPLITTER = Splitter.on(",").trimResults().omitEmptyStrings();
|
||||
|
||||
public static String join(Object[] parts) {
|
||||
return JOINER.join(parts);
|
||||
}
|
||||
|
||||
public static String join(Iterable<?> parts) {
|
||||
return JOINER.join(parts);
|
||||
}
|
||||
|
||||
public static String join(Iterator<?> parts) {
|
||||
return JOINER.join(parts);
|
||||
}
|
||||
|
||||
public static List<String> splitToList(String parts) {
|
||||
return SPLITTER.splitToList(parts);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分几份
|
||||
*
|
||||
* @param parts /
|
||||
* @param size /
|
||||
* @param <T> /
|
||||
* @return /
|
||||
*/
|
||||
public static <T> List<List<T>> splitToSize(List<T> parts, int size) {
|
||||
return Lists.partition(parts, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* 一份几个
|
||||
*
|
||||
* @param parts /
|
||||
* @param groupNum /
|
||||
* @param <T> /
|
||||
* @return /
|
||||
*/
|
||||
public static <T> List<List<T>> splitToSegment(List<T> parts, int groupNum) {
|
||||
List<List<T>> result = new ArrayList<>(1);
|
||||
int i = 0;
|
||||
for (; i < parts.size() / groupNum; i++) {
|
||||
result.add(parts.subList(i * groupNum, (i + 1) * groupNum));
|
||||
}
|
||||
if (parts.size() % groupNum != 0) {
|
||||
result.add(parts.subList(i * groupNum, i * groupNum + parts.size() % groupNum));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static <T, K> Predicate<T> distinctPredicate(Function<? super T, ? extends K> keyMapper) {
|
||||
Map<Object, Boolean> map = new HashMap<>();
|
||||
return (t) -> null == map.putIfAbsent(keyMapper.apply(t), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 流根据对象属性去重
|
||||
* <p>
|
||||
* 使用方式: list = CollUtil.streamDistinct(list, Object::getXXX)
|
||||
*/
|
||||
public static <T, K> List<T> streamDistinct(List<T> data, Function<? super T, ? extends K> keyMapper) {
|
||||
return data.stream().filter(distinctPredicate(keyMapper)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 流根据对象属性自然排序
|
||||
* <p>
|
||||
* 使用方式: list = CollUtil.streamAscSort(list, Object::getXXX)
|
||||
*
|
||||
* @param data /
|
||||
* @param keyExtractor /
|
||||
* @param <T> /
|
||||
* @param <U> /
|
||||
* @return /
|
||||
*/
|
||||
public static <T, U extends Comparable<? super U>> List<T> streamAscSort(List<T> data, Function<? super T, ? extends U> keyExtractor) {
|
||||
return data.stream().sorted(Comparator.comparing(keyExtractor)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 流根据对象属性倒转排序
|
||||
* <p>
|
||||
* 使用方式: list = CollUtil.streamDescSort(list, Object::getXXX)
|
||||
*
|
||||
* @param data /
|
||||
* @param keyExtractor /
|
||||
* @param <T> /
|
||||
* @param <U> /
|
||||
* @return /
|
||||
*/
|
||||
public static <T, U extends Comparable<? super U>> List<T> streamDescSort(List<T> data, Function<? super T, ? extends U> keyExtractor) {
|
||||
return data.stream().sorted(Comparator.comparing(keyExtractor).reversed()).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 流拆分对象为键值对
|
||||
* <p>
|
||||
* 使用方式: map = CollUtil.streamToMap(list, Object::getXXKey, Object::getXXValue)
|
||||
*
|
||||
* @param data /
|
||||
* @param keyMapper /
|
||||
* @param valueMapper /
|
||||
* @param <T> /
|
||||
* @param <K> /
|
||||
* @param <U> /
|
||||
* @return /
|
||||
*/
|
||||
public static <T, K, U> Map<K, U> streamToMap(List<T> data, Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper) {
|
||||
// 根据key去重再并流
|
||||
return streamDistinct(data, keyMapper).stream().collect(Collectors.toMap(keyMapper, valueMapper));
|
||||
}
|
||||
|
||||
/**
|
||||
* 流对List<Double>求和
|
||||
* <p>
|
||||
* 使用方式: total = CollUtil.streamDoubleAdd(doubleList)
|
||||
*
|
||||
* @param data /
|
||||
* @return /
|
||||
*/
|
||||
public static Double streamDoubleAdd(List<Double> data) {
|
||||
if (CollUtil.isNotEmpty(data)) {
|
||||
return data.stream().filter(Objects::nonNull).reduce(Double::sum).orElse(0.0);
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 流对List<BigDecimal>求和
|
||||
* <p>
|
||||
* 使用方式: total = CollUtil.streamBigDecimalAdd(doubleList)
|
||||
*
|
||||
* @param data /
|
||||
* @return /
|
||||
*/
|
||||
public static BigDecimal streamBigDecimalAdd(List<BigDecimal> data) {
|
||||
if (CollUtil.isNotEmpty(data)) {
|
||||
return data.stream().filter(Objects::nonNull).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
|
||||
}
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 流对List<Object>中的某一BigDecimal属性求和
|
||||
* <p>
|
||||
* 使用方式: total = CollUtil.streamBigDecimalAdd(list, XXX)
|
||||
*
|
||||
* @param data /
|
||||
* @return /
|
||||
*/
|
||||
public static <T> BigDecimal streamBigDecimalAdd(List<T> data, String elementName) {
|
||||
return data.stream().filter(Objects::nonNull).map(m -> {
|
||||
// 反射, 取集合中各元素的某属性
|
||||
BigDecimal that;
|
||||
try {
|
||||
Field field = m.getClass().getDeclaredField(elementName);
|
||||
field.setAccessible(true);
|
||||
that = (BigDecimal) field.get(m);
|
||||
} catch (Exception e) {
|
||||
// 忽略异常
|
||||
that = BigDecimal.ZERO;
|
||||
}
|
||||
return that;
|
||||
}).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 流对List<BigDecimal>取最大值
|
||||
* <p>
|
||||
* 使用方式: max = CollUtil.streamBigDecimalMax(list)
|
||||
*
|
||||
* @param data /
|
||||
* @return /
|
||||
*/
|
||||
public static BigDecimal streamBigDecimalMax(List<BigDecimal> data) {
|
||||
return data.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.reduce(BigDecimal::max)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 流对List<BigDecimal>取最小值
|
||||
* <p>
|
||||
* 使用方式: max = CollUtil.streamBigDecimalMin(list)
|
||||
*
|
||||
* @param data /
|
||||
* @return /
|
||||
*/
|
||||
public static BigDecimal streamBigDecimalMin(List<BigDecimal> data) {
|
||||
return data.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.reduce(BigDecimal::min)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 流对List<BigDecimal>取平均值
|
||||
* <p>
|
||||
* 使用方式: avg = CollUtil.streamBigDecimalAvg(list)
|
||||
*
|
||||
* @param data /
|
||||
* @return /
|
||||
*/
|
||||
public static BigDecimal streamBigDecimalAvg(List<BigDecimal> data) {
|
||||
return data.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add)
|
||||
.divide(BigDecimal.valueOf(data.size()), 6, RoundingMode.FLOOR);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
List<MyMetaOption> testData = new ArrayList<>();
|
||||
MyMetaOption selectOption1 = MyMetaOption.builder().label("苹果").value("apple").build();
|
||||
MyMetaOption selectOption2 = MyMetaOption.builder().label("苹果").value("apple").build();
|
||||
MyMetaOption selectOption3 = MyMetaOption.builder().label("香蕉").value("banana").build();
|
||||
MyMetaOption selectOption4 = MyMetaOption.builder().label("猫").value("cat").build();
|
||||
testData.add(selectOption1);
|
||||
testData.add(selectOption2);
|
||||
testData.add(selectOption3);
|
||||
testData.add(selectOption4);
|
||||
List<MyMetaOption> selectOptions1 = CollUtil.streamAscSort(testData, MyMetaOption::getValue);
|
||||
System.out.println(JSON.toJSONString(selectOptions1));
|
||||
List<MyMetaOption> selectOptions2 = CollUtil.streamDescSort(testData, MyMetaOption::getValue);
|
||||
System.out.println(JSON.toJSONString(selectOptions2));
|
||||
List<MyMetaOption> selectOptions3 = CollUtil.streamDistinct(testData, MyMetaOption::getValue);
|
||||
System.out.println(JSON.toJSONString(selectOptions3));
|
||||
Map<String, String> selectMap1 = CollUtil.streamToMap(testData, MyMetaOption::getValue, MyMetaOption::getLabel);
|
||||
System.out.println(JSON.toJSONString(selectMap1));
|
||||
// 这只是一个示范
|
||||
BigDecimal total1 = CollUtil.streamBigDecimalAdd(testData, "value");
|
||||
System.out.println(total1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2021-2025 Tian Jun
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.odboy.util;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.TypeReference;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Json工具
|
||||
*
|
||||
* @author odboy
|
||||
* @date 2024-10-01
|
||||
*/
|
||||
public class JsonUtil {
|
||||
public static <K, V> Map<K, V> toMap(String jsonStr, Class<K> kClass, Class<V> vClass) {
|
||||
return JSON.parseObject(jsonStr, new TypeReference<Map<K, V>>() {
|
||||
});
|
||||
}
|
||||
|
||||
public static <V> List<V> toList(String jsonStr, Class<V> vClass) {
|
||||
return JSON.parseObject(jsonStr, new TypeReference<List<V>>() {
|
||||
});
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String mapStr = "{\"key1\":\"value1\", \"key2\":\"value2\"}";
|
||||
System.err.println(JsonUtil.toMap(mapStr, String.class, String.class));
|
||||
String listStr = "[\"value1\", \"value2\"]";
|
||||
System.err.println(JsonUtil.toList(listStr, String.class));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2021-2025 Tian Jun
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.odboy.util;
|
||||
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.odboy.base.MyEntity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* List 工具
|
||||
*
|
||||
* @author odboy
|
||||
* @date 2024-10-01
|
||||
*/
|
||||
public class ListUtil {
|
||||
/**
|
||||
* 根据对象T的属性去重
|
||||
*
|
||||
* @param items 对象T集合
|
||||
* @param classifier 对象T属性表达式, 比如: User::getName
|
||||
*/
|
||||
public static <T, K> List<T> distinctByArgs(List<T> items, Function<? super T, ? extends K> classifier) {
|
||||
return items.stream()
|
||||
.collect(Collectors.groupingBy(classifier))
|
||||
.values().stream()
|
||||
.map(monitorItem -> monitorItem.iterator().next())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* list转map,保留新值 -> Map<String, User> userMap = items.stream().collect(Collectors.toMap(User::getName, user -> user)) <br>
|
||||
* list转map,保留旧值 -> Map<String, User> userMap = users.stream().collect(Collectors.toMap(User::getName, user -> user, (existing, replacement) -> existing));
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
List<MyEntity> entities = new ArrayList<>();
|
||||
for (int i = 0; i < 50; i++) {
|
||||
MyEntity entity = new MyEntity();
|
||||
if (i % 2 == 0) {
|
||||
entity.setCreateBy("odboy");
|
||||
} else {
|
||||
entity.setCreateBy("admin");
|
||||
}
|
||||
entity.setUpdateBy("admin");
|
||||
entity.setCreateTime(DateTime.now().toTimestamp());
|
||||
entity.setUpdateTime(DateTime.now().toTimestamp());
|
||||
entities.add(entity);
|
||||
}
|
||||
List<MyEntity> entities1 = ListUtil.distinctByArgs(entities, MyEntity::getCreateBy);
|
||||
System.err.println(entities1);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package cn.odboy.util;
|
||||
|
||||
import cn.odboy.base.PageResult;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 2021-2025 Tian Jun
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.odboy.util;
|
||||
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.hutool.script.ScriptRuntimeException;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.script.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 脚本工具
|
||||
*
|
||||
* @author odboy
|
||||
* @date 2023-12-05
|
||||
*/
|
||||
@Component
|
||||
public class ScriptUtil {
|
||||
private static final String FUNCTION_TAG = "function";
|
||||
private final ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
|
||||
|
||||
/**
|
||||
* @param script 函数表达式
|
||||
* @return 返回值
|
||||
*/
|
||||
public Object evalObj(String script, Object compareObj) {
|
||||
try {
|
||||
if (script.contains(FUNCTION_TAG)) {
|
||||
throw new RuntimeException("script格式异常");
|
||||
}
|
||||
// 构建一个不同的脚本上下文
|
||||
ScriptContext newContext = new SimpleScriptContext();
|
||||
if (compareObj != null) {
|
||||
Field[] fields = ReflectUtil.getFields(compareObj.getClass());
|
||||
Map<String, Object> filedNameValueMap = new HashMap<>();
|
||||
Arrays.stream(fields).parallel().forEach(f -> filedNameValueMap.put(f.getName(), ReflectUtil.getFieldValue(compareObj, f)));
|
||||
Set<Map.Entry<String, Object>> entries = filedNameValueMap.entrySet();
|
||||
long count = entries.stream().filter(f -> f.getValue() != null).count();
|
||||
if (count == 0) {
|
||||
throw new RuntimeException("比较对象中没有有效值");
|
||||
}
|
||||
Bindings engineScope = engine.createBindings();
|
||||
entries.forEach(f -> {
|
||||
// 在新的执行引擎作用域中添加与上面相同名称的变量
|
||||
engineScope.put(f.getKey(), f.getValue());
|
||||
});
|
||||
newContext.setBindings(engineScope, ScriptContext.ENGINE_SCOPE);
|
||||
}
|
||||
if (script.contains(FUNCTION_TAG)) {
|
||||
// 由ScriptEngines实现的接口, 其方法允许调用以前已执行的脚本中的过程
|
||||
Invocable inv = (Invocable) engine;
|
||||
// 调用全局函数, 并传入参数
|
||||
inv.invokeFunction("hello", "测试");
|
||||
}
|
||||
// 执行脚本, 注意这里指定新的执行作用域上下文
|
||||
return engine.eval(script, newContext);
|
||||
} catch (ScriptException e) {
|
||||
throw new ScriptRuntimeException(e);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new ScriptRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param script 函数表达式, 例如: function hello(name) { print('Hello, ' + name); }
|
||||
* @param functionName 函数名称, 例如: "hello"
|
||||
* @param args 函数参数, 例如: "小明"
|
||||
* @return 返回值
|
||||
*/
|
||||
public Object evalFunction(String script, String functionName, Object... args) {
|
||||
if (!script.contains(FUNCTION_TAG)) {
|
||||
throw new RuntimeException("script格式异常");
|
||||
}
|
||||
try {
|
||||
// 执行脚本
|
||||
engine.eval(script);
|
||||
// 由ScriptEngines实现的接口,其方法允许调用以前已执行的脚本中的过程。
|
||||
Invocable inv = (Invocable) engine;
|
||||
// 调用全局函数,并传入参数
|
||||
return inv.invokeFunction(functionName, args);
|
||||
} catch (ScriptException e) {
|
||||
throw new ScriptRuntimeException(e);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new ScriptRuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.jwt.JWT;
|
||||
import cn.hutool.jwt.JWTUtil;
|
||||
import cn.odboy.constant.DataScopeEnum;
|
||||
import cn.odboy.context.SpringBeanHolder;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.odboy.util;
|
||||
|
||||
import cn.odboy.mybatis.constant.DataTypeEnum;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author /
|
||||
*/
|
||||
@Slf4j
|
||||
public class SqlUtil {
|
||||
/**
|
||||
* 获取数据源
|
||||
*
|
||||
* @param jdbcUrl /
|
||||
* @param userName /
|
||||
* @param password /
|
||||
* @return DataSource
|
||||
*/
|
||||
private static DataSource getDataSource(String jdbcUrl, String userName, String password) {
|
||||
HikariDataSource druidDataSource = new HikariDataSource();
|
||||
String className;
|
||||
try {
|
||||
className = DriverManager.getDriver(jdbcUrl.trim()).getClass().getName();
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException("Get class name error: =" + jdbcUrl);
|
||||
}
|
||||
if (StringUtils.isEmpty(className)) {
|
||||
DataTypeEnum dataTypeEnum = DataTypeEnum.urlOf(jdbcUrl);
|
||||
if (null == dataTypeEnum) {
|
||||
throw new RuntimeException("Not supported data type: jdbcUrl=" + jdbcUrl);
|
||||
}
|
||||
druidDataSource.setDriverClassName(dataTypeEnum.getDriver());
|
||||
} else {
|
||||
druidDataSource.setDriverClassName(className);
|
||||
}
|
||||
druidDataSource.setJdbcUrl(jdbcUrl);
|
||||
druidDataSource.setUsername(userName);
|
||||
druidDataSource.setPassword(password);
|
||||
druidDataSource.setConnectionTimeout(3000);
|
||||
return druidDataSource;
|
||||
}
|
||||
|
||||
private static Connection getConnection(String jdbcUrl, String userName, String password) {
|
||||
DataSource dataSource = getDataSource(jdbcUrl, userName, password);
|
||||
Connection connection = null;
|
||||
try {
|
||||
connection = dataSource.getConnection();
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
try {
|
||||
int timeOut = 5;
|
||||
if (null == connection || connection.isClosed() || !connection.isValid(timeOut)) {
|
||||
log.info("connection is closed or invalid, retry get connection!");
|
||||
connection = dataSource.getConnection();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("create connection error, jdbcUrl: {}", jdbcUrl);
|
||||
throw new RuntimeException("create connection error, jdbcUrl: " + jdbcUrl);
|
||||
} finally {
|
||||
CloseUtil.close(connection);
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
|
||||
private static void releaseConnection(Connection connection) {
|
||||
if (null != connection) {
|
||||
try {
|
||||
connection.close();
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
log.error("connection close error:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean testConnection(String jdbcUrl, String userName, String password) {
|
||||
Connection connection = null;
|
||||
try {
|
||||
connection = getConnection(jdbcUrl, userName, password);
|
||||
if (null != connection) {
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.info("Get connection failed:" + e.getMessage());
|
||||
} finally {
|
||||
releaseConnection(connection);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String executeFile(String jdbcUrl, String userName, String password, File sqlFile) {
|
||||
Connection connection = getConnection(jdbcUrl, userName, password);
|
||||
try {
|
||||
batchExecute(connection, readSqlList(sqlFile));
|
||||
} catch (Exception e) {
|
||||
log.error("sql脚本执行发生异常:{}", e.getMessage());
|
||||
return e.getMessage();
|
||||
} finally {
|
||||
releaseConnection(connection);
|
||||
}
|
||||
return "success";
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量执行sql
|
||||
*
|
||||
* @param connection /
|
||||
* @param sqlList /
|
||||
*/
|
||||
public static void batchExecute(Connection connection, List<String> sqlList) {
|
||||
Statement st = null;
|
||||
try {
|
||||
st = connection.createStatement();
|
||||
for (String sql : sqlList) {
|
||||
if (sql.endsWith(";")) {
|
||||
sql = sql.substring(0, sql.length() - 1);
|
||||
}
|
||||
st.addBatch(sql);
|
||||
}
|
||||
st.executeBatch();
|
||||
} catch (SQLException throwables) {
|
||||
throwables.printStackTrace();
|
||||
} finally {
|
||||
CloseUtil.close(st);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将文件中的sql语句以;为单位读取到列表中
|
||||
*
|
||||
* @param sqlFile /
|
||||
* @return /
|
||||
* @throws Exception e
|
||||
*/
|
||||
private static List<String> readSqlList(File sqlFile) throws Exception {
|
||||
List<String> sqlList = Lists.newArrayList();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(
|
||||
Files.newInputStream(sqlFile.toPath()), StandardCharsets.UTF_8))) {
|
||||
String tmp;
|
||||
while ((tmp = reader.readLine()) != null) {
|
||||
log.info("line:{}", tmp);
|
||||
if (tmp.endsWith(";")) {
|
||||
sb.append(tmp);
|
||||
sqlList.add(sb.toString());
|
||||
sb.delete(0, sb.length());
|
||||
} else {
|
||||
sb.append(tmp);
|
||||
}
|
||||
}
|
||||
if (!"".endsWith(sb.toString().trim())) {
|
||||
sqlList.add(sb.toString());
|
||||
}
|
||||
}
|
||||
return sqlList;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package cn.odboy.util;
|
||||
|
||||
import cn.hutool.http.useragent.UserAgent;
|
||||
import cn.hutool.http.useragent.UserAgentUtil;
|
||||
import cn.odboy.context.SpringBeanHolder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dreamlu.mica.ip2region.core.Ip2regionSearcher;
|
||||
import net.dreamlu.mica.ip2region.core.IpInfo;
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2021-2025 Tian Jun
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.odboy.util;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.Validation;
|
||||
import javax.validation.Validator;
|
||||
import javax.validation.groups.Default;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Bean验证工具
|
||||
*
|
||||
* @author odboy
|
||||
* @date 2025-01-15
|
||||
*/
|
||||
public class ValidationUtil {
|
||||
private static final Validator VALIDATOR = Validation.buildDefaultValidatorFactory().getValidator();
|
||||
|
||||
public static <T> void validate(T object) {
|
||||
Set<ConstraintViolation<T>> violations = VALIDATOR.validate(object, Default.class);
|
||||
if (!violations.isEmpty()) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (ConstraintViolation<T> violation : violations) {
|
||||
sb.append(violation.getMessage()).append(", ");
|
||||
}
|
||||
throw new IllegalArgumentException(sb.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.config.webConfig;
|
||||
package cn.odboy.websocket;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.odboy.websocket;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author ZhangHouYing
|
||||
* @date 2019-08-10 9:55
|
||||
*/
|
||||
@Data
|
||||
public class WebSocketMsg {
|
||||
private String msg;
|
||||
private WebSocketMsgTypeEnum msgType;
|
||||
|
||||
public WebSocketMsg(String msg, WebSocketMsgTypeEnum msgType) {
|
||||
this.msg = msg;
|
||||
this.msgType = msgType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.odboy.websocket;
|
||||
|
||||
/**
|
||||
* @author ZhangHouYing
|
||||
* @date 2019-08-10 9:56
|
||||
*/
|
||||
public enum WebSocketMsgTypeEnum {
|
||||
/**
|
||||
* 连接
|
||||
*/
|
||||
CONNECT,
|
||||
/**
|
||||
* 关闭
|
||||
*/
|
||||
CLOSE,
|
||||
/**
|
||||
* 信息
|
||||
*/
|
||||
INFO,
|
||||
/**
|
||||
* 错误
|
||||
*/
|
||||
ERROR
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.odboy.websocket;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.websocket.*;
|
||||
import javax.websocket.server.PathParam;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @author ZhangHouYing
|
||||
* @date 2019-08-10 15:46
|
||||
*/
|
||||
@ServerEndpoint("/webSocket/{sid}")
|
||||
@Slf4j
|
||||
@Component
|
||||
public class WebSocketServer {
|
||||
/**
|
||||
* concurrent包的线程安全Map,用来存放每个客户端对应的MyWebSocket对象。(分布式必出问题)
|
||||
*/
|
||||
private static final Map<String, WebSocketServer> CLIENT = new ConcurrentHashMap<>();
|
||||
/**
|
||||
* 与某个客户端的连接会话,需要通过它来给客户端发送数据
|
||||
*/
|
||||
private Session session;
|
||||
/**
|
||||
* 接收sid
|
||||
*/
|
||||
private String sid = "";
|
||||
|
||||
/**
|
||||
* 连接建立成功调用的方法
|
||||
*/
|
||||
@OnOpen
|
||||
public void onOpen(Session session, @PathParam("sid") String sid) {
|
||||
this.session = session;
|
||||
// 如果存在就先删除一个,防止重复推送消息
|
||||
CLIENT.remove(sid);
|
||||
CLIENT.put(sid, this);
|
||||
this.sid = sid;
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接关闭调用的方法
|
||||
*/
|
||||
@OnClose
|
||||
public void onClose() {
|
||||
CLIENT.remove(this.sid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 收到客户端消息后调用的方法
|
||||
*
|
||||
* @param message 客户端发送过来的消息
|
||||
*/
|
||||
@OnMessage
|
||||
public void onMessage(String message, Session session) {
|
||||
log.info("收到来{}的信息:{}", sid, message);
|
||||
sendToAll(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 群发消息
|
||||
*
|
||||
* @param message /
|
||||
*/
|
||||
private static void sendToAll(String message) {
|
||||
//
|
||||
for (WebSocketServer item : CLIENT.values()) {
|
||||
try {
|
||||
item.sendMessage(message);
|
||||
} catch (IOException e) {
|
||||
log.error("发送消息给{}失败", item.sid, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OnError
|
||||
public void onError(Session session, Throwable error) {
|
||||
log.error("发生错误");
|
||||
error.printStackTrace();
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现服务器主动推送
|
||||
*/
|
||||
private void sendMessage(String message) throws IOException {
|
||||
this.session.getBasicRemote().sendText(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 群发自定义消息
|
||||
*/
|
||||
public static void sendInfo(WebSocketMsg webSocketMsg, @PathParam("sid") String sid) throws IOException {
|
||||
String message = JSON.toJSONString(webSocketMsg);
|
||||
log.info("推送消息到{},推送内容:{}", sid, message);
|
||||
try {
|
||||
if (sid == null) {
|
||||
sendToAll(message);
|
||||
} else {
|
||||
CLIENT.get(sid).sendMessage(message);
|
||||
}
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
WebSocketServer that = (WebSocketServer) o;
|
||||
return Objects.equals(session, that.session) &&
|
||||
Objects.equals(sid, that.sid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(session, sid);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package cn.odboy.websocket;
|
||||
|
||||
import io.undertow.server.DefaultByteBufferPool;
|
||||
import io.undertow.websockets.jsr.WebSocketDeploymentInfo;
|
||||
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
|
||||
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 解决启动io.undertow.websockets.jsr UT026010: Buffer pool was not
|
||||
* set on WebSocketDeploymentInfo, the default pool will be used的警告
|
||||
*
|
||||
* @date 2024-06-07
|
||||
*/
|
||||
@Component
|
||||
public class WebSocketServerFactory implements WebServerFactoryCustomizer<UndertowServletWebServerFactory> {
|
||||
|
||||
@Override
|
||||
public void customize(UndertowServletWebServerFactory factory) {
|
||||
factory.addDeploymentInfoCustomizers(deploymentInfo -> {
|
||||
WebSocketDeploymentInfo webSocketDeploymentInfo = new WebSocketDeploymentInfo();
|
||||
webSocketDeploymentInfo.setBuffers(
|
||||
new DefaultByteBufferPool(false, 1024)
|
||||
// new DefaultByteBufferPool(false, 1024,20,4)
|
||||
);
|
||||
deploymentInfo.addServletContextAttribute("io.undertow.websockets.jsr.WebSocketDeploymentInfo", webSocketDeploymentInfo);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>cutejava</artifactId>
|
||||
<groupId>cn.odboy</groupId>
|
||||
<version>1.3.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<properties>
|
||||
<hutool.version>5.8.36</hutool.version>
|
||||
</properties>
|
||||
|
||||
<artifactId>cutejava-domain</artifactId>
|
||||
<name>模型模块</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.odboy</groupId>
|
||||
<artifactId>cutejava-common</artifactId>
|
||||
<version>1.3.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
package cn.odboy.domain;
|
||||
package cn.odboy.model.job.domain;
|
||||
|
||||
import cn.odboy.base.BaseEntity;
|
||||
import cn.odboy.base.MyEntity;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
@@ -16,11 +16,11 @@ import javax.validation.constraints.NotNull;
|
||||
@Getter
|
||||
@Setter
|
||||
@TableName("sys_quartz_job")
|
||||
public class QuartzJob extends BaseEntity {
|
||||
public class QuartzJob extends MyEntity {
|
||||
|
||||
public static final String JOB_KEY = "JOB_KEY";
|
||||
|
||||
@TableId(value = "job_id", type = IdType.AUTO)
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
@NotNull(groups = {Update.class})
|
||||
private Long id;
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.domain;
|
||||
package cn.odboy.model.job.domain;
|
||||
|
||||
import cn.odboy.base.MyObject;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
@@ -15,7 +15,7 @@ public class QuartzLog extends MyObject {
|
||||
|
||||
@TableId(value = "log_id", type = IdType.AUTO)
|
||||
@ApiModelProperty(value = "ID", hidden = true)
|
||||
private Long id;
|
||||
private Long logId;
|
||||
|
||||
@ApiModelProperty(value = "任务名称", hidden = true)
|
||||
private String jobName;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.domain.dto;
|
||||
package cn.odboy.model.job.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
package cn.odboy.modules.system.domain;
|
||||
package cn.odboy.model.system.domain;
|
||||
|
||||
import cn.odboy.base.BaseEntity;
|
||||
import cn.odboy.base.MyEntity;
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
@@ -19,7 +19,7 @@ import java.util.Set;
|
||||
@Getter
|
||||
@Setter
|
||||
@TableName("sys_dept")
|
||||
public class Dept extends BaseEntity {
|
||||
public class Dept extends MyEntity {
|
||||
|
||||
@NotNull(groups = Update.class)
|
||||
@TableId(value = "dept_id", type = IdType.AUTO)
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
package cn.odboy.modules.system.domain;
|
||||
package cn.odboy.model.system.domain;
|
||||
|
||||
import cn.odboy.base.BaseEntity;
|
||||
import cn.odboy.base.MyEntity;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
@@ -15,7 +15,7 @@ import javax.validation.constraints.NotNull;
|
||||
@Getter
|
||||
@Setter
|
||||
@TableName("sys_dict")
|
||||
public class Dict extends BaseEntity {
|
||||
public class Dict extends MyEntity {
|
||||
|
||||
@NotNull(groups = Update.class)
|
||||
@ApiModelProperty(value = "ID", hidden = true)
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
package cn.odboy.modules.system.domain;
|
||||
package cn.odboy.model.system.domain;
|
||||
|
||||
import cn.odboy.base.BaseEntity;
|
||||
import cn.odboy.base.MyEntity;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
@@ -14,7 +14,7 @@ import javax.validation.constraints.NotNull;
|
||||
@Getter
|
||||
@Setter
|
||||
@TableName("sys_dict_detail")
|
||||
public class DictDetail extends BaseEntity {
|
||||
public class DictDetail extends MyEntity {
|
||||
|
||||
@NotNull(groups = Update.class)
|
||||
@ApiModelProperty(value = "ID", hidden = true)
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
package cn.odboy.modules.system.domain;
|
||||
package cn.odboy.model.system.domain;
|
||||
|
||||
import cn.odboy.base.BaseEntity;
|
||||
import cn.odboy.base.MyEntity;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
@@ -16,10 +16,10 @@ import java.util.Objects;
|
||||
@Getter
|
||||
@Setter
|
||||
@TableName("sys_job")
|
||||
public class Job extends BaseEntity {
|
||||
public class Job extends MyEntity {
|
||||
|
||||
@NotNull(groups = Update.class)
|
||||
@TableId(value = "job_id", type = IdType.AUTO)
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
@ApiModelProperty(value = "ID", hidden = true)
|
||||
private Long id;
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
package cn.odboy.modules.system.domain;
|
||||
package cn.odboy.model.system.domain;
|
||||
|
||||
import cn.odboy.base.BaseEntity;
|
||||
import cn.odboy.base.MyEntity;
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
@@ -18,7 +18,7 @@ import java.util.Set;
|
||||
@Getter
|
||||
@Setter
|
||||
@TableName("sys_menu")
|
||||
public class Menu extends BaseEntity {
|
||||
public class Menu extends MyEntity {
|
||||
|
||||
@NotNull(groups = {Update.class})
|
||||
@TableId(value = "menu_id", type = IdType.AUTO)
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
package cn.odboy.modules.system.domain;
|
||||
package cn.odboy.model.system.domain;
|
||||
|
||||
import cn.odboy.base.BaseEntity;
|
||||
import cn.odboy.base.MyEntity;
|
||||
import cn.odboy.constant.DataScopeEnum;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
@@ -21,7 +21,7 @@ import java.util.Set;
|
||||
@Getter
|
||||
@Setter
|
||||
@TableName("sys_role")
|
||||
public class Role extends BaseEntity {
|
||||
public class Role extends MyEntity {
|
||||
|
||||
@NotNull(groups = {Update.class})
|
||||
@TableId(value = "role_id", type = IdType.AUTO)
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
package cn.odboy.modules.system.domain;
|
||||
package cn.odboy.model.system.domain;
|
||||
|
||||
import cn.odboy.base.BaseEntity;
|
||||
import cn.odboy.base.MyEntity;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
@@ -19,7 +19,7 @@ import java.util.Set;
|
||||
@Getter
|
||||
@Setter
|
||||
@TableName("sys_user")
|
||||
public class User extends BaseEntity {
|
||||
public class User extends MyEntity {
|
||||
|
||||
@NotNull(groups = Update.class)
|
||||
@TableId(value = "user_id", type = IdType.AUTO)
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.modules.security.service.dto;
|
||||
package cn.odboy.model.system.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Getter;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.modules.security.service.dto;
|
||||
package cn.odboy.model.system.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.modules.system.domain.dto;
|
||||
package cn.odboy.model.system.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.modules.system.domain.dto;
|
||||
package cn.odboy.model.system.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.modules.system.domain.dto;
|
||||
package cn.odboy.model.system.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.modules.system.domain.dto;
|
||||
package cn.odboy.model.system.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
package cn.odboy.modules.security.service.dto;
|
||||
package cn.odboy.model.system.dto;
|
||||
|
||||
import cn.odboy.modules.system.domain.User;
|
||||
import cn.odboy.model.system.domain.User;
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.modules.system.domain.dto;
|
||||
package cn.odboy.model.system.dto;
|
||||
|
||||
import cn.odboy.base.MyObject;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.modules.system.domain.dto;
|
||||
package cn.odboy.model.system.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.modules.system.domain.dto;
|
||||
package cn.odboy.model.system.dto;
|
||||
|
||||
import cn.odboy.base.MyObject;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.modules.security.service.dto;
|
||||
package cn.odboy.model.system.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.modules.system.domain.dto;
|
||||
package cn.odboy.model.system.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.modules.system.domain.dto;
|
||||
package cn.odboy.model.system.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.modules.system.domain.dto;
|
||||
package cn.odboy.model.system.dto;
|
||||
|
||||
import cn.odboy.base.MyObject;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.domain;
|
||||
package cn.odboy.model.tools.domain;
|
||||
|
||||
import cn.odboy.base.MyObject;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
package cn.odboy.domain;
|
||||
package cn.odboy.model.tools.domain;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.bean.copier.CopyOptions;
|
||||
import cn.odboy.base.BaseEntity;
|
||||
import cn.odboy.base.MyEntity;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
@@ -15,7 +15,7 @@ import lombok.Setter;
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@TableName("tool_local_storage")
|
||||
public class LocalStorage extends BaseEntity {
|
||||
public class LocalStorage extends MyEntity {
|
||||
|
||||
@TableId(value = "storage_id", type = IdType.AUTO)
|
||||
@ApiModelProperty(value = "ID", hidden = true)
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.domain;
|
||||
package cn.odboy.model.tools.domain;
|
||||
|
||||
import cn.odboy.base.MyObject;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.domain;
|
||||
package cn.odboy.model.tools.domain;
|
||||
|
||||
import cn.odboy.base.MyObject;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.domain.dto;
|
||||
package cn.odboy.model.tools.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.domain.dto;
|
||||
package cn.odboy.model.tools.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package cn.odboy.domain.dto;
|
||||
package cn.odboy.model.tools.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
@@ -1,7 +1,7 @@
|
||||
package cn.odboy.config;
|
||||
|
||||
import cn.odboy.mapper.QuartzJobMapper;
|
||||
import cn.odboy.domain.QuartzJob;
|
||||
import cn.odboy.model.job.domain.QuartzJob;
|
||||
import cn.odboy.util.QuartzManage;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package cn.odboy.mapper;
|
||||
|
||||
import cn.odboy.domain.dto.QuartzJobQueryCriteria;
|
||||
import cn.odboy.domain.QuartzJob;
|
||||
import cn.odboy.model.job.domain.QuartzJob;
|
||||
import cn.odboy.model.job.dto.QuartzJobQueryCriteria;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package cn.odboy.mapper;
|
||||
|
||||
import cn.odboy.domain.dto.QuartzJobQueryCriteria;
|
||||
import cn.odboy.domain.QuartzLog;
|
||||
import cn.odboy.model.job.domain.QuartzLog;
|
||||
import cn.odboy.model.job.dto.QuartzJobQueryCriteria;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package cn.odboy.rest;
|
||||
|
||||
import cn.odboy.domain.QuartzJob;
|
||||
import cn.odboy.domain.QuartzLog;
|
||||
import cn.odboy.domain.dto.QuartzJobQueryCriteria;
|
||||
import cn.odboy.base.PageResult;
|
||||
import cn.odboy.exception.BadRequestException;
|
||||
import cn.odboy.model.job.domain.QuartzJob;
|
||||
import cn.odboy.model.job.domain.QuartzLog;
|
||||
import cn.odboy.model.job.dto.QuartzJobQueryCriteria;
|
||||
import cn.odboy.service.QuartzJobService;
|
||||
import cn.odboy.util.PageResult;
|
||||
import cn.odboy.util.SpringBeanHolder;
|
||||
import cn.odboy.context.SpringBeanHolder;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package cn.odboy.service;
|
||||
|
||||
import cn.odboy.domain.dto.QuartzJobQueryCriteria;
|
||||
import cn.odboy.domain.QuartzJob;
|
||||
import cn.odboy.domain.QuartzLog;
|
||||
import cn.odboy.util.PageResult;
|
||||
import cn.odboy.base.PageResult;
|
||||
import cn.odboy.model.job.domain.QuartzJob;
|
||||
import cn.odboy.model.job.domain.QuartzLog;
|
||||
import cn.odboy.model.job.dto.QuartzJobQueryCriteria;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
|
||||
@@ -2,12 +2,13 @@ package cn.odboy.service.impl;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.odboy.domain.dto.QuartzJobQueryCriteria;
|
||||
import cn.odboy.base.PageResult;
|
||||
import cn.odboy.exception.BadRequestException;
|
||||
import cn.odboy.mapper.QuartzJobMapper;
|
||||
import cn.odboy.mapper.QuartzLogMapper;
|
||||
import cn.odboy.domain.QuartzJob;
|
||||
import cn.odboy.domain.QuartzLog;
|
||||
import cn.odboy.model.job.domain.QuartzJob;
|
||||
import cn.odboy.model.job.domain.QuartzLog;
|
||||
import cn.odboy.model.job.dto.QuartzJobQueryCriteria;
|
||||
import cn.odboy.service.QuartzJobService;
|
||||
import cn.odboy.util.*;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
|
||||
@@ -4,16 +4,14 @@ import cn.hutool.extra.template.Template;
|
||||
import cn.hutool.extra.template.TemplateConfig;
|
||||
import cn.hutool.extra.template.TemplateEngine;
|
||||
import cn.hutool.extra.template.TemplateUtil;
|
||||
import cn.odboy.domain.dto.EmailDto;
|
||||
import cn.odboy.context.SpringBeanHolder;
|
||||
import cn.odboy.exception.util.ThrowableUtil;
|
||||
import cn.odboy.mapper.QuartzLogMapper;
|
||||
import cn.odboy.domain.QuartzJob;
|
||||
import cn.odboy.domain.QuartzLog;
|
||||
import cn.odboy.service.QuartzJobService;
|
||||
import cn.odboy.model.job.domain.QuartzJob;
|
||||
import cn.odboy.model.job.domain.QuartzLog;
|
||||
import cn.odboy.model.tools.dto.EmailDto;
|
||||
import cn.odboy.service.EmailService;
|
||||
import cn.odboy.util.RedisUtil;
|
||||
import cn.odboy.util.SpringBeanHolder;
|
||||
import cn.odboy.util.StringUtil;
|
||||
import cn.odboy.util.ThrowableUtil;
|
||||
import cn.odboy.service.QuartzJobService;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -27,9 +25,7 @@ import java.util.Map;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class ExecutionJob extends QuartzJobBean {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
// 此处仅供参考,可根据任务执行情况自定义线程池参数
|
||||
private final ThreadPoolTaskExecutor executor = SpringBeanHolder.getBean("taskAsync");
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package cn.odboy.util;
|
||||
|
||||
import cn.odboy.exception.BadRequestException;
|
||||
import cn.odboy.domain.QuartzJob;
|
||||
import cn.odboy.model.job.domain.QuartzJob;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.quartz.*;
|
||||
import org.quartz.impl.triggers.CronTriggerImpl;
|
||||
@@ -10,8 +10,6 @@ import org.springframework.stereotype.Component;
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Date;
|
||||
|
||||
import static org.quartz.TriggerBuilder.newTrigger;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class QuartzManage {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package cn.odboy.util;
|
||||
|
||||
import cn.odboy.util.SpringBeanHolder;
|
||||
import cn.odboy.context.SpringBeanHolder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user