Daily-Blog项目前台日志(中)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Daily-Blog项目前台日志(中)

分页查询文章列表


需求


在首页查询文章页面都有文章列表 ,首页 :查询所有文章


分类页面: 查询对应分类的文章列表


要求 ::1. 只能查询正式发布的文章 2. 置顶文章要显示在最前面


接口设计

image-20230312143807864.png


实现


//todo 文章分页
@GetMapping("/articleList")
//如果在请求路径后面直接 /+值的 需要使用 @PathVariable
//如果是从请求体中获取出来的就需要加上 @RequestBody
public ResponseResult articleList(Integer pageNum, Integer pageSize, Long categoryId){
    return articleService.articleList(pageNum,pageSize,categoryId);
}

按照要求 ,我们需要将查询到的信息传入前端, 但是 不能将全部信息传入 ,所以就需要将查询到的信息进行封装


List<ArticleListVo> articleListVo = BeanCopyUtils.copyBeanList(page.getRecords(), ArticleListVo.class);

//todo 文章分页
/*
在首页查询文章页面都有文章列表  ,首页 :查询所有文章
分类页面: 查询对应分类的文章列表
要求 ::1. 只能查询正式发布的文章 2. 置顶文章要显示在最前面
 */
@Override
public ResponseResult articleList(Integer pageNum, Integer pageSize, Long categoryId) {
    LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper();
    //如果有categoryId ,那么查询和传入的就需要相同
    queryWrapper.eq(Objects.nonNull(categoryId) && categoryId > 0,Article::getCategoryId,categoryId);
    //状态 : 正式发布
    queryWrapper.eq(Article::getStatus, SystemConstants.ARTICLE_STATUS_PUT);
    //置顶的文章(对isTop进行排序)
    queryWrapper.orderByDesc(Article::getIsTop);
    //分页查询
    Page<Article> pageN = new Page<>(pageNum,pageSize);
    Page<Article> page = page(pageN, queryWrapper);
    //封装查询结果
    List<ArticleListVo> articleListVo = BeanCopyUtils.copyBeanList(page.getRecords(), ArticleListVo.class);
    PageVo pageVo = new PageVo(articleListVo, page.getTotal());
    return ResponseResult.okResult(pageVo);
}

因为我们封装的是categoryName,但是查询出来的确实categoryId,所以需要在查询后进行给categoryName赋值


for (Article article  : records){
    Category category = categoryService.getById(article.getCategoryId());
    article.setCategoryName(category.getName());
}


分页配置


/**
 * myBatisPlus分页配置
 */
@Configuration
public class MyBatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor mb = new MybatisPlusInterceptor();
        mb.addInnerInterceptor(new PaginationInnerInterceptor());
        return mb;
    }
}


修改时间格式配置

在WebConfig中


//todo 修改时间格式 【yyyy-MM-dd HH:mm:ss】 
// 其实也可以直接在相关字段上加注解
// @JsonFormat(timezone="GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
// 只是这样做可以使所有的时间格式都转换
@Bean//使用@Bean注入fastJsonHttpMessageConvert
public HttpMessageConverter fastJsonHttpMessageConverters() {
    //1.需要定义一个Convert转换消息的对象
    FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
    FastJsonConfig fastJsonConfig = new FastJsonConfig();
    fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
    fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
   // SerializeConfig.globalInstance.put(Long.class, ToStringSerializer.instance);
    fastJsonConfig.setSerializeConfig(SerializeConfig.globalInstance);
    fastConverter.setFastJsonConfig(fastJsonConfig);
    HttpMessageConverter<?> converter = fastConverter;
    return converter;
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    converters.add(fastJsonHttpMessageConverters());
}


文章详情接口


需求


要在文章列表页面点击阅读全文时能够跳转到文章详情页面 ,可以让用户阅读文章正文


要求: 1. 要在文章详情中展示其分类名


接口信息

image-20230312164517847.png



响应格式


image-20230312164556027.png

实现

//todo 查询文章详情
  @GetMapping("/{id}")
  public ResponseResult getArticleDetails(@PathVariable("id") Long id){
      return articleService.getArticleDetails(id);
  }
//todo 查询文章详情
/*
要在文章列表页面点击阅读全文时能够跳转到文章详情页面 ,可以让用户阅读文章正文
要求: 1. 要在文章详情中展示其分类名
 */
@Override
public ResponseResult getArticleDetails(Long id) {
    //根据文章id查询文章
    Article article = getById(id);
    //转换成vo格式
    ArticleDetailVo articleDetailVo = BeanCopyUtils.copyBean(article, ArticleDetailVo.class);
    //根据分类id查询分类名
    Long categoryId = articleDetailVo.getCategoryId();
    Category category = categoryService.getById(categoryId);
    if(category == null){
        return ResponseResult.okResult(articleDetailVo);
    }
    articleDetailVo.setCategoryName(category.getName());
    //封装响应,返回
    return ResponseResult.okResult(articleDetailVo);
}


友链查询


需求

如果进行评论 ,那么就可以将用户的网站名、地址、描述、logo放上去


接口设计

image-20230312170340390.png


响应格式

image-20230312170721528.png


表信息

image-20230312170447017.png


实现

@RestController
@RequestMapping("/link")
public class LinkController {
    @Resource
    private LinkService linkService;
    //todo 获取所有友链
    @GetMapping("/getAllLink")
    public ResponseResult getAllLink(){
        return linkService.getAllLink();
    }
}


@Service("linkService")
public class LinkServiceImpl extends ServiceImpl<LinkMapper, Link> implements LinkService {
    // todo 获取所有友链
    /*
     如果进行评论 ,那么就可以将用户的网站名、地址、描述、logo放上去
     */
    @Override
    public ResponseResult getAllLink() {
        //查询所有审核通过的
        LambdaQueryWrapper<Link> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(Link::getStatus, SystemConstants.LINK_STATUS_NORMAL);
        List<Link> links = list(queryWrapper);
        List<LinkVo> linkVos = BeanCopyUtils.copyBeanList(links, LinkVo.class);
        return ResponseResult.okResult(linkVos);
    }
}


评论列表


接口

image-20230316110227487.pngimage-20230316110924073.png


响应


image-20230316112155537.png


需求

不仅需要实现评论 ,还要实现”父子评论“


表分析

image-20230316110441239.png


实现


@RestController
@RequestMapping("/comment")
public class CommentController {
    @Autowired
    private CommentService commentService;
    //todo 评论列表
    @GetMapping("/commentList")
    public ResponseResult commentList(Long articleId ,Integer pageNum , Integer pageSize){
        return commentService.commentList(articleId,pageNum,pageSize);
    }
}

service层


@Service
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements CommentService {
    @Resource
    private UserService userService;
    //todo 评论列表
    @Override
    public ResponseResult commentList(Long articleId, Integer pageNum, Integer pageSize) {
        //根据文章id 所对应的 根评论(root_id = -1)
        LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();
        //对articleId进行判断
        queryWrapper.eq(Comment::getArticleId,articleId);
        queryWrapper.eq(Comment::getRootId, SystemConstants.ARTICLE_ROOT_COMMENT);
        //分页查询
        Page<Comment> pageN = new Page<>(pageNum,pageSize);
        Page<Comment> page = page(pageN, queryWrapper);
        //封装返回
        List<CommentVo> list = toCommentVoList(page.getRecords());
        return ResponseResult.okResult(new PageVo(list,page.getTotal()));
    }
    //comment 集合 和commentVo 集合的拷贝
    private List<CommentVo> toCommentVoList(List<Comment> list){
        List<CommentVo> commentVos = BeanCopyUtils.copyBeanList(list, CommentVo.class);
        //遍历vo
        for (CommentVo commentVo : commentVos){
            //通过createBy查询用户的昵称并且赋值
            String nickName = userService.getById(commentVo.getCreateBy()).getNickName();
            commentVo.setUsername(nickName);
            //通过 toCommentUserId查询用户ude昵称并赋值
            //如果 toCommentUserId != -1才进行查询
            if (commentVo.getToCommentId() != -1){
                String toCommentName = userService.getById(commentVo.getToCommentId()).getNickName();
                commentVo.setToCommentUserName(toCommentName);
            }
        }
        return commentVos;
    }
}


查询根评论对应的子评论


也就是多条评论


image-20230316122832752.png


//查询所有根评论对应的子评论的集合 ,并且赋值给对应的属性children
 for (CommentVo commentVo : list){
     //查询对应子评论
     List<CommentVo> children = getChildren(commentVo.getId());
     commentVo.setChildren(children);
 }


service层


/todo 评论列表
@Override
public ResponseResult commentList(Long articleId, Integer pageNum, Integer pageSize) {
    //根据文章id 所对应的 根评论(root_id = -1)
    LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();
    //对articleId进行判断
    queryWrapper.eq(Comment::getArticleId,articleId);
    queryWrapper.eq(Comment::getRootId, SystemConstants.ARTICLE_ROOT_COMMENT);
    //分页查询
    Page<Comment> pageN = new Page<>(pageNum,pageSize);
    Page<Comment> page = page(pageN, queryWrapper);
    //封装返回
    List<CommentVo> list = toCommentVoList(page.getRecords());
    //查询所有根评论对应的子评论的集合 ,并且赋值给对应的属性children
    for (CommentVo commentVo : list){
        //查询对应子评论
        List<CommentVo> children = getChildren(commentVo.getId());
        commentVo.setChildren(children);
    }
    return ResponseResult.okResult(new PageVo(list,page.getTotal()));
}
//todo 根据根评论的id查询对应的子评论的集合
private List<CommentVo> getChildren(Long commentId){
    LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.eq(Comment::getRootId,commentId);
    List<Comment> list = list(queryWrapper);
    //封装成为CommentVo,然后返回
    return toCommentVoList(list);
}
//comment 集合 和commentVo 集合的拷贝
private List<CommentVo> toCommentVoList(List<Comment> list){
    List<CommentVo> commentVos = BeanCopyUtils.copyBeanList(list, CommentVo.class);
    //遍历vo
    for (CommentVo commentVo : commentVos){
        //通过createBy查询用户的昵称并且赋值
        String nickName = userService.getById(commentVo.getCreateBy()).getNickName();
        commentVo.setUsername(nickName);
        //通过 toCommentUserId查询用户ude昵称并赋值
        //如果 toCommentUserId != -1才进行查询
        if (commentVo.getToCommentId() != -1){
            String toCommentName = userService.getById(commentVo.getToCommentId()).getNickName();
            commentVo.setToCommentUserName(toCommentName);
        }
    }
    return commentVos;
}


发表评论


请求


image-20230316124356854.pngimage-20230316124520194.png


如果是友链 type为 1


还需要有请求体


实现


package com.blog.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.blog.domain.ResponseResult;
import com.blog.domain.entity.Comment;
import com.blog.domain.entity.LoginUser;
import com.blog.domain.entity.User;
import com.blog.domain.vo.CommentVo;
import com.blog.domain.vo.PageVo;
import com.blog.enums.AppHttpCodeEnum;
import com.blog.exception.SystemException;
import com.blog.mapper.CommentMapper;
import com.blog.service.CommentService;
import com.blog.service.UserService;
import com.blog.utils.BeanCopyUtils;
import com.blog.utils.SecurityUtils;
import com.blog.utils.SystemConstants;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.sql.rowset.BaseRowSet;
import java.util.List;
import java.util.Objects;
@Service
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements CommentService {
    @Resource
    private UserService userService;
    //todo 评论列表
    @Override
    public ResponseResult commentList(Long articleId, Integer pageNum, Integer pageSize) {
        //根据文章id 所对应的 根评论(root_id = -1)
        LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();
        //对articleId进行判断
        queryWrapper.eq(Comment::getArticleId,articleId);
        queryWrapper.eq(Comment::getRootId, SystemConstants.ARTICLE_ROOT_COMMENT);
        //分页查询
        Page<Comment> pageN = new Page<>(pageNum,pageSize);
        Page<Comment> page = page(pageN, queryWrapper);
        //封装返回
        List<CommentVo> list = toCommentVoList(page.getRecords());
        //查询所有根评论对应的子评论的集合 ,并且赋值给对应的属性children
        for (CommentVo commentVo : list){
            //查询对应子评论
            List<CommentVo> children = getChildren(commentVo.getRootId());
            commentVo.setChildren(children);
        }
        return ResponseResult.okResult(new PageVo(list,page.getTotal()));
    }
    //todo 添加评论
    @Override
    public ResponseResult addComment(Comment comment) {
        //评论内容不能为空
        if(!StringUtils.hasText(comment.getContent())){
            throw new SystemException(AppHttpCodeEnum.CONTENT_NOT_NULL);
        }
        save(comment);
        return ResponseResult.okResult();
    }
    //todo 根据根评论的id查询对应的子评论的集合
    private List<CommentVo> getChildren(Long commentId){
        LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Comment::getRootId,commentId);
        queryWrapper.orderByAsc(Comment::getCreateTime);
        List<Comment> list = list(queryWrapper);
        //封装成为CommentVo,然后返回
        return toCommentVoList(list);
    }
    //todo comment 集合 和commentVo 集合的拷贝
    private List<CommentVo> toCommentVoList(List<Comment> list){
        List<CommentVo> commentVos = BeanCopyUtils.copyBeanList(list, CommentVo.class);
        //遍历vo
        for (CommentVo commentVo : commentVos){
            //通过createBy查询用户的昵称并且赋值
            String nickName = userService.getById(commentVo.getCreateBy()).getNickName();
            commentVo.setUsername(nickName);
            //通过 toCommentUserId查询用户ude昵称并赋值
            //如果 toCommentUserId != -1才进行查询
            if (commentVo.getToCommentUserId() != -1){
                String toCommentUserName = userService.getById(commentVo.getToCommentUserId()).getNickName();
                commentVo.setToCommentUserName(toCommentUserName);
            }
        }
        return commentVos;
    }
}


友链评论


接口

image-20230318111815616.png


实现


@GetMapping("/linkCommentList")
public ResponseResult listCommentList(Integer pageNum , Integer pageSize){
    return commentService.commentList(SystemConstants.COMMENT_TYPE_FRIEND,null,pageNum,pageSize);
}
@Service
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements CommentService {
    @Resource
    private UserService userService;
    //todo 评论列表
    @Override
    public ResponseResult commentList(String commentType, Long articleId, Integer pageNum, Integer pageSize) {
        //根据文章id 所对应的 根评论(root_id = -1)
        LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();
        //对articleId进行判断  ,必须是文章评论再显示这个条件
        queryWrapper.eq(SystemConstants.COMMENT_TYPE_ARTICLE.equals(commentType),Comment::getArticleId,articleId);
        queryWrapper.eq(Comment::getRootId, SystemConstants.ARTICLE_ROOT_COMMENT);
        //评论类型
        queryWrapper.eq(Comment::getType,commentType);
        //分页查询
        Page<Comment> pageN = new Page<>(pageNum,pageSize);
        Page<Comment> page = page(pageN, queryWrapper);
        //封装返回
        List<CommentVo> list = toCommentVoList(page.getRecords());
        //查询所有根评论对应的子评论的集合 ,并且赋值给对应的属性children
        for (CommentVo commentVo : list){
            //查询对应子评论
            List<CommentVo> children = getChildren(commentVo.getRootId());
            commentVo.setChildren(children);
        }
        return ResponseResult.okResult(new PageVo(list,page.getTotal()));
    }
}


个人中心


接口image-20230318125856965.png



表分析image-20230318125957961.png


实现


@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    @GetMapping("/userInfo")
    public ResponseResult userInfo(){
        return userService.userInfo();
    }
}


@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    //todo 用户中心
    @Override
    public ResponseResult userInfo() {
        //获取当前用户
        Long userId = SecurityUtils.getUserId();
        //根据当前用户id查询当前用户
        User user = getById(userId);
        //封装成userInfoVo返回
        UserInfoVo userInfoVo = BeanCopyUtils.copyBean(user, UserInfoVo.class);
        return ResponseResult.okResult(userInfoVo);
    }
}


个人信息curd


头像上传—-使用七牛云

image-20230318132126703.png


首先上传至web应用服务器 ,然后再从web服务器上传至 oss


接口


上传文件需求 :image-20230318141309454.png




更新个人信息需求 :

image-20230318145103396.png



实现

上传文件

@RestController
public class UploadController {
    @Autowired
    private UploadService uploadService;
    @PostMapping("/upload")
    public ResponseResult uploadImg(MultipartFile img){
        return uploadService.uploadImg(img);
    }
}
/**
 * 上传文件到七牛云
 */
@ConfigurationProperties(prefix = "oss")
@Service
@Data
public class UploadServiceImpl implements UploadService {
    //todo 实现文件的上传
    @Override
    public ResponseResult uploadImg(MultipartFile img) {
        //判断文件的大小
        //获取原始文件名进行判断
        String originalFilename = img.getOriginalFilename();
        if(!originalFilename.endsWith(".png") && !originalFilename.endsWith(".jpg")){
            return ResponseResult.errorResult(AppHttpCodeEnum.FILE_TYPE_ERROR);
        }
        //如果通过,上传文件到oss
        String url = uploadOSS(img);
        return ResponseResult.okResult(url);
    }
    private String accessKey;
    private String secretKey;
    private String bucket;
    private String uploadOSS(MultipartFile imgFile){
        //构造一个带指定 Region 对象的配置类
        Configuration cfg = new Configuration(Region.autoRegion());
        //...其他参数参考类注释
        UploadManager uploadManager = new UploadManager(cfg);
        //默认不指定key的情况下,以文件内容的hash值作为文件名
        //images目录下的文件
        String originalFilename = imgFile.getOriginalFilename();
        String key = "images/"+originalFilename;
        try {
            //将前端传过来的imgFile文件转换成一个inputStream,然后
            InputStream inputStream = imgFile.getInputStream();
            Auth auth = Auth.create(accessKey, secretKey);
            String upToken = auth.uploadToken(bucket);
            try {
                Response response = uploadManager.put(inputStream,key,upToken,null, null);
                //解析上传成功的结果
                DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
                System.out.println(putRet.key);
                System.out.println(putRet.hash);
            } catch (QiniuException ex) {
                Response r = ex.response;
                System.err.println(r.toString());
                try {
                    System.err.println(r.bodyString());
                } catch (QiniuException ex2) {
                    //ignore
                }
            }
        } catch (Exception ex) {
            //ignore
        }
        //文件地址
        return "http://rrpanx30j.hd-bkt.clouddn.com/images/"+ originalFilename;
    }
}

更新个人信息实现 :


@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    @GetMapping("/userInfo")
    public ResponseResult userInfo(){
        return userService.userInfo();
    }
    @PutMapping("/userInfo")
    public ResponseResult updateUserInfo(@RequestBody User user){
        return userService.updateUserInfo(user);
    }
}


@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    //todo 用户中心
    @Override
    public ResponseResult userInfo() {
        //获取当前用户
        Long userId = SecurityUtils.getUserId();
        //根据当前用户id查询当前用户
        User user = getById(userId);
        //封装成userInfoVo返回
        UserInfoVo userInfoVo = BeanCopyUtils.copyBean(user, UserInfoVo.class);
        return ResponseResult.okResult(userInfoVo);
    }
    //todo 更新个人信息
    @Override
    public ResponseResult updateUserInfo(User user) {
        updateById(user);
        return ResponseResult.okResult();
    }
}


@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Autowired
    private PasswordEncoder passwordEncoder;
    //todo 注册用户
    @Override
    public ResponseResult register(User user) {
        //对数据进行非空判断 要求用户名 密码 等都不为空
        if(!StringUtils.hasText(user.getUserName())){
            ResponseResult.errorResult(AppHttpCodeEnum.USERNAME_NOT_NULL);
        }
        if( StringUtils.hasText(user.getPassword())){
            ResponseResult.errorResult(AppHttpCodeEnum.PASSWORD_NOT_NULL);
        }
        if( StringUtils.hasText(user.getEmail())){
            ResponseResult.errorResult(AppHttpCodeEnum.EMAIL_NOT_NULL);
        }
        if( StringUtils.hasText(user.getNickName())){
            ResponseResult.errorResult(AppHttpCodeEnum.NICKNAME_EXIST);
        }
        //判断数据库中是否存在用户
        if(usernameExist(user.getUserName())){
            //用户已经存在
            ResponseResult.errorResult(USERNAME_EXIST);
        }
        if(nickNameExist(user.getNickName())){
            //昵称存在
            ResponseResult.errorResult(NICKNAME_EXIST);
        }
        ///密码加密处理
        String encodePass = passwordEncoder.encode(user.getPassword());
        user.setPassword(encodePass); //设置加密之后的密码
        save(user);
        //返回结果
        return ResponseResult.okResult();
    }
    //todo 判断用户名是否存在
    private boolean usernameExist(String username){
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUserName,username);
        int count = count(queryWrapper);
        if(count >= 1){
            return true;
        }
        return false;
    }
    //todo 判断昵称是否存在
    private boolean nickNameExist(String nickName){
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getNickName,nickName);
        int count = count(queryWrapper);
        if(count >= 1){
            return true;
        }
        return false;
    }
}


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
19天前
|
JSON Java 数据库
SpringBoot项目使用AOP及自定义注解保存操作日志
SpringBoot项目使用AOP及自定义注解保存操作日志
34 1
|
3月前
|
JSON 中间件 Go
go语言后端开发学习(四) —— 在go项目中使用Zap日志库
本文详细介绍了如何在Go项目中集成并配置Zap日志库。首先通过`go get -u go.uber.org/zap`命令安装Zap,接着展示了`Logger`与`Sugared Logger`两种日志记录器的基本用法。随后深入探讨了Zap的高级配置,包括如何将日志输出至文件、调整时间格式、记录调用者信息以及日志分割等。最后,文章演示了如何在gin框架中集成Zap,通过自定义中间件实现了日志记录和异常恢复功能。通过这些步骤,读者可以掌握Zap在实际项目中的应用与定制方法
131 1
go语言后端开发学习(四) —— 在go项目中使用Zap日志库
|
3月前
|
开发框架 .NET Docker
【Azure 应用服务】App Service .NET Core项目在Program.cs中自定义添加的logger.LogInformation,部署到App Service上后日志不显示Log Stream中的问题
【Azure 应用服务】App Service .NET Core项目在Program.cs中自定义添加的logger.LogInformation,部署到App Service上后日志不显示Log Stream中的问题
|
3月前
|
XML Java Maven
logback在springBoot项目中的使用 springboot中使用日志进行持久化保存日志信息
这篇文章详细介绍了如何在Spring Boot项目中使用logback进行日志记录,包括Maven依赖配置、logback配置文件的编写,以及实现的日志持久化和控制台输出效果。
logback在springBoot项目中的使用 springboot中使用日志进行持久化保存日志信息
|
3月前
|
数据可视化 Java API
如何在项目中快速引入Logback日志并搭配ELK使用
如何在项目中快速引入Logback日志并搭配ELK使用
|
3月前
|
开发框架 .NET API
如何在 ASP.NET Core Web Api 项目中应用 NLog 写日志?
如何在 ASP.NET Core Web Api 项目中应用 NLog 写日志?
178 0
|
3月前
|
监控 程序员 数据库
分享一个 .NET Core Console 项目中应用 NLog 写日志的详细例子
分享一个 .NET Core Console 项目中应用 NLog 写日志的详细例子
|
14天前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
125 30
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
1月前
|
XML JSON Java
Logback 与 log4j2 性能对比:谁才是日志框架的性能王者?
【10月更文挑战第5天】在Java开发中,日志框架是不可或缺的工具,它们帮助我们记录系统运行时的信息、警告和错误,对于开发人员来说至关重要。在众多日志框架中,Logback和log4j2以其卓越的性能和丰富的功能脱颖而出,成为开发者们的首选。本文将深入探讨Logback与log4j2在性能方面的对比,通过详细的分析和实例,帮助大家理解两者之间的性能差异,以便在实际项目中做出更明智的选择。
227 3
|
1月前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1633 14