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" />

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/949723.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

gesp(C++一级)(17)洛谷:B4062:[GESP202412 一级] 温度转换

gesp(C一级)&#xff08;17&#xff09;洛谷&#xff1a;B4062&#xff1a;[GESP202412 一级] 温度转换 题目描述 小杨最近学习了开尔文温度、摄氏温度和华氏温度的转换。令符号 K K K 表开尔文温度&#xff0c;符号 C C C 表摄氏温度&#xff0c;符号 F F F 表华氏温度&am…

windows ping ssh

问题解决1&#xff1a;局域网内&#xff0c;为啥别人ping不到我的IP 问题解决2&#xff1a;ssh连接windows10拒绝连接 第一步&#xff1a;ssh使用的22端口&#xff0c;首先确认windows10的22端口是否开启。 –开启步骤 1.控制面板–>Windws Defender 防火墙–>高级设置…

《Rust权威指南》学习笔记(二)

枚举enum 1.枚举的定义和使用如下图所示&#xff1a; 定义时还可以给枚举的成员指定数据类型&#xff0c;例如&#xff1a;enum IpAddr{V4(u8, u8, u8, u8),V6(String),}。枚举的变体都位于标识符的命名空间下&#xff0c;使用::进行分隔。 2.一个特殊的枚举Option&#xff0…

科研绘图系列:R语言单细胞数据常见的可视化图形

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载导入数据数据预处理图1图2图3图4图5图6系统信息参考介绍 单细胞数据常见的可视化图形 因为本教程是单细胞数据,因此运行本画图脚本需要电脑的内存最少32Gb 加载…

打造三甲医院人工智能矩阵新引擎(二):医学影像大模型篇--“火眼金睛”TransUNet

一、引言 1.1 研究背景与意义 在现代医疗领域,医学影像作为疾病诊断与治疗的关键依据,发挥着不可替代的作用。从传统的X射线、CT(计算机断层扫描)到MRI(磁共振成像)等先进技术,医学影像能够直观呈现人体内部结构,为医生提供丰富的诊断信息,涵盖疾病识别、病灶定位、…

IP查询于访问控制保护你我安全

IP地址查询 查询方法&#xff1a; 命令行工具&#xff1a; ①在Windows系统中&#xff0c;我们可以使用命令提示符&#xff08;WINR&#xff09;查询IP地址&#xff0c;在弹窗中输入“ipconfig”命令查看本地网络适配器的IP地址等配置信息&#xff1b; ②在Linux系统中&…

2025新春烟花代码(一)HTML5夜景放烟花绽放动画效果

标题预览效果 标题HTML代码 <!DOCTYPE html> <html lang"en"> <script>var _hmt _hmt || [];(function () {var hm document.createElement("script");hm.src "https://hm.baidu.com/hm.js?45f95f1bfde85c7777c3d1157e8c2d34&…

【Rust自学】10.6. 生命周期 Pt.2:生命周期的语法与例子

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 10.6.1. 生命周期标注语法 生命周期的标注并不会改变引用的生命周期长度。如果某个函数它制定了泛型生命周期参数&#xff0c;那么它就可…

【C语言程序设计——选择结构程序设计】求一元二次方程的根(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 相关知识 sqrt() 函数 编程要求 测试说明 通关代码 测试结果 任务描述 本关任务&#xff1a;根据求根公式&#xff0c;计算并输出一元二次方程的两个实根&#xff0c;要求精确道小数点后2位。要求方程系数从键盘输入。如果输入的系数不满足求…

【C++数据结构——图】图的邻接矩阵和邻接表的存储(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 相关知识 1. 带权有向图 2. 图的邻接矩阵 3. 图的邻接表 测试说明 通关代码 测试结果 任务描述 本关任务&#xff1a;编写一个程序实现图的邻接矩阵和邻接表的存储。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a; 带权有向图…

java 转义 反斜杠 Unexpected internal error near index 1

代码&#xff1a; String str"a\\c"; //出现异常&#xff0c;Unexpected internal error near index 1 //System.out.println(str.replaceAll("\\", "c"));//以下三种都正确 System.out.println(str.replace(\\, c)); System.out.println(str.r…

QML学习(七) 学习QML时,用好Qt设计器,快速了解各个组件的属性

在初步学习QML时&#xff0c;特别建议看看Qt设计器&#xff0c;先利用Qt Quick设计师的使用&#xff0c;快速的对Qt Quick的各个组件及其常用的属性&#xff0c;有个初步的了解和认识。如果初始学习一上来直接以代码形式开干&#xff0c;很容易一头雾水。而设计器以最直白的所见…

Flutter 鸿蒙化 flutter和鸿蒙next混和渲染

前言导读 这一个节课我们讲一下PlatformView的是使用 我们在实战中有可能出现了在鸿蒙next只加载一部分Flutter的情况 我们今天就讲一下这种情况具体实现要使用到我们的PlatformView 效果图 具体实现: 一、Native侧 使用 DevEco Studio工具打开 platform_view_example\oho…

js逆向实战(1)-- 某☁️音乐下载

下载某云音乐源文件.mp4格式 首先随便点进一首歌&#xff0c;如图所示获取该音乐id&#xff0c;然后点击播放键&#xff0c;打开F12进行查询XHR 由此可知&#xff0c;实际请求网址是 https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token「你的token」url需带…

学习随笔:word2vec在win11 vs2022下编译、测试运行

word2vec 官网word2vec的本质是在自然语言词条数据集与计算机浮点数据集之间建立双射关系。word2vec建立的数据集最厉害的一点是&#xff0c;将自然语言词条数据集内部的推理过程&#xff0c;映射到了计算机浮点数据集内部的数值运算。我个人感觉理解这个数据映射方式是理解AI大…

开源数据集成平台白皮书重磅发布《Apache SeaTunnel 2024用户案例合集》!

2025年新年临近&#xff0c;Apache SeaTunnel 社区用户案例精选&#x1f4d8;也跟大家见面啦&#xff01;在过去的时间里&#xff0c;SeaTunnel 社区持续成长&#xff0c;吸引了众多开发者的关注与支持。 为了致谢一路同行的伙伴&#xff0c;也为了激励更多人加入技术共创&…

Milvus×合邦电力:向量数据库如何提升15%电价预测精度

01. 全球能源市场化改革下的合邦电力 在全球能源转型和市场化改革的大背景下&#xff0c;电力交易市场正逐渐成为优化资源配置、提升系统效率的关键平台。电力交易通过市场化手段&#xff0c;促进了电力资源的有效分配&#xff0c;为电力行业的可持续发展提供了动力。 合邦电力…

Day21补代码随想录_20241231_669.修剪二叉搜索树|108.将有序数组转换为二叉搜索树|538.把二叉搜索树转换为累加树

669.修剪二叉搜索树 题目 【比增加和删除节点难的多】 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界 low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在 [low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即&#xff0c;…

机场安全项目|基于改进 YOLOv8 的机场飞鸟实时目标检测方法

目录 论文信息 背景 摘要 YOLOv8模型结构 模型改进 FFC3 模块 CSPPF 模块 数据集增强策略 实验结果 消融实验 对比实验 结论 论文信息 《科学技术与工程》2024年第24卷第32期刊载了中国民用航空飞行学院空中交通管理学院孔建国, 张向伟, 赵志伟, 梁海军的论文——…

【USRP】教程:在Macos M1(Apple芯片)上安装UHD驱动(最正确的安装方法)

Apple芯片 前言安装Homebrew安装uhd安装gnuradio使用b200mini安装好的路径下载固件后续启动频谱仪功能启动 gnu radio关于博主 前言 请参考本文进行安装&#xff0c;好多人买了Apple芯片的电脑&#xff0c;这种情况下&#xff0c;可以使用UHD吗&#xff1f;答案是肯定的&#…