你的Java服務是如何監控的呢? 1.Null:監控?什麼監控?我一個寫代碼的服務掛了跟我有什麼關係? 2.命令行:服務掛了?記憶體泄漏?jstat jmap jcmd,還好不是我寫的 3.擼代碼:Java採集JVM/伺服器資源信息 -> Prometheus -> Grafana,請允許我對業務代碼 ...
xml版本查看:https://www.cnblogs.com/binz/p/6564490.html
springboot3.x以前的版本查看 https://www.cnblogs.com/binz/p/17421063.html
springboot3.x查看 https://www.cnblogs.com/binz/p/17654403.html
1、pom引用
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.1.2</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <artifactId>spring-boot-starter-tomcat</artifactId> <groupId>org.springframework.boot</groupId> </exclusion> </exclusions> </dependency> <!-- web 容器使用 undertow 性能更強 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> </dependency> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.4.7</version> </dependency>
<!-- 以前的tkmapper 不支持springboot3.x -->
<!-- 具體查看https://mapper.mybatis.io/--> <dependency> <groupId>io.mybatis</groupId> <artifactId>mybatis-mapper</artifactId> <version>2.1.1</version> </dependency>
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>3.0.2</version> </dependency>
<!-- openapi、 swagger3、knife4j配置,適用boot3 -->
<!-- https://doc.xiaominfo.com -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>4.3.0</version>
</dependency>
<!-- openapi配置 -->
</dependencies>
2、新建自己的BaseMapper
import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; import java.util.Optional; import org.apache.ibatis.session.RowBounds; import com.github.pagehelper.Page; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ReflectUtil; import io.mybatis.mapper.Mapper; import io.mybatis.mapper.example.Example; import io.mybatis.mapper.example.LambdaExampleWrapper; public interface BaseMapper<T> extends Mapper<T,Long>{ List<T> selectList(T entity, RowBounds rowBounds); default T getById(Long id) { return selectByPrimaryKey(id).orElse(null); } default <RE extends Serializable> RE getById(Long id,Class<RE> returnClass) { T t = getById(id); if(t != null) { return covert(t,returnClass); } return null; } default T one(T query) { return selectOne(query).orElse(null); } default <RE extends Serializable> RE one(T query,Class<RE> returnClass) { Optional<T> optional = selectOne(query); if(optional.isPresent()) { T t = optional.get(); return covert(t,returnClass); } return null; } default <RE extends Serializable> List<RE> select(T t,Class<RE> returnClass) { List<T> ts = selectList(t); return covertList(ts,returnClass); } default <RE extends Serializable> Page<RE> selectPage(T t,Class<RE> returnClass) { Page<T> ts = (Page<T>) selectList(t); return (Page<RE>) covertList(ts,returnClass); } default <RE extends Serializable> Page<RE> selectPageByExample(Example<T> example,Class<RE> returnClass) { Page<T> ts = (Page<T>) selectByExample(example); return (Page<RE>) covertList(ts,returnClass); } default <RE extends Serializable> List<RE> selectByExample(Example<T> example,Class<RE> returnClass) { List<T> ts = selectByExample(example); return covertList(ts,returnClass); } default <RE extends Serializable> RE selectOneByExample(Example<T> example,Class<RE> returnClass) { Optional<T> optional = selectOneByExample(example); if(optional.isPresent()) { T t = optional.get(); return covert(t,returnClass); } return null; } default <RE extends Serializable> RE selectOneByExampleLimitOne(Example<T> example,Class<RE> returnClass) { T t = selectOneByExampleLimitOne(example); if(t != null) { return covert(t, returnClass); } return null; } default T selectOneByExampleLimitOne(Example<T> example) { RowBounds rowBounds = new RowBounds(0, 1); List<T> ts = selectByExample(example, rowBounds); if(ObjectUtil.isNotEmpty(ts)) { return ts.get(0); } return null; } default T selectOneByLimitOne(T t) { RowBounds rowBounds = new RowBounds(0, 1); List<T> ts = selectList(t,rowBounds); if(ObjectUtil.isNotEmpty(ts)) { return ts.get(0); } return null; } @SuppressWarnings("unchecked") default Class<T> thisTClass() { Class<?> class1 = getClass(); Class<?> interfaces = class1.getInterfaces()[0]; Type[] genericInterfaces = interfaces.getGenericInterfaces(); Type type = genericInterfaces[0]; if( type instanceof ParameterizedType){ ParameterizedType pType = (ParameterizedType) type; Type clazz = pType.getActualTypeArguments()[0]; if( clazz instanceof Class<?> ){ return (Class<T>) clazz; } } return null; } default <RE extends Serializable> List<RE> covertList(List<T> ts,Class<RE> returnClass){ List<RE> responses; if(ts instanceof Page) { responses = new Page<>(); }else { responses = new ArrayList<>(); } for (T t : ts) { responses.add(covert(t,returnClass)); } return responses; } default <RE extends Serializable> RE covert(T t , Class<RE> returnClass) { if(t != null) { RE response = null; try { response = ReflectUtil.newInstanceIfPossible(returnClass); BeanUtil.copy(t, response); } catch (Exception e) { e.printStackTrace(); } return response; } return null; } //自帶的wrapper()個人覺得還缺點東西,就自己複製了一份出來微調了,根據情況使用,不需要就刪除,需要對應的代碼在下方 default LambdaExampleWrapper<T> lambdaWrapper() { return new LambdaExampleWrapper<>(BaseMapper.this, example()); } }View Code
3、新建表模型,註意註解使用和以前版本有區別,但是相容一些之前javax.persistence的一些基本註解
import java.util.Date; import io.mybatis.provider.Entity; import lombok.Data; @Data @Entity.Table("system_user") public class User { @Entity.Column(id = true,insertable = false,updatable = false) private Long id; /** * 姓名 */ private String realname; /** * 手機號 */ private String mobile; /** * 密碼 */ private String password; /** * 身份證號 */ private String idcard; /** * 頭像 */ private String avatar; /** * 最後登錄時間 */ private String lastLoginIp; /** * 最後登錄時間 */ private Date lastLoginTime; /** * 創建人 */ private Long createBy; /** * 創建時間 */ private Date createTime; /** * 修改人 */ private Long updateBy; /** * update_time */ private Date updateTime; }View Code
4、創建對應業務的mapper繼承BaseMapper
import com.xxx.core.base.BaseMapper; import com.xxx.system.model.User; public interface UserMapper extends BaseMapper<User>{ }
5、啟動類掃描自己的mapper目錄 @MapperScan
import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.ComponentScan; import org.springframework.scheduling.annotation.EnableScheduling; @EnableCaching @EnableScheduling @SpringBootApplication @MapperScan(basePackages="com.xxx.*.mapper") @ComponentScan(basePackages = { "com.xxx.*.config", "com.xxx.*.controller", "com.xxx.*.job" }) public class OperateApiStarted { public static void main(String[] args) { SpringApplication.run(OperateApiStarted.class, args); } }
6、創建io.mybatis.mapper.example.LambdaExampleWrapper
package io.mybatis.mapper.example; import java.io.Serializable; import java.util.Arrays; import java.util.List; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.ibatis.exceptions.TooManyResultsException; import org.apache.ibatis.session.RowBounds; import com.github.pagehelper.Page; import com.xxx.BaseMapper; import com.xxx.BeanUtil; import io.mybatis.common.util.Assert; import io.mybatis.mapper.fn.Fn; public class LambdaExampleWrapper<T> { private final BaseMapper<T> baseMapper; private final Example<T> example; private Example.Criteria<T> current; public LambdaExampleWrapper(BaseMapper<T> baseMapper, Example<T> example) { this.baseMapper = baseMapper; this.example = example; this.current = example.createCriteria(); } /** * or 一組條件 * * @return 條件 */ public LambdaExampleWrapper<T> or() { this.current = this.example.or(); return this; } /** * 獲取查詢條件 */ public Example<T> example() { return example; } /** * 清除條件,可重用 */ public LambdaExampleWrapper<T> clear() { this.example.clear(); this.current = example.createCriteria(); return this; } /** * 指定查詢列 * * @param fns 方法引用 */ @SafeVarargs public final LambdaExampleWrapper<T> select(Fn<T, Object>... fns) { this.example.selectColumns(fns); return this; } /** * 排除指定查詢列 * * @param fns 方法引用 */ @SafeVarargs public final LambdaExampleWrapper<T> exclude(Fn<T, Object>... fns) { this.example.excludeColumns(fns); return this; } /** * 設置起始 SQL * * @param startSql 起始 SQL,添加到 SQL 前,註意防止 SQL 註入 */ public LambdaExampleWrapper<T> startSql(String startSql) { this.example.setStartSql(startSql); return this; } /** * 設置結尾 SQL * * @param endSql 結尾 SQL,添加到 SQL 最後,註意防止 SQL 註入 */ public LambdaExampleWrapper<T> endSql(String endSql) { this.example.setEndSql(endSql); return this; } /** * 通過方法引用方式設置排序欄位 * * @param fn 排序列的方法引用 * @param order 排序方式 * @return Example */ public LambdaExampleWrapper<T> orderBy(Fn<T, Object> fn, Example.Order order) { this.example.orderBy(fn, order); return this; } /** * 支持使用字元串形式來設置 order by,用以支持一些特殊的排序方案 * * @param orderByCondition 排序字元串(不會覆蓋已有的排序內容) * @return Example */ public LambdaExampleWrapper<T> orderBy(String orderByCondition) { this.example.orderBy(orderByCondition); return this; } /** * 支持使用字元串形式來設置 order by,用以支持一些特殊的排序方案 * * @param orderByCondition 排序字元串構造方法,比如通過數組集合迴圈拼接等 * @return Example */ public LambdaExampleWrapper<T> orderBy(Supplier<String> orderByCondition) { this.example.orderBy(orderByCondition); return this; } /** * 支持使用字元串形式來設置 order by,用以支持一些特殊的排序方案 * * @param useOrderBy 條件表達式,true使用,false不使用 字元串排序 * @param orderByCondition 排序字元串構造方法,比如通過數組集合迴圈拼接等 * @return Example */ public LambdaExampleWrapper<T> orderBy(boolean useOrderBy, Supplier<String> orderByCondition) { return useOrderBy ? this.orderBy(orderByCondition) : this; } /** * 通過方法引用方式設置排序欄位,升序排序 * * @param fns 排序列的方法引用 * @return Example */ @SafeVarargs public final LambdaExampleWrapper<T> orderByAsc(Fn<T, Object>... fns) { this.example.orderByAsc(fns); return this; } /** * 通過方法引用方式設置排序欄位,降序排序 * * @param fns 排序列的方法引用 * @return Example */ @SafeVarargs public final LambdaExampleWrapper<T> orderByDesc(Fn<T, Object>... fns) { this.example.orderByDesc(fns); return this; } /** * 設置 distince */ public LambdaExampleWrapper<T> distinct() { this.example.setDistinct(true); return this; } /** * 設置更新欄位和值 * * @param useSet 表達式條件, true 使用,false 不使用 * @param setSql "column = value" */ public LambdaExampleWrapper<T> set(boolean useSet, String setSql) { return useSet ? set(setSql) : this; } /** * 設置更新欄位和值 * * @param setSql "column = value" */ public LambdaExampleWrapper<T> set(String setSql) { this.example.set(setSql); return this; } /** * 設置更新欄位和值 * * @param useSet 表達式條件, true 使用,false 不使用 * @param fn 欄位 * @param value 值 */ public LambdaExampleWrapper<T> set(boolean useSet, Fn<T, Object> fn, Object value) { return useSet ? set(fn, value) : this; } /** * 設置更新欄位和值 * * @param useSet 表達式條件, true 使用,false 不使用 * @param fn 欄位 * @param supplier 值構造函數 */ public LambdaExampleWrapper<T> set(boolean useSet, Fn<T, Object> fn, Supplier<Object> supplier) { return useSet ? set(fn, supplier.get()) : this; } /** * 設置更新欄位和值 * * @param fn 欄位 * @param value 值 */ public LambdaExampleWrapper<T> set(Fn<T, Object> fn, Object value) { this.example.set(fn, value); return this; } /** * 指定欄位為 null * * @param useCondition 表達式條件, true 使用,false 不使用 * @param fn 欄位對應的 get 方法引用 */ public LambdaExampleWrapper<T> isNull(boolean useCondition, Fn<T, Object> fn) { return useCondition ? isNull(fn) : this; } /** * 指定欄位為 null * * @param fn 欄位對應的 get 方法引用 */ public LambdaExampleWrapper<T> isNull(Fn<T, Object> fn) { this.current.addCriterion(fn.toColumn() + " IS NULL"); return this; } /** * 指定欄位不為 null * * @param useCondition 表達式條件, true 使用,false 不使用 * @param fn 欄位對應的 get 方法引用 */ public LambdaExampleWrapper<T> isNotNull(boolean useCondition, Fn<T, Object> fn) { return useCondition ? isNotNull(fn) : this; } /** * 指定欄位不為 null * * @param fn 欄位對應的 get 方法引用 */ public LambdaExampleWrapper<T> isNotNull(Fn<T, Object> fn) { this.current.addCriterion(fn.toColumn() + " IS NOT NULL"); return this; } /** * 欄位 = 值 * * @param useCondition 表達式條件, true 使用,false 不使用 * @param fn 欄位對應的 get 方法引用 * @param value 值 */ public LambdaExampleWrapper<T> eq(boolean useCondition, Fn<T, Object> fn, Object value) { return useCondition ? eq(fn, value) : this; } /** * 欄位 = 值 * * @param useCondition 表達式條件, true 使用,false 不使用 * @param fn 欄位對應的 get 方法引用 * @param supplier 值構造函數 */ public LambdaExampleWrapper<T> eq(boolean useCondition, Fn<T, Object> fn, Supplier<Object> supplier) { return useCondition ? eq(fn, supplier.get()) : this; } /** * 欄位 = 值 * * @param fn 欄位對應的 get 方法引用 * @param value 值 */ public LambdaExampleWrapper<T> eq(Fn<T, Object> fn, Object value) { this.current.addCriterion(fn.toColumn() + " =", value); return this; } /** * 欄位 != 值 * * @param useCondition 表達式條件, true 使用,false 不使用 * @param fn 欄位對應的 get 方法引用 * @param supplier 值構造函數 */ public LambdaExampleWrapper<T> ne(boolean useCondition, Fn<T, Object> fn, Supplier<Object> supplier) { return useCondition ? ne(fn, supplier.get()) : this; } /** * 欄位 != 值 * * @param useCondition 表達式條件, true 使用,false 不使用 * @param fn 欄位對應的 get 方法引用 * @param value 值 */ public LambdaExampleWrapper<T> ne(boolean useCondition, Fn<T, Object> fn, Object value) { return useCondition ? ne(fn, value) : this; } /** * 欄位 != 值 * * @param fn 欄位對應的 get 方法引用 * @param value 值 */ public LambdaExampleWrapper<T> ne(Fn<T, Object> fn, Object value) { this.current.addCriterion(fn.toColumn() + " <>", value); return this; } /** * 欄位 > 值 * * @param useCondition 表達式條件, true 使用,false 不使用 * @param fn 欄位對應的 get 方法引用 * @param supplier 值構造函數 */ public LambdaExampleWrapper<T> gt(boolean useCondition, Fn<T, Object> fn, Supplier<Object> supplier) { return useCondition ? gt(fn, supplier.get()) : this; } /**