首页
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
篇与
后端学习
的结果
2023-10-16
log4j异步打印日志
log4j异步打印日志介绍: 打印日志是程序开发中的常见操作,我们可以通过日志查看程序的运行状态和错误信息等,但如果我们一次打印的日志过多,那么线程将会被阻塞无法执行打印日志过后的操作,这就导致的程序的响应时间过久,体验感不好,因此我们需要对其进行优化。举个简单的例子来看看 这里我们打印100000条数据查看日志文件中的信息可以发现打印100000条数据需要1秒多的时间采用异步的方式打印日志 引入依赖 <dependency> <groupId>com.lmax</groupId> <artifactId>disruptor</artifactId> <version>3.4.2</version> </dependency>修改log4j的配置文件 (没有配置文件的请看上一篇文章 log4j包依赖冲突 ) 在启动类的main方法中设置异步加载 System.setProperty("Log4jContextSelector", "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");再次测试controller中的方法可以看到打印100000条数据从原来的花费 1s 多的时间经过优化后,只需要 95ms ,通过异步的方式打印效率的提升是显而易见的。
2023年10月16日
138 阅读
6 评论
0 点赞
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
swagger集成
介绍: swagger是一个文档api,我们使用apiPost测试的时候需要输入地址和各种参数,比较麻烦,我们采用集成swagger的方式自动生成文档,便于我们进行测试 引入依赖:<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency> 编写swagger配置文件: @Configuration @EnableSwagger2 public class SwaggerConfig { //配置swagger的bean实例 @Bean public Docket docket() { return new Docket(DocumentationType.SWAGGER_2) .groupName("wcy") //分组 .apiInfo(apiInfo()) //select()函数返回一个ApiSelectorBuilder实例,用来控制接口被swagger做成文档 .enable(true) //是否启动 .select() //用于指定扫描哪个包下的接口 .apis(RequestHandlerSelectors.basePackage("com.guardyou")) //选择所有的API,如果你想只为部分API生成文档,可以配置这里 .paths(PathSelectors.any()) //过滤什么路径 .build(); } //配置swagger的信息apiInfo private ApiInfo apiInfo() { return new ApiInfoBuilder() //用来自定义API的标题 .title("SwaggerAPI标题测试") //用来描述整体的API .description("swagger的描述信息") //创建人信息 .contact(new Contact("guardyou3" + "","http://localhost:8081/swagger-ui.html","xxx@qq.com")) //用于定义服务的域名 //.termsOfServiceUrl("") .version("1.0") //可以用来定义版本 .build(); } } 打开浏览器访问swagger-ui.html可以看到已经能够访问文档界面了,并且显示相应的controller,值得注意的是只有出现在controller中的实体类才会被扫描,否则是不会出现在文档中的。点开具体的方法可以看到他已经给我们介绍了具体的用法以及参数示例,我们可以直接进行调用,是不是非常的方便{alert type="success"}swagger常用注解:{callout color="#ef4d4d"}@Api: 作用在类上,表示对类的说明@ApiOperation: 作用在方法上,标注方法的用途@ApiParam: 作用在方法参数或者实体类属性上,表明参数信息,是否必须等描述信息@ApiModel :作用在实体类上,藐视实体信息@ApiModelProperty: 作用在实体类的属性上,描述属性信息@ApiIgnore: 作用在实体类属性上,忽略某个字段使其不显示在文档中{/callout}还有其他swagger相关注解,这里暂不列出{/alert}
2023年10月15日
147 阅读
48 评论
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 点赞