diff --git a/java/jdk8/Lambda.md b/java/jdk8/Lambda.md new file mode 100644 index 0000000..4adf353 --- /dev/null +++ b/java/jdk8/Lambda.md @@ -0,0 +1,124 @@ +## Lambda 表达式-函数式编程 + +#### 介绍 + ++ 只有是函数式的接口才可以使用lambda表达式 ++ 接口中有且只有一个抽象方法的接口称为函数式接口 ++ @FunctionalInterface 注解强制检测是否为函数式接口 + +#### 用法 + ++ 无参数,无返回值:()-> 具体实现 ++ 有一个参数,无返回值:(x)-> 具体实现 ++ 若只有一个参数,小括号可以省略不写:x -> 具体实现 ++ 若有多个参数,多条语句,加个大括号就行了:(x,y)-> { 具体实现 } ++ 若 lambda 中只有一条语句,return 和大括号都可以省略不写,如`Comparatorcom = (x,y) -> Integer.compare(x,y)` + +#### 四大内置函数式接口 + +| 接口 | 语法 | +| :----------------------: | :---------------: | +| Consumer 消费型接口 | void accept(T t) | +| Supplier 供给型接口 | T get() | +| Function 函数型接口 | R apply(T t) | +| Predicate 断言型接口 | boolean test(T t) | + ++ ##### Consumer + + + ##### 实例 + + ```java + String name = "大山"; + private void consumer(Consumer consumer){ + consumer.accept(name); + } + + @Test + public void test1(){ + consumer((name)-> System.out.println("我的名字:"+name)); + // 若只有一个参数,小括号可以省略不写:x -> 具体实现 + consumer(name-> System.out.println("他的名字:"+name)); + } + ``` + + + ##### 输出内容 + + ``` + 我的名字:大山 + 他的名字:大山 + ``` + ++ ##### Supplier + + + ##### 实例 + + ```java + private void supplier(Supplier supplier){ + System.out.println("今日生产数量:"+supplier.get()); + } + + @Test + public void test2(){ + supplier(()-> {return 123;}); + // 若 lambda 中只有一条语句,return 和大括号都可以省略不写,如`Comparatorcom = (x,y) -> Integer.compare(x,y)` + supplier(()-> 150); + } + ``` + + + ##### 输出内容 + + ```sh + 今日生产数量:123 + 今日生产数量:150 + ``` + + + ++ ##### Function + + + ##### 实例 + + ```java + private void function(String num,Function function){ + System.out.println("生产数量:"+(function.apply(num)+100)); + } + + @Test + public void test3(){ + function("200",num-> Integer.parseInt(num)); + } + ``` + + + ##### 输出内容 + + ``` + 生产数量:300 + 生产数量:120 + ``` + + + ++ ##### Predicate + + + 实例 + + ```java + private void predicate(Integer age,Predicate predicate){ + System.out.println("我今年成年了吗:"+predicate.test(age)); + } + + @Test + public void test4(){ + predicate(15,age->age>=18); + predicate(23,age->age>=18); + } + ``` + + + ##### 输出内容 + + ``` + 我今年成年了吗:false + 我今年成年了吗:true + ``` + + \ No newline at end of file diff --git a/java/jdk8/LocalDate.md b/java/jdk8/LocalDate.md new file mode 100644 index 0000000..e69de29 diff --git a/java/jdk8/Optional.md b/java/jdk8/Optional.md new file mode 100644 index 0000000..e69de29 diff --git a/java/jdk8/Stream.md b/java/jdk8/Stream.md new file mode 100644 index 0000000..e69de29 diff --git a/java/jdk8/方法引用.md b/java/jdk8/方法引用.md new file mode 100644 index 0000000..c96da45 --- /dev/null +++ b/java/jdk8/方法引用.md @@ -0,0 +1,102 @@ +## 方法引用 + +#### 介绍 + ++ 若 **lambda体** 中的内容有方法已经实现了,我们可以使用 “方法引用” (可以理解为方法引用是 lambda 表达式的另外一种表现形式) + +#### 用法 + ++ 通过对象名引用成员方法 对象 :: 成员方法名 ++ 通过类名访问静态方法 类 :: 静态方法名 ++ 通过super调用父类的成员方法 super :: 成员方法名 ++ 通过this调用本类的成员方法 this :: 成员方法名 ++ 构造器引用 类名 :: new ++ 数组引用 Type[] :: new + +#### 实例 + ++ ##### 对象 :: 成员方法名 + + + ##### 实例 + + ```java + + ``` + + + ##### 输出内容 + + ``` + + ``` + + + ++ ##### 类 :: 静态方法名 + + + ##### 实例 + + ```java + + ``` + + + ##### 输出内容 + + ``` + + ``` + ++ ##### super :: 成员方法名 + + + ##### 实例 + + ```java + + ``` + + + ##### 输出内容 + + ``` + + ``` + ++ ##### this :: 成员方法名 + + + ##### 实例 + + ```java + + ``` + + + ##### 输出内容 + + ``` + + ``` + ++ ##### 类名 :: new + + + ##### 实例 + + ```java + + ``` + + + ##### 输出内容 + + ``` + + ``` + ++ ##### Type[] :: new + + + ##### 实例 + + ```java + + ``` + + + ##### 输出内容 + + ``` + + ``` \ No newline at end of file diff --git a/java/工具类/JAVA常用工具类.md b/java/工具类/JAVA常用工具类.md new file mode 100644 index 0000000..2846bf4 --- /dev/null +++ b/java/工具类/JAVA常用工具类.md @@ -0,0 +1,299 @@ +## JAVA常用工具类 + +#### HttpRequestUtil + +##### 作用:对HttpReuquest对象进行操作的工具类 + +```java +public class HttpRequestUtil { + + /** + * 获取请求IP地址 + */ + public static String getIpAddr(HttpServletRequest request) throws IOException { + // 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址 + + String ip = request.getHeader("X-Forwarded-For"); + + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_CLIENT_IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_X_FORWARDED_FOR"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + } else if (ip.length() > 15) { + String[] ips = ip.split(","); + for (int index = 0; index < ips.length; index++) { + String strIp = (String) ips[index]; + if (!("unknown".equalsIgnoreCase(strIp))) { + ip = strIp; + break; + } + } + } + return ip; + } + + /** + * 获取代理信息 + */ + public static String getAgent(HttpServletRequest request){ + return request.getHeader("user-agent"); + } +} +``` + + + +#### Base64ToMultipartFile + +##### 作用:实现了MultipartFile接口 可以接受Base64编码后的文件 + +```java +/** + * @author dss + * @since 2022/8/8 + */ +public class Base64ToMultipartFile implements MultipartFile { + private final byte[] fileContent; + + private final String extension; + private final String contentType; + private final String name; + + private final String id = "file_"+ UUID.randomUUID().toString(); + + + public Base64ToMultipartFile(String base64,String name) { + if (base64==null) throw new MyException(RestResponse.MSG.UPLOAD_EXCEPTION).setMsg("文件解析失败"); + String[] split = base64.split(","); + + if (split==null||split.length!=2) throw new MyException(RestResponse.MSG.UPLOAD_EXCEPTION).setMsg("文件解析失败"); + String uri = split[0]; + String data = split[1]; + try { + this.fileContent = Base64.getDecoder().decode(data.getBytes(StandardCharsets.UTF_8)); + }catch (IllegalArgumentException e){ + throw new MyException(RestResponse.MSG.UPLOAD_EXCEPTION).setMsg("文件解析失败"); + } + this.extension = uri.split(";")[0].split("/")[1]; + this.contentType = uri.split(";")[0].split(":")[1]; + this.name=name; + } + + /** + * @param base64 + * @param dataUri 格式类似于: data:image/png;base64 + * @param name + */ + public Base64ToMultipartFile(String base64, String dataUri, String name) { + try { + this.fileContent = Base64.getDecoder().decode(base64.getBytes(StandardCharsets.UTF_8)); + }catch (IllegalArgumentException e){ + throw new MyException(RestResponse.MSG.UPLOAD_EXCEPTION).setMsg("文件解析失败"); + } + this.extension = dataUri.split(";")[0].split("/")[1]; + this.contentType = dataUri.split(";")[0].split(":")[1]; + this.name = name; + } + + public Base64ToMultipartFile(String base64, String extension, String contentType, String name) { + try { + this.fileContent = Base64.getDecoder().decode(base64.getBytes(StandardCharsets.UTF_8)); + }catch (IllegalArgumentException e){ + throw new MyException(RestResponse.MSG.UPLOAD_EXCEPTION).setMsg("文件解析失败"); + } + this.extension = extension; + this.contentType = contentType; + this.name = name; + } + + @Override + public String getName() { + if (name==null){ + return id; + } + return name; + } + + @Override + public String getOriginalFilename() { + if (name==null){ + return id + "." + extension; + } + return name+"."+extension; + } + + @Override + public String getContentType() { + return contentType; + } + + @Override + public boolean isEmpty() { + return fileContent == null || fileContent.length == 0; + } + + @Override + public long getSize() { + return fileContent.length; + } + + @Override + public byte[] getBytes() throws IOException { + return fileContent; + } + + @Override + public ByteArrayInputStream getInputStream() throws IOException { + return new ByteArrayInputStream(fileContent); + } + + @Override + public void transferTo(File file) throws IOException, IllegalStateException { + try (FileOutputStream fos = new FileOutputStream(file)) { + fos.write(fileContent); + } + } + + + /** + * 实列 + */ + public static void main(String[] args) { + StringBuilder s = new StringBuilder("data:image/png;base64,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"); + + Base64ToMultipartFile base64ToMultipartFile = new Base64ToMultipartFile(s.toString(),null); + + System.out.println(base64ToMultipartFile.getOriginalFilename()); + } +} +``` + + + +#### SpringContextUtil + +##### 作用:使用静态方法从Spring容器中获取Bean对象 + +```java +@Component +public class SpringContextUtil implements ApplicationContextAware { + private static ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + SpringContextUtil.applicationContext = applicationContext; + } + + //获取applicationContext + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + //通过name获取 Bean. + public static Object getBean(String name) { + return getApplicationContext().getBean(name); + } + + //通过class获取Bean. + public static T getBean(Class clazz) { + return getApplicationContext().getBean(clazz); + } + + //通过name,以及Clazz返回指定的Bean + public static T getBean(String name, Class clazz) { + return getApplicationContext().getBean(name, clazz); + } +} +``` + +#### TransactionUtil + +##### 作用:手动事务控制 + +```java +@Component +@Scope("prototype") +public class TransactionUtils { + private TransactionStatus status; + + private final DataSourceTransactionManager dataSourceTransactionManager; + + public TransactionUtils(DataSourceTransactionManager dataSourceTransactionManager){ + + this.dataSourceTransactionManager = dataSourceTransactionManager; + } + + //开始事务 + public TransactionStatus begin() { + + status = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute()); + return status; + } + //提交事务 + public void commit(TransactionStatus transaction) { + dataSourceTransactionManager.commit(transaction); + } + //回滚事务 + public void rollback() { + dataSourceTransactionManager.rollback(status); + } +} +``` + +#### ReflectionUtils + +##### 作用:通过反射获取某个类的所有属性 + +```java +public class ReflectionUtils { + + /** + * 获取某个一个类所有的属性(包括所有父类) + * @param clazz 目标类 + * @return 所有属性集合 + */ + public static List reflectForField(Class clazz) { + Class tmpClazz = clazz; + List fieldList = new ArrayList<>(); + while (tmpClazz != null) { + if (tmpClazz.equals(Object.class)) { + tmpClazz = tmpClazz.getSuperclass(); + continue; + } + fieldList.addAll(new ArrayList<>(Arrays.asList(tmpClazz.getDeclaredFields()))); + tmpClazz = tmpClazz.getSuperclass(); + } + return fieldList; + } + + /** + * 获取某个类的某个属性(包括父类) + * @param clazz 目标类 + * @param filedName 属性名称 + * @return 属性 + */ + public static Field getDeclaredField(Class clazz,String filedName){ + List fieldList = reflectForField(clazz); + + for (int i = 0; i < fieldList.size(); i++) { + if (fieldList.get(i).getName().equals(filedName)){ + return fieldList.get(i); + } + } + return null; + } +} +``` + diff --git a/java/Java 通过反射获取枚举对象.md b/java/工具类/Java 通过反射获取枚举对象.md similarity index 100% rename from java/Java 通过反射获取枚举对象.md rename to java/工具类/Java 通过反射获取枚举对象.md diff --git a/java/工具类/Validation工具类.md b/java/工具类/Validation工具类.md new file mode 100644 index 0000000..361ef20 --- /dev/null +++ b/java/工具类/Validation工具类.md @@ -0,0 +1,52 @@ +## JAVAX Validation工具类 + +##### 手动对对象进行验证 + +```java +/** + * @author dss + * @since 2022/7/6 + */ +public class ValidationUtil { + /** + * 开启快速结束模式 failFast (true) + */ + private static final Validator validator = Validation.byProvider(HibernateValidator.class).configure().failFast(false).buildValidatorFactory().getValidator(); + /** + * 校验对象 + * + * @param t bean + * @param groups 校验组 + * @return ValidResult + */ + public static void validateBean(T t,Class...groups) { + if (t==null) throw new MyException(RestResponse.MSG.PARAM_VALIDATION_FAILURE); + Set> violationSet = validator.validate(t,groups); + boolean hasError = violationSet != null && !violationSet.isEmpty(); + //存在验证错误直接抛出异常 + if (hasError){ + for (ConstraintViolation violation : violationSet) { + throw new MyException(RestResponse.MSG.PARAM_VALIDATION_FAILURE).setMsg(violation.getMessage()); + } + } + + } + /** + * 校验bean的某一个属性 + * + * @param obj bean + * @param propertyName 属性名称 + * @return ValidResult + */ + public static void validateProperty(T obj, String propertyName) { + Set> violationSet = validator.validateProperty(obj, propertyName); + boolean hasError = violationSet != null && !violationSet.isEmpty(); + //存在验证错误直接抛出异常 + if (hasError){ + for (ConstraintViolation violation : violationSet) { + throw new MyException(RestResponse.MSG.PARAM_VALIDATION_FAILURE).setMsg(violation.getMessage()); + } + } + } +} +``` \ No newline at end of file diff --git a/java/工具类/枚举工具类.md b/java/工具类/枚举工具类.md new file mode 100644 index 0000000..dc1bc39 --- /dev/null +++ b/java/工具类/枚举工具类.md @@ -0,0 +1,198 @@ +## 枚举工具类 + +#### EnumCodeService + +##### 作用:枚举Service 对实现此接口的枚举实现序列化以及其他功能 + +```java +@JsonDeserialize(using = EnumCodeDeserializer.class) //jackson注解 +@JsonSerialize(using = EnumCodeSerializer.class) //jackson注解 +public interface EnumCodeService { + /** + * 获取状态吗 + * @return + */ + Integer getCode(); + + /** + * 获取Name + * @return + */ + String getName(); +} +``` + + + +#### EnumCodeUtil + +##### 作用:枚举工具类 + +```java +public class EnumCodeUtil { + public static & EnumCodeService> E manageCode(Class enumClass, int code) { + E[] enumConstants = enumClass.getEnumConstants(); + for (E e : enumConstants) { + if (e.getCode() == code) { + return e; + } + } + return null; + } + + public static & EnumCodeService> E convert(Class enumClass, String str) { + E[] enumConstants = enumClass.getEnumConstants(); + for (E e : enumConstants) { + if (e.toString() .equals(str.toUpperCase()) ||e.getName().equals(str.toLowerCase()) || String.valueOf(e.getCode()).equals(str)) { + return e; + } + } + throw new CommonException(enumClass.getName()+"枚举不存在"); + } + + public static List> enumToListMap(Class clazz) { + List> resultList = null; + // 判断是否是枚举类型 + if ("java.lang.Enum".equals(clazz.getSuperclass().getCanonicalName())) { + resultList = new ArrayList<>(); + // 获取所有public方法 + Method[] methods = clazz.getMethods(); + List fieldList = new ArrayList<>(); + for (int i = 0; i < methods.length; i++) { + String methodName = methods[i].getName(); + + // 找到枚举类中的以get开头的(并且不是父类已定义的方法)所有方法 + if (methodName.startsWith("get") && !"getDeclaringClass".equals(methodName) + && !"getClass".equals(methodName)) { + Field field = null; + try { + // 通过方法名获取自定义字段 + field = clazz.getDeclaredField(StringUtils.uncapitalize(methodName.substring(3))); + } catch (NoSuchFieldException | SecurityException e) { + e.printStackTrace(); + } + // 如果不为空则添加到fieldList集合中 + if (field != null) { + fieldList.add(field); + } + } + } + // 判断fieldList集合是否为空 + if (!fieldList.isEmpty()) { + Map map = null; + // 获取所有枚举 + Enum[] enums = (Enum[])clazz.getEnumConstants(); + for (int i = 0; i < enums.length; i++) { + map = new HashMap<>(); + for (int l = 0, len = fieldList.size(); l < len; l++) { + Field field = fieldList.get(l); + field.setAccessible(true); + try { + //如果字段名称等于则跳过 非必要判断可不写 + if (field.getName().equals("cls")){ + continue; + } + // 向map集合添加字段名称 和 字段值 + map.put(field.getName(), field.get(enums[i])); + } catch (IllegalArgumentException | IllegalAccessException e) { + e.printStackTrace(); + } + } + map.put("enumValue",enums[i].toString()); + // 将Map添加到集合中 + resultList.add(map); + } + } + } + return resultList; + } +} +``` + + + +#### EnumCodeSerializer + +##### 作用:基于jackson实现枚举序列化规则 + +```java +public class EnumCodeSerializer extends JsonSerializer { + @Override + public void serialize(T t, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + jsonGenerator.writeString(t.getCode().toString()); + } +} +``` + + + +#### EnumCodeDeserializer + +##### 作用:基于jackson实现枚举反序列化规则 + +```java +@Slf4j +public class EnumCodeDeserializer extends JsonDeserializer { + @Override + public E deserialize( + JsonParser jsonParser, + DeserializationContext deserializationContext + ) throws IOException { + Class c = jsonParser.getCurrentValue().getClass(); + Field declaredField = ReflectionUtils.getDeclaredField(c,jsonParser.getCurrentName()); + Class type = (Class) declaredField.getType(); + if (NullUtils.isNotEmptyString(jsonParser.getValueAsString())){ + return (E) EnumCodeUtil.convert(type, jsonParser.getValueAsString()); + }else{ + return null; + } + } +} + +``` + + + +#### EnumTypeHandler + +##### 作用:基于mybatis框架实现对实现了EnumService的枚举,进行数据库和服务器之间的序列化和反序列化 + +```java +public class EnumTypeHandler & EnumCodeService> extends BaseTypeHandler { + + private Class type; + + public EnumTypeHandler(){ + + } + + public EnumTypeHandler(Class type) { + if (type == null) { + throw new IllegalArgumentException("Type argument cannot be null"); + } else { + this.type = type; + } + } + + @Override + public void setNonNullParameter(PreparedStatement preparedStatement, int i, EnumCodeService enumCode, JdbcType jdbcType) throws SQLException { + preparedStatement.setInt(i, enumCode.getCode()); + } + + @Override + public EnumCodeService getNullableResult(ResultSet resultSet, String s) throws SQLException { + return EnumCodeUtil.manageCode(type, resultSet.getInt(s)); + } + + @Override + public EnumCodeService getNullableResult(ResultSet resultSet, int i) throws SQLException { + return EnumCodeUtil.manageCode(type, resultSet.getInt(i)); + } + + @Override + public EnumCodeService getNullableResult(CallableStatement callableStatement, int i) throws SQLException { + return EnumCodeUtil.manageCode(type, callableStatement.getInt(i)); + } +} +``` + diff --git a/java/工具类/自定义restful接口响应体.md b/java/工具类/自定义restful接口响应体.md new file mode 100644 index 0000000..eace552 --- /dev/null +++ b/java/工具类/自定义restful接口响应体.md @@ -0,0 +1,275 @@ +## 自定义restful接口响应体 + +#### RestResponse + +##### 作用:响应体载体,响应内容都在此对象中存储,此类定义MSG枚举消息体 + +```java +@Data +@Accessors(chain = true) +@ToString +@NoArgsConstructor +public class RestResponse implements Serializable { + + private static boolean showError = true; + + public enum MSG { + + // 成功 + SUCCESS(1, "SUCCESS"), + // 失败 + FAILURE(0, "FAILURE"), + // 参数为空 + NULL_PARAM(10000, "参数为空"), + // 对象为空 + NULL_OBJ(10001, "对象为空"), + // 有数据为空 + NO_DATA_BASE_EXISTS(10002, "数据在库中为空"), + // 参数未找到 + NO_EXISTS_PARAM(10003, "参数未找到"), + // 数据不存在 + NO_DATA_EXISTS(10004, "数据不存在"), + // 分页参数为空 + NULL_PAGE_PARAM(10005, "分页参数为空"), + // 参数验证失败 + PARAM_VALIDATION_FAILURE(10006, "参数验证未通过"), + // 参数不一致 + PARAM_NOT_EQUAL(10007, "执行修改操作异常,参数id不一致"), + // 参数验证失败 + DATA_EXISTS(10008, "数据已存在"), + // 参数值不符合规范 + PARAM_VALUE_ERROR(11000, "参数值不符合规范"); + + int code; + String msg; + + public int getCode() { + return code; + } + + public String getMsg() { + return msg; + } + + public void setCode(int code) { + this.code = code; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + + MSG(int code, String msg) { + this.code = code; + this.msg = msg; + } + } + + private int code; + private String msg; + @JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler"}) + private T data; + + public RestResponse(MSG msg) { + this.code = msg.code; + this.msg = msg.msg; + } + + /** + * 通过预设错误码和自定义错误信息创建 + * @param code 错误码 + * @param msg 错误信息 + */ + private RestResponse(int code, String msg) { + this.code = code; + this.msg = msg; + } + + public RestResponse(T obj) { + this.code = MSG.SUCCESS.code; + this.msg = MSG.SUCCESS.msg; + this.data = obj; + } + + public RestResponse(MSG msg, T obj) { + this.code = msg.code; + this.msg = msg.msg; + this.data = obj; + } + + public RestResponse(int code,String msg, T obj) { + this.code = code; + this.msg = msg; + this.data = obj; + } + + public static RestResponse success() { + return new RestResponse<>(MSG.SUCCESS); + } + + public static RestResponse success(T obj) { + return new RestResponse<>(MSG.SUCCESS, obj); + } + + public static RestResponse success(int code, String msg) { + return new RestResponse<>(code, msg); + } + + public static RestResponse success(T obj,String msg) { + return new RestResponse<>(MSG.SUCCESS.code,msg, obj); + } + + public static RestResponse failure() { + return new RestResponse<>(MSG.FAILURE); + } + + + public static RestResponse failure(int code, String msg) { + return new RestResponse<>(code, msg); + } + + + public static RestResponse failure(MSG e) { + return new RestResponse<>(e.getCode(), e.getMsg()); + } + + + public static RestResponse failure(MyException e) { + return new RestResponse<>(e.getCode(), e.getMsg()); + } + + + public static RestResponse failure(T obj) { + return new RestResponse<>(MSG.FAILURE, obj); + } + + /** + * 分页信息 + * @param content 内容列表 + * @param page 当前页数 + * @param size 每页数据量 + * @param total 数据总量 + * @param totalPage 总页数 + * @return res + */ + public static RestResponse> pageList(List content, long page, long size, long total, long totalPage) { + + + PageResult pr = new PageResult<>(content, page, total, size, totalPage); + + return new RestResponse<>(MSG.SUCCESS, pr); + } + + /** + * 分页信息 + * @param content 内容列表 + * @param total 数据总量 + * @return res + */ + public static RestResponse> simplePageList(List content, long total) { + + PageResult pr = new PageResult<>(content, total); + + return new RestResponse<>(MSG.SUCCESS, pr); + } + +} +``` + + + +#### PageResult + +##### 作用:分页查询响应体载体 + +```java +@Data +@Builder +@NoArgsConstructor +@Accessors(chain = true) +@ApiModel("分页返回对象") +public class PageResult implements Serializable { + + private static final long serialVersionUID = 1402394526521183854L; + + @ApiModelProperty("主题内容") + @JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler"}) + private List content; + @ApiModelProperty("当前页") + private long page; + @ApiModelProperty("每页数量") + private long size; + @ApiModelProperty("总数量") + private long total; + @ApiModelProperty("总页数") + private long totalPage; + + public PageResult(List content, + long page, + long size, + long total, + long totalPage){ + this.content=content; + this.page=page; + this.size=size; + this.totalPage=totalPage; + this.total=total; + } + + public PageResult(List content, + long total){ + this.content=content; + this.total=total; + } +} +``` + +#### MyException + +##### 作用:自定义异常类 + +```java +@Data +@NoArgsConstructor +@Accessors(chain = true) +@Builder +public class MyException extends RuntimeException { + + + //错误码 + private Integer code; + + //错误信息 + private String msg; + + /** + * 自定义异常信息 + */ + public MyException(Integer code, String msg) { + super(msg); + this.code = code; + this.msg = msg; + } + + /** + * 响应类异常信息 + */ + public MyException(RestResponse.MSG msg) { + super(msg.getMsg()); + this.code=msg.getCode(); + this.msg=msg.getMsg(); + } + + public MyException append(String msg){ + this.msg+=msg; + return this; + } + + public MyException before(String msg){ + this.msg=msg+this.msg; + return this; + } +} +``` + diff --git a/java/Java CMD运行Jar出现乱码问题.md b/java/踩坑记录/Java CMD运行Jar出现乱码问题.md similarity index 100% rename from java/Java CMD运行Jar出现乱码问题.md rename to java/踩坑记录/Java CMD运行Jar出现乱码问题.md diff --git a/java/queue/Java 队列-生产者消费者模式之卖馒头.md b/java/队列-queue/Java 队列-生产者消费者模式之卖馒头.md similarity index 100% rename from java/queue/Java 队列-生产者消费者模式之卖馒头.md rename to java/队列-queue/Java 队列-生产者消费者模式之卖馒头.md diff --git a/java/queue/java-queue(队列).md b/java/队列-queue/java-queue(队列).md similarity index 100% rename from java/queue/java-queue(队列).md rename to java/队列-queue/java-queue(队列).md diff --git a/mysql/MySQL踩坑记录.md b/mysql/MySQL踩坑记录.md new file mode 100644 index 0000000..7b98da7 --- /dev/null +++ b/mysql/MySQL踩坑记录.md @@ -0,0 +1,29 @@ +## MySQL踩坑记录 + +### 【1235】 This version of MySQL doesn’t yet support ‘LIMIT & IN/ALL/ANY/SOME subquery’ + ++ ##### 含义:这版本的 MySQL 不支持使用 LIMIT 子句的 IN/ALL/ANY/SOME 子查询 + ++ ##### 问题SQL + + 我想要查找凭证列表中的前十条记录 + + ```mysql + SELECT * FROM voucher where id IN + (select DISTINCT(id) from voucher where is_deleted = 0 and DATE_FORMAT(v.bookkeeping_date,'%Y-%m') >= '2022-08' LIMIT 0,10) + ``` + ++ ##### 原因 + + + 原因在于子查询三层嵌套在 in或 not in 中使用了 limit + ++ ##### 解决办法 + + 将我们的SQL在进行嵌套一层,绕开limit子查询就可以了 + + ```mysql + SELECT * from voucher where id IN + (select id from (select DISTINCT(id) from voucher where is_deleted = 0 and DATE_FORMAT(v.bookkeeping_date,'%Y-%m') >= '2022-08' LIMIT 0,10) vtable) + ``` + + \ No newline at end of file diff --git a/mysql/记录.md b/mysql/记录.md deleted file mode 100644 index 32c6af8..0000000 --- a/mysql/记录.md +++ /dev/null @@ -1 +0,0 @@ -## \ No newline at end of file