美文网首页
对一个开源项目的上手

对一个开源项目的上手

作者: 萍水间人 | 来源:发表于2019-05-31 20:06 被阅读0次

    用的halo
    https://github.com/halo-dev/halo

    导入project之后就开始build了


    然后尝试run起来

    对于开源项目,一定要跑起来,如果不run起来就直接看源代码的话会头疼的

    项目已经启动了


    之后我们访问


    开始调试

        @PostMapping("login")
        @ApiOperation("Login")
        @CacheLock(autoDelete = false)
        public AuthToken auth(@RequestBody @Valid LoginParam loginParam) {
            return adminService.authenticate(loginParam);
        }
    

    PostMapping 应该就是路由的选择
    其他的先不管
    auth函数,收到了

    loginParam 这个结构
    我们可以具体看下LoginParam

    public class LoginParam {
    
        @NotBlank(message = "用户名或邮箱不能为空")
        @Size(max = 255, message = "用户名或邮箱的字符长度不能超过 {max}")
        private String username;
    
        @NotBlank(message = "登陆密码不能为空")
        @Size(max = 100, message = "用户密码字符长度不能超过 {max}")
        private String password;
    
    }
    

    是一个类

    有两个私有字段username和password

    在对username和password进行判断(字符长度)
    然后继续验证
    看下adminService这个类
    在service文件夹中


    有一个authenticate方法

        @NonNull
        AuthToken authenticate(@NonNull LoginParam loginParam);
    

    也就是对loginParam进行进一步的验证

    继续跟踪AuthToken这个类

    @Data
    public class AuthToken {
    
        /**
         * Access token.
         */
        @JsonProperty("access_token")
        private String accessToken;
    
        /**
         * Expired in. (seconds)
         */
        @JsonProperty("expired_in")
        private int expiredIn;
    
        /**
         * Refresh token.
         */
        @JsonProperty("refresh_token")
        private String refreshToken;
    }
    

    应该是登陆之后会有一个accessToken,然后还会设置一个有效期
    同时还会有更新的token
    这个类位于security这个文件夹中

    突然发现AdminService其实只是一个接口,具体看实现
    AdminServiceImpl

    直奔authenticate方法

        @Override
        public AuthToken authenticate(LoginParam loginParam) {
            Assert.notNull(loginParam, "Login param must not be null");
    
            String username = loginParam.getUsername();
    
            String mismatchTip = "用户名或者密码不正确";
    
            final User user;
    
            try {
                // Get user by username or email
                user = Validator.isEmail(username) ?
                        userService.getByEmailOfNonNull(username) : userService.getByUsernameOfNonNull(username);
            } catch (NotFoundException e) {
                log.error("Failed to find user by name: " + username, e);
                throw new BadRequestException(mismatchTip);
            }
    
            userService.mustNotExpire(user);
    
            if (!userService.passwordMatch(user, loginParam.getPassword())) {
                // If the password is mismatch
                throw new BadRequestException(mismatchTip);
            }
    
            if (SecurityContextHolder.getContext().isAuthenticated()) {
                // If the user has been logged in
                throw new BadRequestException("You have been logged in, do not log in repeatedly please");
            }
    
            // Generate new token
            return buildAuthToken(user);
        }
    

    可以看到调用了Validator的验证器去验证isEmail
    然后还有一系列验证,具体的就不看了

    同时这个类是位于service文件夹中

    所以登陆的逻辑就很清晰了,接收到请求,验证用户名和密码,然后返回一个token

    我们接下来分析是如何请求显示文章的

    发送的URL如下:


    有两个参数page = 0&&size = 10
    对应的是/admin/posts

    然后找到/posts

    有一个类叫做PostController
    然后有一个pageBy方法

        public Page<PostListVO> pageBy(@PageableDefault(sort = "updateTime", direction = DESC) Pageable pageable,
                                       PostQuery postQuery) {
            Page<Post> postPage = postService.pageBy(postQuery, pageable);
            return postService.convertToListVo(postPage);
        }
    

    同时接收 pageablepostQuery两个参数

    看到pageable就是我们的请求,number=0,size=10
    同时默认排序是DESC
    Pageable这个接口不是自己写的,就不看了

    来看PostQuery这个类

    @Data
    public class PostQuery {
    
        /**
         * Keyword.
         */
        private String keyword;
    
        /**
         * Post status.
         */
        private PostStatus status;
    
        /**
         * Category id.
         */
        private Integer categoryId;
    
    }
    
    

    也就是拥有了关键词,状态,和类别的ID

    Page是一个泛型的接口吧,然后我们指定的是post这个类
    post这个类是继承自BasePost, 简要看一下BasePost这个类,它又是继承自BaseEntity这个类的

    public class BasePost extends BaseEntity {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
    
        /**
         * Post title.
         */
        @Column(name = "title", columnDefinition = "varchar(100) not null")
        private String title;
    
        /**
         * Post status.
         */
        @Column(name = "status", columnDefinition = "int default 1")
        private PostStatus status;
    ....
    
    

    这个类其实有很多个字段,也就是文章的各种属性吧

    接下来着重看一下convertToListVo方法

        @Override
        public Page<PostListVO> convertToListVo(Page<Post> postPage) {
            Assert.notNull(postPage, "Post page must not be null");
    
            List<Post> posts = postPage.getContent();
    
            Set<Integer> postIds = ServiceUtils.fetchProperty(posts, Post::getId);
    
            // Get tag list map
            Map<Integer, List<Tag>> tagListMap = postTagService.listTagListMapBy(postIds);
    
            // Get category list map
            Map<Integer, List<Category>> categoryListMap = postCategoryService.listCategoryListMap(postIds);
    
            // Get comment count
            Map<Integer, Long> commentCountMap = postCommentService.countByPostIds(postIds);
    
            return postPage.map(post -> {
                PostListVO postListVO = new PostListVO().convertFrom(post);
    
                if (StringUtils.isBlank(postListVO.getSummary())) {
                    // Set summary
                    postListVO.setSummary(convertToSummary(post.getOriginalContent()));
                }
    
                Optional.ofNullable(tagListMap.get(post.getId())).orElseGet(LinkedList::new);
    
                // Set tags
                postListVO.setTags(Optional.ofNullable(tagListMap.get(post.getId()))
                        .orElseGet(LinkedList::new)
                        .stream()
                        .filter(Objects::nonNull)
                        .map(tag -> (TagDTO) new TagDTO().convertFrom(tag))
                        .collect(Collectors.toList()));
    
                // Set categories
                postListVO.setCategories(Optional.ofNullable(categoryListMap.get(post.getId()))
                        .orElseGet(LinkedList::new)
                        .stream()
                        .filter(Objects::nonNull)
                        .map(category -> (CategoryDTO) new CategoryDTO().convertFrom(category))
                        .collect(Collectors.toList()));
    
                // Set comment count
                postListVO.setCommentCount(commentCountMap.getOrDefault(post.getId(), 0L));
    
                return postListVO;
            });
        }
    

    postPage相当于一个文章的数据结构了

    然后对得到这篇文章的内容,然后将其summary,tags,categories,comment count设置好

    最后就返回了吧,更具体的细节不清楚了

    删除文章

    没太看懂是怎么删除文章的


    还有这个publish对应的就是复原文章

    相关文章

      网友评论

          本文标题:对一个开源项目的上手

          本文链接:https://www.haomeiwen.com/subject/wzmitctx.html