首页
Search
1
关于a标签的onclick事件可能会出现的问题
224 阅读
2
gitignore配置不生效问题
221 阅读
3
mapstruct的简单使用(可能会出现的问题)
194 阅读
4
2023/10/10 LeetCode
186 阅读
5
log4j包依赖冲突
181 阅读
默认分类
前端基础学习
后端学习
swagger
redis
日志管理
刷题记录
2023/10刷题记录
java常见问题
登录
Search
Guardyou3
累计撰写
10
篇文章
累计收到
334
条评论
首页
栏目
默认分类
前端基础学习
后端学习
swagger
redis
日志管理
刷题记录
2023/10刷题记录
java常见问题
页面
搜索到
4
篇与
java常见问题
的结果
2024-02-07
gitignore配置不生效问题
关于配置.gitignore文件不生效的问题我们在使用git进行代码管理的时候,通常不会将一些文件提交到代码仓库,比如说.idea文件,target目录等,这个时候我们需要在.gitignore文件中进行配置。需要注意一些问题:确保 .gitignore 文件被放在了项目的根目录下。检查 .gitignore 中设置的忽略规则,确保它们正确且符合语法规范。当已经提交了不需要的文件时,这个时候即使将对应不需要的文件正确配置在了.gieignore文件中也不会生效,因为此时文件已经被跟踪了,所以需要清除缓存,使用 git rm -r --cached .命令将所以缓存清空,这个时候配置就会正常生效了。
2024年02月07日
221 阅读
37 评论
1 点赞
2023-10-16
log4j包依赖冲突
springboot集成log4j导致依赖冲突问题引入依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> <version>2.4.2</version> </dependency>yaml文件指定log4j配置文件路径(log4j配置文件在文章末)logging: config: classpath:log4j-spring.xml启动springboot发现引入的log4j依赖包与之前的依赖产生了冲突此时我们需要将之前的依赖包排除通过该 maven helper 插件通过右键点击冲突的依赖包,选择exclude将其排除,此时再次启动发现已经正常启动查看配置文件中日志保存的目录也已经生成日志文件此时日志配置就成功完成了,除此之外如果遇到其他依赖包冲突的问题,也可以通过maven helper去查找,将冲突的包排除掉即可。附上:log4j配置文件<?xml version="1.0" encoding="UTF-8"?> <!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出--> <!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数--> <configuration status="INFO" monitorInterval="5"> <!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL --> <!--变量配置--> <Properties> <!-- 格式化输出:%date表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符--> <!-- %logger{36} 表示 Logger 名字最长36个字符 --> <property name="LOG_PATTERN" value="%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"/> <!-- 定义日志存储的路径 --> <property name="FILE_PATH" value="../log"/> <property name="FILE_NAME" value="frame.log"/> </Properties> <!--https://logging.apache.org/log4j/2.x/manual/appenders.html--> <appenders> <console name="Console" target="SYSTEM_OUT"> <!--输出日志的格式--> <PatternLayout pattern="${LOG_PATTERN}"/> <!--控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--> <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/> </console> <!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,适合临时测试用--> <File name="fileLog" fileName="${FILE_PATH}/temp.log" append="false"> <PatternLayout pattern="${LOG_PATTERN}"/> </File> <!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档--> <RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/info.log" filePattern="${FILE_PATH}/${FILE_NAME}-INFO-%d{yyyy-MM-dd}_%i.log.gz"> <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--> <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout pattern="${LOG_PATTERN}"/> <Policies> <!--interval属性用来指定多久滚动一次,默认是1 hour--> <TimeBasedTriggeringPolicy interval="1"/> <SizeBasedTriggeringPolicy size="10MB"/> </Policies> <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖--> <DefaultRolloverStrategy max="15"/> </RollingFile> <!-- 这个会打印出所有的warn及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档--> <RollingFile name="RollingFileWarn" fileName="${FILE_PATH}/warn.log" filePattern="${FILE_PATH}/${FILE_NAME}-WARN-%d{yyyy-MM-dd}_%i.log.gz"> <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--> <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout pattern="${LOG_PATTERN}"/> <Policies> <!--interval属性用来指定多久滚动一次,默认是1 hour--> <TimeBasedTriggeringPolicy interval="1"/> <SizeBasedTriggeringPolicy size="10MB"/> </Policies> <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖--> <DefaultRolloverStrategy max="15"/> </RollingFile> <!-- 这个会打印出所有的error及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档--> <RollingFile name="RollingFileError" fileName="${FILE_PATH}/error.log" filePattern="${FILE_PATH}/${FILE_NAME}-ERROR-%d{yyyy-MM-dd}_%i.log.gz"> <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--> <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/> <PatternLayout pattern="${LOG_PATTERN}"/> <Policies> <!--interval属性用来指定多久滚动一次,默认是1 hour--> <TimeBasedTriggeringPolicy interval="1"/> <SizeBasedTriggeringPolicy size="10MB"/> </Policies> <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖--> <DefaultRolloverStrategy max="15"/> </RollingFile> </appenders> <!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。--> <!--然后定义loggers,只有定义了logger并引入的appender,appender才会生效--> <loggers> <!--过滤掉spring和mybatis的一些无用的DEBUG信息--> <logger name="org.mybatis" level="info" additivity="false"> <AppenderRef ref="Console"/> </logger> <!--监控系统信息--> <!--若是additivity设为false,则子Logger只会在自己的appender里输出,而不会在父Logger的appender里输出。--> <Logger name="org.springframework" level="info" additivity="false"> <AppenderRef ref="Console"/> </Logger> <root level="info"> <appender-ref ref="Console"/> <appender-ref ref="RollingFileInfo"/> <appender-ref ref="RollingFileWarn"/> <appender-ref ref="RollingFileError"/> <appender-ref ref="fileLog"/> </root> </loggers> </configuration>
2023年10月16日
181 阅读
35 评论
0 点赞
2023-10-15
mapstruct的简单使用(可能会出现的问题)
MapStruct是什么简介: 在我们日常的Java开发工作中,经常会遇到模型对象的转化,例如将DTO转化为PO,进行数据模型转换的方式有很多种,与动态映射框架相比,MapStruct通过使用普通方法getter、setter方法进行快速模型转换的实现,而不是反射的形式,效率很高,这里简单介绍一下其用法。{callout color="#ef4d93"}简洁版引入依赖编写Mapper接口,配置转换方法直接调用mapper接口中的方法直接看文章末尾{/callout}以分页查询作为一个例子,将Req和Dto进行转换,示例所使用的的类: UserPo:@TableName("user") @Data public class UserPo extends BaseEntity implements Serializable { @TableId(value = "id",type = IdType.AUTO) private Long id; private String name; private Integer age; } UserDTO:@Data public class UserDto { private String name; private Integer age; private Integer pageSize; private Integer pageIndex; } UserListReq:@Data public class UserListReq { private Integer pageSize; private Integer pageIndex; } 封装返回对象 PageResult@Data public class PageResult<T> implements Serializable { private Long total; private Long size; private Long current; private Long pages; private List<T> records = Collections.emptyList(); public void loadData(IPage<T> pageData) { this.setCurrent(pageData.getCurrent()); this.setSize(pageData.getSize()); this.setTotal(pageData.getTotal()); this.setRecords(pageData.getRecords()); this.setPages(pageData.getPages()); } }UserService 层中的代码: @Override public PageResult<UserPo> getUserPage(UserDto userDto) { IPage<UserPo> userPoPage = new Page<>(userDto.getPageIndex(),userDto.getPageSize()); IPage<UserPo> userPage = userMapper.selectPage(userPoPage, null); PageResult<UserPo> pageResult = new PageResult<>(); pageResult.loadData(userPage); return pageResult; }传统的BeanUtils的模型转换用法: controller层中的代码,Result是封装的一个统一返回类,这里不展示: @GetMapping("/page") public Result page(@RequestBody UserListReq userListReq) { UserDto userDto = new UserDto(); BeanUtils.copyProperties(userListReq,userDto); return Result.ok(userService.getUserPage(userDto)); }使用BeanUtils的方式直接进行模型转换,虽然看上去很简洁,但实际因为使用反射效率较低。下面我们采用MapStruct的方式进行转换 基础用法: 引入依赖:<dependencies> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>1.4.2.Final</version> </dependency> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.4.2.Final</version> </dependency> </dependencies>编写一个convert接口@Mapper public interface UserDtoConvert { UserDtoConvert INSTANCE = Mappers.getMapper(UserDtoConvert.class); // @Mapping(source = "pageIndex",target = "pageNo") UserDto convertReqToUserDTO(UserListReq userListReq); }如果说要转换的模型中的属性名称不同,可以通过@Mapping注解进行映射关系的配置,这里不进行演示。controller层中使用 @GetMapping("/page") public Result page(@RequestBody UserListReq userListReq) { UserDto userDto = UserDtoConvert.INSTANCE.convertReqToUserDTO(userListReq); return Result.ok(userService.getUserPage(userDto)); }只需要调用接口方法即可,使用方式非常简介,效率也很高。注意事项:导入@Mapper的时候不要导成mybatisPlus的包了 另一个可能会导致的问题:lombok和mapstruct之间的顺序问题lombok一定要在mapstruct之前,不然返回的对象属性值仍然为null查看编译后的文件 这是lombok在mapstruct之前生成的实现类如果lombok在mapstruct之后,那么生成的实现类就没有上图红色圆圈框起来的部分,直接返回new UserDto对象导致并没有进行属性复制。
2023年10月15日
194 阅读
71 评论
133 点赞
2023-10-11
BigDecimal的使用问题
关于使用BigDecimal会出现的几个常见问题介绍 :BigDecimal类在金融开发行业被广泛使用,不知道大家在使用BigDecimal的时候是否会出现一些问题,这里博主来介绍使用BigDecimal可能会导致的错误( 文章完整示例代码在底部 ){callout color="#ef4d4d"}问题一{/callout}demo1 :这里我们创建两个BigDecimal对象,使两个对象的值都为0.1,第一个bigDecimal1直接传入一个浮点数,第二个bigDecimal2通过valueOf的方式创建对象,那个如果我们运行这个测试,那么按照我们最初的想法,打印的值都为0.1才对,但是事实真是如此吗?下面我们来进行测试。demo1结果: 我们观察发现,第一个bigDecimal1的值为一长串的浮点数,它其实是一个0.1的近似值,而BigDecimal2的值为0.1,具体的原因其实是因为0.1无法被一个有限位的二进制表示出来,所以是一个0.1的近似值存在了BigDecimal中,而第二个值bigDecimal2是一个准确值,为什么呢?我们通过其源码来进行分析。我们可以发现在其源码中,返回的BigDecimal对象经过了Double的数值转换为一个字符串,此时不会出现精度问题注意:如果我们传入的值超过了double的范围,他也会出现精度问题 解决方法: 既然我们知道valueOf在底层帮我们进行了一个字符串转换,那么我们直接在创建BigDecimal对象的时候就直接传入一个字符串,那么我们不是就可以绕过这个问题了吗。 例子: 我们任意传入一个很大的值,可以发现并没有出现精度问题,因此我们就可以通过传入字符串的方式避免第一个陷阱。其实idea已经给了我们提示了:{callout color="#ef4d4d"}问题二{/callout}demo2: 这里我们创建两个BigDecimal对象,我们对其分别使用equals方法和compareTo方法进行值的比较demo2结果: 我们可以发现,通过equals方法进行比较的值是false,而compareTo方法返回0(true),为什么第一个方法的比较值为false呢?我们进入源码中查看问题分析: 通过观察发现,BigDecimal对象重写了Object类的equals方法,在此方法中首先对其 精度进行了比较 ,这也就是说如果两个对象的值在逻辑上是相同的,但因为精度不同的BigDecimal对象将不被认为其值相等,这就是为什么会返回false原因,而compareTo方法只比较数值,返回值为-1,0,1。因此我们如果要对两个BigDecimal对象进行数值比较的话,采用compareTo方法返回0即可说明相等,当然如果在某些情况需要强行让精度相同才认为数值相同的话,我们也可以使用equals方法进行比较,灵活运用就好{callout color="#ef4d4d"}问题三{/callout} demo3: 我们定义了两个BigDecimal对象,值分别为1.0和3.0,我们让两个对象相除,这个时候是否会有问题?我们知道1除以3的结果是一个循环小数0.3333...,如果我们执行程序能够正常打印吗?demo3结果: 发现此时抛出了一个异常,其大致的意思就是没有指定精度,返回的结果必须是一个精确的数值。问题解决: 其实在BigDecimal已经帮我们解决了这个问题了我们可以使用divide的一个重载方法,其第一个参数是divisor是除数,第二个参数scale是精度,也就是返回的小数位数,第三个参数是RoundingMode是一个枚举类,我们可以通过其指定保留精度的规则,比如四舍五入或者直接抹掉。 修改后的代码: 此时我们指定保留两位小数,并且采用四舍五入的方式(RoundingMode.HALF_UP),发现正确打印出来精确的结果0.33{callout color="#ef4d5d"}这里列出几种常见的RoundingMode类型RoundingMode.UP:向远离0的方向舍入(5.5 -> 6)(-5.5 -> -6)RoundingMode.DOWN:向靠近0的方向舍入(1.1 -> 1)(-5.5 -> -5)RoundingMode.CEILING:向正无穷方向舍入(1.1 -> 2)(-5.5 -> -5)RoundingMode.FLOOR:向负无穷方向舍入(1.6 -> 1)(-1.1 -> -2)还有另外4种模式,感兴趣的也可以直接翻看源码,这里就不一一列出了{/callout}综上就是使用BigDecimal可能会出现的三种问题 demo源码:public class BigDecimalTest { @Test public void bigDecimalTest1() { BigDecimal bigDecimal1 = new BigDecimal(0.1); BigDecimal bigDecimal2 = BigDecimal.valueOf(0.1); System.out.println("bigDecimal1 = "+bigDecimal1); System.out.println("bigDecimal2 = "+bigDecimal2); System.out.println(new BigDecimal("11111111111111111111111111111.222222222")); } @Test public void bigDecimalTest2() { BigDecimal bigDecimal1 = new BigDecimal("0.10"); BigDecimal bigDecimal2 = new BigDecimal("0.1"); System.out.println("equals方法比较结果:"+bigDecimal1.equals(bigDecimal2)); System.out.println("compareTo方法比较结果:"+bigDecimal1.compareTo(bigDecimal2)); } @Test public void bigDecimalTest3() { BigDecimal bigDecimal1 = new BigDecimal("1.0"); BigDecimal bigDecimal2 = new BigDecimal("3.0"); BigDecimal bigDecimal3 = bigDecimal1.divide(bigDecimal2,2, RoundingMode.HALF_UP); System.out.println("两个数相除的结果:"+bigDecimal3); } }
2023年10月11日
71 阅读
6 评论
1 点赞