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

简介: 在CSDN发一个CSDN系统是什么体验?大家都知道CSDN 有一个下载的模块,就是用户上传资源然后管理员会进行审核,上传资源的用户可以赚钱还可以赚积分。

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


大家都知道CSDN 有一个下载的模块,就是用户上传资源然后管理员会进行审核,上传资源的用户可以赚钱还可以赚积分。


微信图片_20221009224734.png

那么个人可不可以开发这样的系统呢?


完全可以!


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


一,技术简介


该项目非常详细的讲解了springboot,可以用于面试、毕设、学习等。

最新版的springboot2.0框架;


前端框架采用流行的Layui;


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


thymeleaf模版引擎;


shiro安全框架;


javamail集成,找回密码用到;


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


全文检索lucene;


QQ第三方登录。


微信图片_20221009224744.png


二,系统演示


微信图片_20221009224750.png


微信图片_20221009224756.png


微信图片_20221009224800.png


微信图片_20221009224806.png


微信图片_20221009224811.png


微信图片_20221009224816.png


微信图片_20221009224820.png


微信图片_20221009224825.png


系统不管是界面还是功能都非常的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();
    }
}



/**
 * 小孟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;
    }
}


/**
 * 根路径及其他请求处理
 */
@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();
            }
        }
    }
目录
相关文章
一键自动化博客发布工具,用过的人都说好(csdn篇)
使用一键自动化博客发布工具blog-auto-publishing-tools把博客发布到csdn上。
一键自动化博客发布工具,用过的人都说好(csdn篇)
|
5月前
|
前端开发 Java 数据库连接
程序与技术分享:CleanBlog(个人博客+源码)
程序与技术分享:CleanBlog(个人博客+源码)
30 0
|
5月前
|
存储 vr&ar Windows
程序与技术分享:DDraw笔记
程序与技术分享:DDraw笔记
29 0
一键自动化博客发布工具,用过的人都说好(知乎篇)
使用一键自动化博客发布工具blog-auto-publishing-tools把博客发布到知乎上。
一键自动化博客发布工具,用过的人都说好(知乎篇)
|
6月前
|
Web App开发
一键自动化博客发布工具,用过的人都说好(简书篇)
给大家推荐一个一键自动化博客发布工具,完全的一键操作,让你轻松告别手动发布博客的烦恼。
|
弹性计算 安全 关系型数据库
基于阿里云构建自己的博客(过程及心得体会)
本文介绍了如何使用免费领取的云服务器ECS、云数据库RDS MySQL Serverless 来构建自己的博客。首先,作者介绍了自己选择阿里云的原因和虚拟主机的优点。然后,详细介绍了如何配置阿里云虚拟主机以支持HTTPS和80端口等,最后在完成博客搭建后讲述了自己的心得体会。
|
机器学习/深度学习 人工智能 算法
我的第一篇博客--C++课程设计
前言 这是我的第一篇博客,内容便是最近所做的课程设计,之后也会每天和大家分享一下刷题笔记,以及AC后的代码,希望大家的批评指正,分享大家的一些观点和想法,希望和大家共同进步。
113 0
|
算法 开发工具 git
CSDN算法技能树测评
CSDN算法技能树测评
147 0
CSDN算法技能树测评
|
JSON 小程序 JavaScript
全栈工程师之路-中级篇之小程序开发-第一章第三节阅读官方demo
全栈工程师之路-中级篇之小程序开发-第一章第三节阅读官方demo
179 0
全栈工程师之路-中级篇之小程序开发-第一章第三节阅读官方demo
|
UED
[博文推荐]设计的意义
本文来自丁宇的博客,分享了自己对于“设计的意义”的个人理解。 最近通过各种渠道和形式接触了几位设计师,他们来自不同的公司,做着迥异的产品,但当我问起类似于“设计的意义”这样的问题时,他们的回答均不能让人满意。
768 0