• 手把手教你设计一个CSDN系统


    在CSDN发一个CSDN系统是什么体验?

    大家都知道CSDN 有一个下载的模块,就是用户上传资源然后管理员会进行审核,上传资源的用户可以赚钱还可以赚积分。
    在这里插入图片描述
    那么个人可不可以开发这样的系统呢?

    完全可以!

    小孟前面就就可开发了一个,而且处理很详细的教程。具体的介绍如下所示:

    一,技术简介

    该项目非常详细的讲解了springboot,可以用于面试、毕设、学习等。
    最新版的springboot2.0框架;

    前端框架采用流行的Layui;

    redis高性能缓存框架,存放热门数据,常用数据;

    thymeleaf模版引擎;

    shiro安全框架;

    javamail集成,找回密码用到;

    数据库连接池使用的是阿里巴巴的Druid;

    全文检索lucene;

    QQ第三方登录。
    在这里插入图片描述
    在这里插入图片描述

    二,系统演示

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    系统不管是界面还是功能都非常的nice,如果想看详细的教程或者演示,也有对系统的本系统的学习

    https://www.bilibili.com/video/BV1jJ41197BJ?p=110&vd_source=e64f225fc5daf048d2687502cb23bb3b

    三,核心代码展示

    /**
     * 小孟V:jishulearn
     */
    @RestController
    @RequestMapping(value = "/article")
    public class ArticleController {
    
        @Autowired
        private ArcTypeService arcTypeService;
    
        @Autowired
        private ArticleService articleService;
    
        @Autowired
        private ArticleIndex articleIndex;
    
        /**
         * 按资源类型分页查询资源列表
         * @param type
         * @param currentPage
         * @return
         */
        @RequestMapping("/{type}/{currentPage}")
        public ModelAndView type(@PathVariable(value = "type",required = false) String type, @PathVariable(value = "currentPage",required = false)Integer currentPage){
            ModelAndView mav = new ModelAndView();
            mav.setViewName("index");
            //类型的html代码
            List arcTypleList = arcTypeService.listAll(Sort.Direction.ASC,"sort");
            mav.addObject("arcTypeStr", HTMLUtil.getArcTypeStr(type,arcTypleList));
            //资源列表
            Map<String,Object> map = articleService.list(type,currentPage, Consts.PAGE_SIZE);
            mav.addObject("articleList",map.get("data"));
            //分页html代码
            mav.addObject("pageStr",HTMLUtil.getPagation("/article/"+type,Integer.parseInt(String.valueOf(map.get("count"))),currentPage,"该分类还没有数据..."));
            return mav;
        }
    
        /**
         * 关键字分词搜索
         */
        @RequestMapping("/search")
        public ModelAndView search(String keywords,@RequestParam(value = "page",required = false) Integer page) throws ParseException, InvalidTokenOffsetsException, org.apache.lucene.queryparser.classic.ParseException, IOException {
            if(page==null){
                page = 1;
            }
            ModelAndView mav = new ModelAndView();
            mav.setViewName("index");
            //类型的html代码
            List arcTypleList = arcTypeService.listAll(Sort.Direction.ASC,"sort");
            mav.addObject("arcTypeStr", HTMLUtil.getArcTypeStr("all",arcTypleList));
            //资源列表
            List<Article> articleList = articleIndex.search(keywords);
            Integer toIndex = articleList.size()>=page*Consts.PAGE_SIZE?page*Consts.PAGE_SIZE:articleList.size();
            mav.addObject("articleList",articleList.subList((page-1)*Consts.PAGE_SIZE,toIndex));
            mav.addObject("keywords",keywords);
            //分页html代码
            int totalPage = articleList.size()%Consts.PAGE_SIZE==0?articleList.size()/Consts.PAGE_SIZE:articleList.size()/Consts.PAGE_SIZE+1;
            String targetUrl = "/article/search?keywords="+keywords;
            String msg = "没有关键字是 \"<font style=\"border: 0px;color:red;font-weight:bold;padding-left: 3px; padding-right: 3px;\" >" +keywords + "</font>\" 的相关资源,请联系站长!";
            mav.addObject("pageStr",HTMLUtil.getPagation2(targetUrl,totalPage,page,msg));
            return mav;
        }
    
        /**
         * 资源详情
         */
        @RequestMapping("/detail/{articleId}")
        public ModelAndView detail(@PathVariable(value = "articleId",required = false) String articleId) throws IOException, org.apache.lucene.queryparser.classic.ParseException {
            ModelAndView mav = new ModelAndView();
            String replace = articleId.replace(".html","");
            articleService.updateClick(Integer.parseInt(replace));
            Article article = articleService.getById(Integer.parseInt(replace));
            if(article.getState()!=2){
                return null;
            }
            mav.addObject("article",article);
            //类型的html代码
            List arcTypleList = arcTypeService.listAll(Sort.Direction.ASC,"sort");
            mav.addObject("arcTypeStr", HTMLUtil.getArcTypeStr(article.getArcType().getArcTypeId().toString(),arcTypleList));
    
            //通过lucene分词查找相似资源
            List<Article> articleList = articleIndex.searchNoHighLighter(article.getName().replace("视频","").replace("教程","")
                                .replace("下载","").replace("PDF",""));
            if(articleList!=null&&articleList.size()>0){
                mav.addObject("similarityArticleList",articleList);
            }
            mav.setViewName("detail");
            return mav;
        }
    
        /**
         * 判断资源是否免费
         */
        @ResponseBody
        @RequestMapping("/isFree")
        public boolean isFree(Integer articleId){
            Article article = articleService.getById(articleId);
            return article.isFree();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    
    /**
     * 小孟V:jishulearn
     */
    @Controller
    @RequestMapping(value = "/comment")
    public class CommentController {
    
        @Autowired
        private CommentService commentService;
    
        /**
         * 前端提交保存评论信息
         * @param comment
         * @param session
         * @return
         */
        @ResponseBody
        @PostMapping("/add")
        public Map<String,Object> add(Comment comment, HttpSession session){
            Map<String,Object> map = new HashMap<>();
            comment.setContent(StringUtil.esc(comment.getContent()));
            comment.setCommentDate(new Date());
            comment.setState(0);
            comment.setUser((User)session.getAttribute(Consts.CURRENT_USER));
            commentService.save(comment);
            map.put("success",true);
            return map;
        }
    
        /**
         * 分页查询某个资源的评论信息
         */
        @ResponseBody
        @RequestMapping(value = "/list")
        public Map<String,Object> list(Comment s_comment, @RequestParam(value = "page",required = false)Integer page){
            s_comment.setState(1);
            Page<Comment> commentPage = commentService.list(s_comment,page,5, Sort.Direction.DESC,"commentDate");
            Map<String,Object> map = new HashMap<>();
            map.put("data", HTMLUtil.getCommentPageStr(commentPage.getContent()));          //评论的HTML代码
            map.put("total",commentPage.getTotalPages());                                   //总页数
            return map;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    /**
     * 根路径及其他请求处理
     */
    @Controller
    public class IndexController {
    
        @Autowired
        private ArcTypeService arcTypeService;
    
        @Autowired
        private ArticleService articleService;
    
        @Autowired
        private UserService userService;
    
        @Autowired
        private MessageService messageService;
    
        @Value("${imgFilePath}")
        private String imgFilePath;         //图片上传路径
    
        /**
         * 首页
         */
        @RequestMapping("/")
        public ModelAndView index(){
            ModelAndView mav = new ModelAndView();
            mav.setViewName("index");
            //类型的html代码
            List arcTypleList = arcTypeService.listAll(Sort.Direction.ASC,"sort");
            mav.addObject("arcTypeStr", HTMLUtil.getArcTypeStr("all",arcTypleList));
            //资源列表
            Map<String,Object> map = articleService.list("all",1, Consts.PAGE_SIZE);
            mav.addObject("articleList",map.get("data"));
            //分页html代码
            mav.addObject("pageStr",HTMLUtil.getPagation("/article/all",Integer.parseInt(String.valueOf(map.get("count"))),1,"该分类还没有数据..."));
            return mav;
        }
    
        /**
         * QQ登录回调
         */
        @RequestMapping("/connect")
        public String qqCallback(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws QQConnectException {
            response.setContentType("text/html;charset=utf-8");
            AccessToken accessTokenObj = new Oauth().getAccessTokenByRequest(request);
            String accessToken = null;
            String openId = null;
            String state = request.getParameter("state");
            String session_state = (String) session.getAttribute("qq_connect_state");
            if(StringUtil.isEmpty(session_state)||!session_state.equals(state)){
                System.out.println("非法请求");
                return "redirect:/";
            }
            accessToken = accessTokenObj.getAccessToken();
            if(StringUtil.isEmpty(accessToken)){
                System.out.println("没有获取到响应参数");
                return "redirect:/";
            }
            session.setAttribute("accessToken",accessToken);
            OpenID openIDObj = new OpenID(accessToken);
            openId = openIDObj.getUserOpenID();
            UserInfo qzoneUserInfo = new UserInfo(accessToken,openId);
            UserInfoBean userInfoBean = qzoneUserInfo.getUserInfo();
            if(userInfoBean==null||userInfoBean.getRet()!=0||StringUtil.isNotEmpty(userInfoBean.getMsg())){
                System.out.println("没有对应的qq信息");
                return "redirect:/";
            }
            //获取用户成功
            User currentUser = (User)session.getAttribute(Consts.CURRENT_USER);
            if(currentUser!=null&&StringUtil.isNotEmpty(currentUser.getUserName())&&StringUtil.isNotEmpty(currentUser.getEmail())&&StringUtil.isEmpty(currentUser.getOpenId())){
                currentUser.setOpenId(openId);
                userService.save(currentUser);
                session.setAttribute(Consts.CURRENT_USER,currentUser);
                return "redirect:/";
            }
    
            User user = userService.findByOpenId(openId);
            if(user==null){             //该用户是第一次登录,先注册
                user = new User();
                user.setOpenId(openId);
                user.setNickname(userInfoBean.getNickname());
                String imgName = DateUtil.getCurrentDateStr()+".jpg";
                downloadPicture(userInfoBean.getAvatar().getAvatarURL100(),imgFilePath+imgName);
                user.setHeadPortrait(imgName);
                user.setSex(userInfoBean.getGender());
                user.setPassword(CryptographyUtil.md5("123456",CryptographyUtil.SALT));
                user.setRegistrationDate(new Date());
                user.setLatelyLoginTime(new Date());
                //userService.save(user);
                session.setAttribute(Consts.CURRENT_USER,user);
            }else{                  //已经注册过,更新用户信息,直接将信息存入session 然后跳转
                if(!user.isOff()){     //非封号状态
                    user.setNickname(userInfoBean.getNickname());
                    user.setSex(userInfoBean.getGender());
                    user.setLatelyLoginTime(new Date());
                    userService.save(user);
                    Subject subject = SecurityUtils.getSubject();
                    UsernamePasswordToken token = new UsernamePasswordToken(user.getUserName(),user.getPassword());
                    subject.login(token);               //登录验证
                    Integer messageCount = messageService.getCountByUserId(user.getUserId());
                    user.setMessageCount(messageCount);
                    Article s_article = new Article();
                    s_article.setUseful(false);
                    s_article.setUser(user);
                    session.setAttribute(Consts.UN_USEFUL_ARTICLE_COUNT,articleService.getCount(s_article,null,null,null));
                    session.setAttribute(Consts.CURRENT_USER,user);
                }
            }
            return "redirect:/";
        }
    
        /**
         * 通过链接下载图片保存到头像文件夹
         */
        private void downloadPicture(String urlString,String path){
            URL url = null;
            DataInputStream dataInputStream = null;
            FileOutputStream fileOutputStream = null;
            try {
                url = new URL(urlString);
                dataInputStream = new DataInputStream(url.openStream());
                fileOutputStream = new FileOutputStream(new File(path));
                ByteArrayOutputStream output = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int length;
                while ((length = dataInputStream.read(buffer))>0){
                    output.write(buffer,0,length);
                }
                fileOutputStream.write(output.toByteArray());
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                try {
                    dataInputStream.close();
                    fileOutputStream.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141

    我是小孟,欢迎关注我!可以一起交流。点赞评论是对我最大支持!

  • 相关阅读:
    Oracle 快速入门
    【数据结构】—超级详细的归并排序(含C语言实现)
    精品Python宠物领养网站系统失物招领
    go面试题 最大交换
    通过rabbitmq生成延时消息,并生成rabbitmq镜像
    【Vue-Element】Vue下配置好看的滚动条
    擅长处理临时数据的结构——栈
    QSS的应用
    Kafka为什么是高性能高并发高可用架构
    利用 Redis 也能实现订单30分钟自动取消?
  • 原文地址:https://blog.csdn.net/mengchuan6666/article/details/125365933