java开发springoot
阅读理解
- 命令之间空一行:表示前面的是配置
- 红色背景:表示待验证
- 蓝色背景:表示常用或推荐
- 绿色背景:注意/推荐
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 {@Beanpublic 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: truesetting: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.DruidDataSourcedriver-class-name: com.mysql.jdbc.Driverjdbc-url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false&allowMultiQueries=true&serverTimezone=GMT%2B8&useSSL=falseusername: rootpassword: rootsecondary:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.jdbc.Driverjdbc-url: jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false&allowMultiQueries=true&serverTimezone=GMT%2B8&useSSL=falseusername: rootpassword: 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")@Primarypublic 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;}@Beanpublic 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); // }@Beanpublic PlatformTransactionManager transactionManager(){return new DataSourceTransactionManager(dynamicDataSource());}@Beanpublic 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 {@Overrideprotected 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){//获得当前访问的classClass<?> 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 {@Beanpublic TaskScheduler taskScheduler() {ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();scheduler.setPoolSize(10); // 设置线程池大小scheduler.initialize();return scheduler;} }
2.写异步类的@Async 异步方法
@Asyncpublic 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 数据对象*/@Deprecatedpublic 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)
json转对象
import com.alibaba.nacos.shaded.com.google.gson.Gson;
Gson gson = new Gson(); Test test= gson.fromJson(rawJson, Test.class);
debug 开启
<logger name="com.bianque" level="debug" />
AOP
1.导包
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId> </dependency>
2.创建Aop 类
@Aspect @Component public class IphmsServiceBraceletRecordControllerAop {@Before("execution(* com.aa(..))")public void parseBraceletData1before(JoinPoint joinPoint) {System.out.println("parseBraceletData1before");}}
- 路劲切入:execution()
* com.aa(com.bb) 具体的某个方法
- 注解切入:@annotation()
3启动类增加注解:@EnableAspectJAutoProxy
http 数据获取
@PostMapping("/test") @ApiOperation(value = "test") public AjaxResult<Boolean> Test(HttpServletRequest request) {StringBuilder jsonBuilder = new StringBuilder(); try (BufferedReader reader = request.getReader()) {char[] buffer = new char[1024];int read;while ((read = reader.read(buffer, 0, buffer.length)) != -1) {jsonBuilder.append(buffer, 0, read);} } catch (IOException e) {e.printStackTrace(); } return jsonBuilder.toString(); }
正则
- Pattern.compile("正则表达式") 获取正则表达式对象
- .matcher(string) 正则提取