当前位置: 首页 > article >正文

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

详细步骤 

  1. 官网地址:Jenkins
  2. 启动: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" />


http://www.kler.cn/a/470540.html

相关文章:

  • java 转义 反斜杠 Unexpected internal error near index 1
  • 25上软考中级【嵌入式系统设计师】易混淆知识点
  • STM32 软件I2C读写
  • C# 检查一个字符串是否是科学计数法格式字符串 如 1.229266E+01
  • 【C++】字符串与字符数|组操作详解:strcpy 和 strcat 的使用与解析
  • 【three.js】搭建环境
  • 【苏德矿高等数学】第1讲:有界函数、无界函数、复合函数
  • DeepSpeed是什么,怎样使用
  • 个性化电影推荐系统|Java|SSM|JSP|
  • 【形式篇】年终总结怎么写:PPT如何将内容更好地表现出来
  • 5.C语言流程控制语句详解:if、switch、while、for、break、continue等
  • Vue Router v3.x 迁移到 v4.x(两者的区别)【路由篇】
  • 【模电】功率放大电路总结
  • 【C++数据结构——查找】二分查找(头歌实践教学平台习题)【合集】
  • 【渗透测试术语总结】
  • Zero to JupyterHub with Kubernetes 下篇 - Jupyterhub on k8s
  • 人工智能的发展领域之GPU加速计算的应用概述、架构介绍与教学过程
  • 【H3CNE邓方鸣】路由协议概述+2025.1.5
  • SQLite 的未来发展与展望
  • 【vue3封装element-plus的反馈组件el-drawer、el-dialog】
  • 解决 IntelliJ IDEA 中 Tomcat 日志乱码问题的详细指南
  • STLG_01_14_程序设计C语言 - 函数与程序结构
  • 基于ROS先验地图的机器人自主定位与导航SLAM
  • 基于单片机的直流稳压电源的设计(论文+源码)
  • 【AIGC-ChatGPT进阶提示词指令】AI美食助手的设计与实现:Lisp风格系统提示词分析
  • jenkins入门9--参数化构建