阅读理解
- 命令之间空一行:表示前面的是配置
- 红色背景:表示待验证
- 蓝色背景:表示常用或推荐
- 绿色背景:注意/推荐
json 转 对象
import com.fasterxml.jackson.databind.ObjectMapper;
public DebangResp convertJsonToObject(String jsonString) { ObjectMapper objectMapper = new ObjectMapper(); try { return objectMapper.readValue(jsonString, DebangResp.class); } catch (Exception e) { e.printStackTrace(); // 处理异常,例如返回 null 或抛出自定义异常 return null; } }
jenkins
安装
- 添加yum 源仓库
wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo
- 导入仓库源的key(秘钥)
rpm --import https://jenkins-ci.org/redhat/jenkins-ci.org.key
详细步骤
- 官网地址:Jenkins
- 启动:java -jar jenkins.war
稳定版本
Redhat提供安装Jenkins长期稳定版本的源,参考下面命令安装:
sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat-stable/jenkins.repo
sudo rpm --import https://jenkins-ci.org/redhat/jenkins-ci.org.key
sudo yum install jenkins
报错
解决方案
IDEA
idea快捷键
ctrl+h:查看继承关系
structure 查看该类的成员
idea自定义模板
自定义创建文件模板
- 在设置窗口中,选择 Editor > File and Code Templates > file
- 例如编辑class类容
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
#parse("File Header.java")
/**
* 客户身体报告(CustomerPhysicalReport)实体类
*
* @author zhg
* @since ${DATE} ${TIME}
*/
public class ${NAME} {
}
#if 和 #end 是模板引擎的语法,用来控制代码块的条件生成。
#parse("File Header.java") 从另一个模板文件 "File Header.java" 中解析并插入代码。
- 特殊变量:
${NAME}: 用于类名。
${PACKAGE_NAME}: 用于包名。
${USER}: 用户名。
${DATE}: 当前日期。:年/月/日
${TIME}: 当前时间。
${YEAR}: 当前年份。
${MONTH}: 当前月份。
${DAY_OF_MONTH}: 当前日期中的天数。
${HOUR}: 当前小时数。
${MINUTE}: 当前分钟数。
- 自定义变量: 如果您想添加更多自定义变量,可以在模板中使用 ${VAR_NAME} 的形式,并在创建类时 IDEA 会提示您输入这些变量的值。
自定义 方法 模板
- File -> Settings - > Editor -> Live Templates -> 点击"+"号 -> Template Group
新建组名
- 编辑类容
/** @Author zhg
@Description //TODO end
@Date time date
@Param param paramparam
@return return
**/
- 配置生效位置
- 应用
add
快捷键应用
- Windows/Linux: 按 Ctrl + Shift + Doc Comment (或 Ctrl + Shift + /)。
- macOS: 按 Cmd + Shift + Doc Comment (或 Cmd + Shift + /)。
IDEA 一键启动配置
获取时间
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
swagger
1.导入依赖
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.8.0</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.8.0</version> </dependency>
2.配置类
import org.springframework.beans.factory.annotation.Value; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.Collections; @Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()) .build() .apiInfo(apiInfo()); } private ApiInfo apiInfo() { return new ApiInfo( "My API", "A sample API documentation generated using Springfox", "API TOS", "Terms of service", new Contact("John Doe", "www.example.com", "myeaddress@company.com"), "License of API", "API license URL", Collections.emptyList()); } }
3.yml
spring: mvc: pathmatch: matching-strategy: ANT_PATH_MAT
4.访问
http://localhost:端口/路径/swagger-ui.html
4.Knife4j增强
<dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <version>2.0.4</version> </dependency>删除
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.8.0</version>
</dependency>
5.添加配置(可选)
knife4j: enable: true setting: enablePathMapping: true
5.访问
http://localhost:端口/路径/doc.html
6.使用
- @Api
用于类上,表示这是一个 Swagger 资源。
参数:
tags:描述该类的作用,参数是一个数组,可以填写多个标签。
description:描述该类的功能。
@Api(tags = "用户管理", description = "用户基本信息操作")
public class UserController {
// ...
}
- @ApiOperation
用于方法上,描述一个具体的 API 操作。
参数:
value:描述此操作的简短摘要。
notes:额外的注意事项。
response:指定响应对象的类型。
tags:与 @Api 类似,用于分类。
@ApiOperation(value = "获取用户列表", notes = "返回所有用户的列表", response = User.class)
public List<User> getUsers() {
// ...
}
- @ApiParam
用于方法参数上,描述一个参数。
参数:
value:描述此参数的意义。
required:是否必须。
defaultValue:默认值。
@ApiOperation(value = "获取用户详情", notes = "根据 ID 获取用户详情", response = User.class)
public User getUser(@ApiParam(value = "用户ID", required = true) @PathVariable Long id) {
// ...
}
- @ApiResponses
用于方法上,描述可能的 HTTP 响应状态码。
参数:
value:一个数组,每个元素都是一个 ApiResponse 对象。
@ApiResponses(value = {
@ApiResponse(code = 200, message = "成功"),
@ApiResponse(code = 404, message = "未找到"),
@ApiResponse(code = 500, message = "内部服务器错误")
})
public User getUser(@PathVariable Long id) {
// ...
}
@ApiResponse
描述一个 HTTP 响应的状态码及消息。
参数:
code:HTTP 状态码。
message:描述信息。
- @ApiModel
用于类上,描述一个模型对象。
参数:
description:描述此模型的作用。
@ApiModel(description = "用户信息")
public class User {
private Long id;
private String name;
// ...
}
- @ApiModelProperty
用于字段上,描述模型对象中的一个属性。
参数:
value:描述此属性的意义。
required:是否必须。
example:示例值。
@ApiModel(description = "用户信息")
public class User {
@ApiModelProperty(value = "用户ID", required = true, example = "1")
private Long id;
// ...
}
mvn 打包
- mvn install -DskipTests # 跳过测试,但不跳过编译
- mvn install -Dmaven.test.skip=true # 跳过测试和编译
- mvn install:install-file -Dfile=path/to/example.jar -DgroupId=com.example -DartifactId=example-jar -Dversion=1.0 -Dpackaging=jar 添加jar包到仓库
-Dfile .jar包路径
-DgroupId 组id
-DartifactId artifactId
-Dversion 版本
-Dpackaging 文件类型
pom.xml
jar包依赖导入
<groupId>com.bianque</groupId> <artifactId>bianque-common-dop</artifactId> <version>0.0.1-SNAPSHOT</version> <scope>system</scope> <systemPath>${project.basedir}/src/main/resources/libs/dop-sdk-0.0.1-SNAPSHOT.jar</systemPath>
服务调用
Feign
报错
- JSON parse error: Illegal character ((CTRL-CHAR, code 31)): only regular white space
- 若依框架没有权限。需要登录状态(才能通过Security)
解决方案
位置:调用项目
1、关闭请求数据压缩
feign.compression.request.enabled: false
feign.compression.response.enabled: false
2、设置请求压缩的最小请求大小
feign.compression.request.min-request-size: 8192
git
文件颜色的含义
蓝色:修改过的文件
红色:冲突文件
粉红:未追踪的文件
绿色:已经追踪文件
暂存
- 执行暂存
git stash
apply [stash_key] 不会丢失栈信息
sava ‘描述信息’ 有描述信息
push 压栈 没有描述信息
pop 弹栈 会丢失栈信息
- 查看暂存列表
git stash list
- 应用暂存
git stash apply [stash-key]
--index [n] windows平台替换 apply [stash-key]
分支
- 查看分支
git branch
-d 删除已经完成合并的分支
-D 强制删除分支
- 新建分支
git branch branch_name
- 切换分支
git swicth branch_name
- 合并分支
git merge brash_name
- 终止合并分支
git merge --abort
合并分支到当前分支
- 查看分支图
git log --graph --oneline --decorate --all
或
alias git-log='git log --graph --oneline --decorate --all'
git-log
-
提交
git commit -m "描述信息"
- 与上一个commit合并
git commit --amend -m "描述信息"
远端仓库
- 查看远端仓库
git remote
参数解析
- v 查看所有远端url
- get-url 查看特定远端的url
- set-url 设置远端仓库的url
- remove local_origion_branch_name
- 查看特定远端仓库地址
- 对接远端仓库
git remote add [local_origin_branch_name] [origin_url]
- 推送并合并
git push [local_origin_branch_name] [local_branch_name:origin_branch_name]
或
git push --set-upstream local_origin_branch_name [local_branch_name:origin_branch_name]
git push
-f 强制覆盖
远端分支与本地分支的关联关系
git branch -vv
- 远端克隆
git clone [origin_url] [loca_file_name]
- 远端抓取
git fetch [origin_name] [origin_branch_name]
或
git fetch
抓取远端分支,但不会合并
- 远端拉取
git pull local_origion_branch_name origion_branch_name:local_branch_name
或
git fetch
git merge branch_name
冲突
修改同一个文件,同一行
- 查看冲突列表
git status
both modified: main1.txt
both modified: main2.txt
- 查看冲突的具体内容
git diff
-
本地仓库冲突解决方案
1.提交:生成冲突文件
2.修改:冲突文件
3.添加:添加文件到暂存区
3.提交
-
远程仓库 冲突解决方案
1.pull :生成冲突文件
2.修改:冲突文件
3.添加:添加文件到暂存区
3.commit:提交文件(自动合并分支)
4.push :推送自己的最新修改
回退
- 回退版本
git reset id
--soft 保留工作区,暂存区: 可以重新修改,再提交
--mixed 保留工作区,清除暂存区:可以重新修改,再提交(需要重新添加暂存区)
--hard 清除工作区,暂存区
- 查看暂存区内容
git ls-files
- 查看操作记录
git reflog
- 查看提交记录
git log --oneline
查看版本信息
git log --graph
可以回退版本
CI/CD 还没完成
git安装
gitlab安装
jenkins安装之docker
1.pull 镜像
docker pull jenkins/jenkins:lts
2.启动
docker run \
--name jenkins \
--restart always \
-d \
-p 8080:8080 \
-p 50000:50000 \
-v jenkins_home:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/bin/docker:/usr/bin/docker \
jenkins/jenkins:lts
3.访问
http://ip:8080
3.查看密码
# Jenkins容器启动日志 保存密码后面登陆控制台使用。
docker logs -f 容器名
mybatis
mapper
- import org.apache.ibatis.annotations.Param; 参数包
mapper.xml
- classpath:只会到你的class路径中查找找文件。
- classpath*:不仅包含class路径,还包括jar文件中(class路径)进行查找。
-
<trim> 标签 prefix:需要在去除之前 添加的前缀。 suffix:需要在去除之后 添加的后缀。 prefixOverrides:需要 去除的前缀。 suffixOverrides:需要 去除的后缀。
- 条件生成sql
<set>特点:
用于生成 SQL 更新语句中的 SET 子句。
只有至少一个子元素的值不为 null 时才会输出整个 SET 子句。
常见于 UPDATE 语句中,用来动态构建需要更新的字段列表。
<update id="updateUser"> UPDATE user <set> <if test="username != null">username = #{username}, </if> <if test="email != null">email = #{email}, </if> <if test="age != null">age = #{age} </if> </set> WHERE id = #{id} </update>
<trim>特点:
可以移除前导或尾随的文本(如逗号、括号等),这对于构建动态 SQL 很有用。
支持 prefix 和 suffix 属性来添加前缀和后缀。
支持 prefixOverrides 和 suffixOverrides 属性来移除多余的前缀和后缀。
<select id="selectUsers">
SELECT * FROM user
WHERE 1=1
<trim prefix="AND (" suffix=")" prefixOverrides="AND">
<if test="username != null"> username = #{username} </if>
<if test="email != null"> AND email = #{email} </if>
<if test="age != null"> AND age = #{age} </if>
</trim>
</select>
- 循环生成sql
<foreach collection="entities" item="entity" separator=","> (#{entity.uid},#{entity.bannerSetUid}, #{entity.picUrl}, #{entity.linkType}, #{entity.jumpUrl}, #{entity.sortNum}, #{entity.status}, #{entity.createTime}, #{entity.updateTime}) </foreach>
这个XML函数是一个foreach循环,它的功能是对一个名为entities的集合进行迭代处理。每次迭代时,将集合中的每个元素作为entity进行处理,并用,作为分隔符将处理结果拼接在一起。在迭代过程中,将每个entity的uid、bannerSetUid、picUrl、linkType、jumpUrl、sortNum、status、createTime和updateTime属性按照给定的顺序输出。
- 类的属性映射
<resultMap type="com.apq.sdemo.common.dataobj.ManageDO" id="ManageMap"> <result property="uid" column="uid" jdbcType="VARCHAR"/> </resultMap>
多数据源:动态数据源切换
- 1.配置多数据源yml
datasource: mysql-db: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.jdbc.Driver jdbc-url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false&allowMultiQueries=true&serverTimezone=GMT%2B8&useSSL=false username: root password: root secondary: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.jdbc.Driver jdbc-url: jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false&allowMultiQueries=true&serverTimezone=GMT%2B8&useSSL=false username: root password: root
- 2. DataSourceConfig 类配置
@Configuration @MapperScan(basePackages = "com.test.mapper", sqlSessionTemplateRef = "mysqlDbSqlSessionTemplate") public class DataSourceConfig { @Bean(name = "datasource1") @ConfigurationProperties(prefix = "spring.datasource.mysql-db") public DataSource datasource1() { return DataSourceBuilder.create().build(); } @Bean(name = "datasource2") @ConfigurationProperties(prefix = "spring.datasource.secondary") public DataSource datasource2() { return DataSourceBuilder.create().build(); } @Bean(name = "dynamicDataSource") @Primary public DataSource dynamicDataSource(){ DynamicDataSource dynamicDataSource = new DynamicDataSource(); // 设置默认数据源 这个代码有点重复了,因为我们在DataSourceChange类中已经设定了默认数据库 dynamicDataSource.setDefaultTargetDataSource(datasource1()); HashMap<Object, Object> objectObjectHashMap = new HashMap<>(); objectObjectHashMap.put("datasource1", datasource1()); objectObjectHashMap.put("datasource2", datasource2()); dynamicDataSource.setTargetDataSources(objectObjectHashMap); return dynamicDataSource; } @Bean public SqlSessionFactory mysqlDbSqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setVfs(SpringBootVFS.class); bean.setTypeAliasesPackage("com.test.dao"); bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*.xml")); return bean.getObject(); } // @Bean // public DataSourceTransactionManager mysqlDbTransactionManager(@Qualifier("dynamicDataSource") DataSource dataSource) { // return new DataSourceTransactionManager(dataSource); // } @Bean public PlatformTransactionManager transactionManager(){ return new DataSourceTransactionManager(dynamicDataSource()); } @Bean public SqlSessionTemplate mysqlDbSqlSessionTemplate(@Qualifier("mysqlDbSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { return new SqlSessionTemplate(sqlSessionFactory); } }
- 3.编写DataSourceContextHolder
public class DataSourceContextHolder { /** * 默认数据源 */ public static final String DEFAULT_DS = "datasource1"; private static final ThreadLocal<String> contextHolder = new ThreadLocal<>(); // 设置数据源名 public static void setDB(String dbType) { System.out.println("切换到{"+dbType+"}数据源"); contextHolder.set(dbType); } // 获取数据源名 public static String getDB() { return (contextHolder.get()); } // 清除数据源名 public static void clearDB() { contextHolder.remove(); } }
- 3.编写DynamicDataSource
public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDB(); } }
- 4.自定义注解DS
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) @Documented public @interface DS { String value() default "datasource1"; }
- 5.编写AOP:DynamicDataSourceAspect
@Aspect @Component public class DynamicDataSourceAspect { @Before("@annotation(com.annotation.DS)") public void beforeSwitchDS(JoinPoint point){ //获得当前访问的class Class<?> className = point.getTarget().getClass(); //获得访问的方法名 String methodName = point.getSignature().getName(); //得到方法的参数的类型 Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes(); String dataSource = DataSourceContextHolder.DEFAULT_DS; try { // 得到访问的方法对象 Method method = className.getMethod(methodName, argClass); // 判断是否存在@DS注解 if (method.isAnnotationPresent(DS.class)) { DS annotation = method.getAnnotation(DS.class); // 取出注解中的数据源名 dataSource = annotation.value(); } } catch (Exception e) { e.printStackTrace(); } // 切换数据源 DataSourceContextHolder.setDB(dataSource); } @After("@annotation(com.annotation.DS)") public void afterSwitchDS(JoinPoint point){ DataSourceContextHolder.clearDB(); } }
- 6.启动类添加
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
- 7.DS注解:应用再方法上
mybatis plus
1.pom.xml
<!-- mybatisplus--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.3</version> <!-- 使用最新稳定版本 --> </dependency><!-- mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency>
2.yml
# datasource
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/testdb?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
username: root
password: 123456# mybatis-plus
mybatis-plus:
configuration:
# 显示 SQL 执行语句
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
# 主键类型
id-type: auto
# 逻辑删除字段
logic-delete-field: deleted
# 逻辑删除值
logic-not-delete-value: 0
logic-delete-value: 1
多数据源配置
1.添加DataSourceConfig配置类
@Configuration
public class DataSourceConfig {@Bean(name = "dataSource1")
@ConfigurationProperties(prefix = "spring.datasource1")
public DataSource dataSource1() {
return DataSourceBuilder.create().build();
}@Bean(name = "dataSource2")
@ConfigurationProperties(prefix = "spring.datasource2")
public DataSource dataSource2() {
return DataSourceBuilder.create().build();
}
}
2.事务管理器配置
@Configuration
@EnableTransactionManagement
public class TransactionConfig {@Bean(name = "transactionManager1")
public PlatformTransactionManager transactionManager1(@Qualifier("dataSource1") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}@Bean(name = "transactionManager2")
public PlatformTransactionManager transactionManager2(@Qualifier("dataSource2") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
3.mapper接口加注解
@Repository
@Mapper
@DataSource("dataSource1")
public interface UserMapper1 extends BaseMapper<User> {
}@Repository
@Mapper
@DataSource("dataSource2")
public interface UserMapper2 extends BaseMapper<User> {
}
事务管理
@Transactional(rollbackFor = DataAccessException.class)
注解
-
@PathVariable("storeName") 路径参数
常用lambda
List 或 Set遍历
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// 使用Lambda表达式遍历List
names.stream().forEach(name -> System.out.println(name));
aspect
1.示例
@Aspect @Component public class ControllerAspect { @Around(value = "execution(* com.x.x.x.x.controller.*.*(..))") public Object handleControllerMethods(ProceedingJoinPoint joinPoint) throws Throwable { return joinPoint.proceed(); } }
- 通知
@Around 环绕通知
- 连接点方法
joinPoint.proceed() 执行方法
joinPoint.getArgs() 获取请求参数
异步
1 @EnableAsync 启用异步及config类
@Configuration @EnableAsync public class AsyncConfig implements AsyncConfigurer { @Bean public TaskScheduler taskScheduler() { ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); scheduler.setPoolSize(10); // 设置线程池大小 scheduler.initialize(); return scheduler; } }
2.写异步类的@Async 异步方法
@Async
public void customerLogsAsyncTask() {
System.out.println("Executing async task on thread: " + Thread.currentThread().getName());
try {
Thread.sleep(2000); // 模拟耗时操作
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}
}
}
3.调用异步方法
@Autowired
private MyService myService;
myService.performAsyncTask();
事务
1.配置类上添加@EnableTransactionManagement注解,以启用Spring的事务管理功能。
@Configuration
@EnableTransactionManagement
public class AppConfig {@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}// 配置类的其他内容...
}
2. 使用@Transactional注解
@Service
public class UserService {
@Transactional(rollbackFor = Exception.class)
public void updateUserAndRole(Long userId, Long roleId) {
// 业务
}
}
常用函数接口
boolean 一个参数泛型
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
void 一个参数泛型
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
// 可以有默认方法和静态方法,但核心抽象方法是accept
}
获取请求ip
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 获取客户端IP地址
final String clientIp = getClientIp(request);
private String getClientIp(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
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();
}
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip);
}
请求信息获取
静态获取:RequestContextHolder
AjaxResult 返回值信息
import io.swagger.annotations.ApiModel; import lombok.Data; import java.io.Serializable; import java.util.Objects; @ApiModel(description = "返回") @Data public class AjaxResult<T> implements Serializable { private static final long serialVersionUID = 1L; /** * 是否成功 true or false */ private boolean success; /** * 状态码 */ private int code; /** * 返回内容 */ private String msg; /** * 数据对象 */ private T data; /** * 状态类型 */ public enum Type { /** 成功 */ SUCCESS(0), /** 警告 */ WARN(301), /** 错误 */ ERROR(500); private final int value; Type(int value) { this.value = value; } public int value() { return this.value; } } /** * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。 */ public AjaxResult() { } /** * 初始化一个新创建的 AjaxResult 对象 * * @param type 状态类型 * @param msg 返回内容 * @param data 数据对象 */ public AjaxResult(Type type, String msg, T data) { this.code = type.value(); this.msg = msg; if (Objects.nonNull(data)) { this.data = data; } if (type.value == Type.SUCCESS.value) { this.success = Boolean.TRUE; } else { this.success = Boolean.FALSE; } } /** * 返回成功消息 * * @return 成功消息 */ public static AjaxResult success() { return AjaxResult.success("操作成功"); } /** * 返回成功数据 * * @return 成功消息 */ public static <U> AjaxResult<U> success(U data) { return AjaxResult.success("操作成功", data); } /** * 返回成功消息 * * @param msg 返回内容 * @return 成功消息 */ public static AjaxResult success(String msg) { return AjaxResult.success(msg, null); } /** * 返回成功消息 * * @param msg 返回内容 * @param data 数据对象 * @return 成功消息 */ public static <U> AjaxResult<U> success(String msg, U data) { return new AjaxResult(Type.SUCCESS, msg, data); } /** * 返回警告消息 * * @param msg 返回内容 * @return 警告消息 */ public static AjaxResult warn(String msg) { return AjaxResult.warn(msg, null); } /** * 返回警告消息 * * @param msg 返回内容 * @param data 数据对象 * @return 警告消息 */ public static <U> AjaxResult<U> warn(String msg, U data) { return new AjaxResult(Type.WARN, msg, data); } /** * 返回错误消息 * * @return */ public static AjaxResult error() { return AjaxResult.error("操作失败"); } /** * 返回错误消息 * * @param msg 返回内容 * @return 警告消息 */ public static AjaxResult error(String msg) { return AjaxResult.error(msg, null); } /** * 返回错误消息 * * @param msg 返回内容 * @param data 数据对象 * @return 警告消息 */ public static <U> AjaxResult<U> error(String msg, U data) { return new AjaxResult(Type.ERROR, msg, data); } /** * 方便链式调用 * * @param key 键 * @param value 值 * @return 数据对象 */ @Deprecated public AjaxResult put(String key, Object value) { //super.put(key, value); return this; } /** * 是否为成功消息 * * @return 结果 */ public boolean isSuccess() { return success; } public String getMsg() { return msg; } public Integer getCode() { return code; } }
Httpstatus 返回状态码
/** * 返回状态码 * * @author ruoyi */ public class HttpStatus { /** * 操作成功 */ public static final int SUCCESS = 200; /** * 对象创建成功 */ public static final int CREATED = 201; /** * 请求已经被接受 */ public static final int ACCEPTED = 202; /** * 操作已经执行成功,但是没有返回数据 */ public static final int NO_CONTENT = 204; /** * 资源已被移除 */ public static final int MOVED_PERM = 301; /** * 重定向 */ public static final int SEE_OTHER = 303; /** * 资源没有被修改 */ public static final int NOT_MODIFIED = 304; /** * 参数列表错误(缺少,格式不匹配) */ public static final int BAD_REQUEST = 400; /** * 未授权 */ public static final int UNAUTHORIZED = 401; /** * 访问受限,授权过期 */ public static final int FORBIDDEN = 403; /** * 资源,服务未找到 */ public static final int NOT_FOUND = 404; /** * 不允许的http方法 */ public static final int BAD_METHOD = 405; /** * 资源冲突,或者资源被锁 */ public static final int CONFLICT = 409; /** * 不支持的数据,媒体类型 */ public static final int UNSUPPORTED_TYPE = 415; /** * 系统内部错误 */ public static final int ERROR = 500; /** * 接口未实现 */ public static final int NOT_IMPLEMENTED = 501; /** * 系统警告消息 */ public static final int WARN = 601; }
stream 流
数据 收集.collect
数据格式控制 Collectors
分组:Collectors .groupingBy ()
示例
.collect(Collectors.groupingBy(String::toLowerCase,Collectors.groupingBy(String::toUpperCase)))
List<Map<Date, BigDecimal>> list = iphmsBraceletDataList.stream() .map(iphmsBraceletData -> Collections.singletonMap( iphmsBraceletData.getCreateTime(), iphmsBraceletData.getKcal())) .collect(Collectors.toList());
K8S
分页
import com.github.pagehelper.Page;Page<IphmsTopicsRecordSleepResp> page = new Page<>(); page.addAll(list); page.add(list); page.setTotal(new PageInfo(iphmsSleepResultList).getTotal());
Integer t1 = PageUtils.getPageNunSiz().getT1(); Integer t2 = PageUtils.getPageNunSiz().getT2(); Page<IphmsHealthResult> page = new Page<>(t1 ,t2);
日期时间
常见日期格式字符串
- Jan 4, 2025 10:45:26 转 MMM d, yyyy HH:mm:ss
- 2024-12-27 20:53:57 转 yyyy-MM-dd HH:mm:ss
字符串日期,解析
format
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- format(startTime) Date时间转字符串
formatter
DateTimeFormatter.ofPattern("yyyy-MM-dd")
- .parse(dateString) 解析字符串,返回Date
LocalDate 操作
- .withDayOfMonth(1); 设置天
-
startTime.withDayOfMonth(startTime.lengthOfMonth()); 获取当前月的最后一天的日期
- .plusMonths(1) 增加 月份
- .parse(dateString, formatter) 把有格式的字符串转 LocalDate
LocalDateTime 操作
-
.withYear(Integer.parseInt(year)) 年 .withMonth(Integer.parseInt(month)) 月 .withDayOfMonth(Integer.parseInt(day)); 日
-
.withHour(timeToSet.getHour()) 时
.withMinute(timeToSet.getMinute()) 分
.withSecond(timeToSet.getSecond()); 秒
.withNano(0); 纳秒 - LocalDateTime.parse(dateTimeString, formatter) 字符串转LocalDateTime
- .atZone() 设置 时区
- now() 现在的日期时间
- .atStartOfDay(ZoneId.systemDefault())
LocalTime 操作
- .now() 获取现在的时间
- .format(formatter); 获取格式时间字符串
YearMonth 年月 操作
-
YearMonth.from(localDateTime) 获取 LocalDateTime 的年月数据
- .atDay(1) 设置 天
- .atEndOfMonth() 月份的最后一天
- parse(dateString, formatter) 把有格式的字符串转 YearMonth
时分秒 操作
// 获取当前日期和时间
Calendar calendar = Calendar.getInstance();
// 设置时、分、秒
calendar.set(Calendar.HOUR_OF_DAY, 15); // 设置小时(24小时制)
calendar.set(Calendar.MINUTE, 30); // 设置分钟
calendar.set(Calendar.SECOND, 0);
// 转换为Date对象
Date date = calendar.getTime();
Date 操作
-
.getTime() 获取时间戳
-
Date.from() 其他日期对象转Date
-
时间格式控制
import java.text.SimpleDateFormat;Date startTime = new Date(); // 假设 startTime 是当前时间
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String formattedDate = sdf.format(startTime);
转换
- Date 转 LocalDate
// 将 Date 转 LocalDate
// 假设 startTime 是一个 Date 对象
LocalDate localDate = startTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
- Date 转 LocalDateTime
// 将 Date 转 LocalDateTime
// 假设 startTime 是一个 Date 对象
LocalDate localDate = startTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
- LocalDate 转 Date
// localDate 为LocalDate 对象
Date newStartTime = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
- localDateTime 转 Date
// localDateTime 为LocalDateTime 对象
Date newStartTime = Date.from(Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
DateUtil
当月日期获取
// 当月的第一天
startTime = DateUtil.offsetDay(DateUtil.parse(time, "yyyy-MM"), 0);
// 获取 当月数据 最后一天
endTime = DateUtil.offsetDay(DateUtil.parse(time, "yyyy-MM"), -1);
- DateUtil.parse(time,"yyyy-MM") 字符串 转Date
- DateUtils.getNowDate() 获取现在的日期时间
TEST
依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency>
注解
@SpringBootTest(classes = BianQueIphmsApplication.class) @ExtendWith(SpringExtension.class)
获取对象的值和属性
Class<?> aClass = iphmsAnalysis.getClass(); Field[] declaredFields = aClass.getDeclaredFields(); for (Field declaredField : declaredFields) { declaredField.setAccessible(true); // 属性名 String name = declaredField.getName(); System.out.println(name); System.out.println(declaredField.getType()); try { // 属性值 Object o = declaredField.get(iphmsAnalysis); System.out.println(o); } catch (IllegalAccessException e) { throw new RuntimeException(e); } }
json 处理
JSON.parseArray(rangeName, String.class)
debug 开启
<logger name="com.bianque" level="debug" />