基于javaweb+mysql的springboot个人博客系统(前后端分离+java+vue+springboot+ssm+mysql+maven+redis)

基于javaweb+mysql的springboot个人博客系统(前后端分离+java+vue+springboot+ssm+mysql+maven+redis)

私信源码获取及调试交流

运行环境

Java≥8、MySQL≥5.7、Node.js≥10

开发工具

后端:eclipse/idea/myeclipse/sts等均可配置运行

前端:WebStorm/VSCode/HBuilderX等均可

适用

课程设计,大作业,毕业设计,项目练习,学习演示等

功能说明

基于javaweb的SpringBoot个人博客系统(前后端分离+java+vue+springboot+ssm+mysql+maven+redis)

一、项目简述

本系统功能包括:文章展示、热门文章、文章分类、标签云用户登录评论、匿名评论用户留言、匿名留言评论管理、文章发布、文章管理文章数据统计等等.

二、项目运行

环境配置: Jdkl . 8 + + Mysql + HBuilderX ( Webstorm 也行) + Eclispe ( IntelliJ 10 以,三 clispe , MyEclispe , Sts 都支持)。

项目技术: Springboot + Maven + Mybatis + Vue + Redis 组成, BIS 模式+ M aven 等等,附带支付宝沙箱环境以及支付环节代码。

        Set<String> tags = articleService.findAllTags();
        return tags;
    }

    @ApiOperation("获取文章的所有月份")
    @GetMapping("/archives")
    public Set<String> getArchivesMonths() {
        Set<String> months = articleService.archivesMonths();
        return months;
    }
}

/**
 * @description 管理博客文章
 */
@RestController("adminArticleController")
@RequestMapping("admin/articles")
@Slf4j
public class ArticleController {
    @Autowired
    private ArticleService articleService;

    @ApiOperation("插入文章")
    @PostMapping("/")
    public ResultVO insArticle(@RequestBody @Validated ArticleDTO articleDTO) {
        articleService.insArticle(articleDTO);
        return ResultVO.ok("插入文章成功!");
    }

    @ApiOperation("修改文章")
    @PutMapping("/")
    public ResultVO updArticle(@RequestBody @Validated ArticleDTO articleDTO) {
        articleService.updArticle(articleDTO);
        return ResultVO.ok("更新文章成功!");
    }

    @ApiOperation("根据对应文章id删除文章")
    @DeleteMapping("/{id}")
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public ResponseEntity<ResultVO> exception(Exception exception) {
        exception.printStackTrace();
        log.error("message:{}", exception.getMessage());
        //未知异常
        ResultVO resultVO = ResultVO.error(exception.getMessage());
        return new ResponseEntity<>(resultVO, HttpStatus.INTERNAL_SERVER_ERROR);
    }

    /**
     * 结合BeanValid,格式化异常信息
     *
     * @param ex
     * @return
     */
    private String getMessage(MethodArgumentNotValidException ex) {
        BindingResult bindingResult = ex.getBindingResult();
        StringBuilder sb = new StringBuilder();
        for (FieldError error : bindingResult.getFieldErrors()) {
            String field = error.getField();
            Object value = error.getRejectedValue();
            String msg = error.getDefaultMessage();
            String message = String.format("错误字段:%s,错误值:%s,原因:%s;", field, value, msg);
            sb.append(message);
        }
        return sb.toString();
    }
}

 * @description 拦截器:用于日志打印
 */
@Component
@Slf4j
public class LogInterceptor implements HandlerInterceptor {
    @Override
    public synchronized boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        log.info("request-method:{}", request.getMethod());
        log.info("request-url:{}", request.getRequestURL());
        String remoteAddr = request.getRemoteAddr();
        log.info("remote-addr:{}", remoteAddr);
        StringBuffer sb = new StringBuffer();
        request.getParameterMap().forEach((k, v) -> sb.append(k).append(Arrays.toString(v)));
        log.info("request-parameters:{}", sb.toString());
        // 根据ip定位
        //((Runnable) () -> {
        //    try {
        //        String res = HttpUtil.get(TAOBAO_IP_INFO + "?ip=" + remoteAddr);
        //        JSONObject jsonObject = JSONUtil.parseObj(res);
        //        if ("0".equals(jsonObject.get("code"))) {
        //            JSONObject data = jsonObject.getJSONObject("data");
        //            log.info("ip-info:country:{}、area:{}、region:{}、city:{}、isp:{}", data.get("country"), data.get("area"), data.get("region"), data.get("city"), data.get("isp"));
        //        }
        //    } catch (Exception e) {
        //        log.error("ip:{}定位出错", remoteAddr);
        //    }
        //}).run();
        return true;
    }
}

/**

/**
 * @description 留言信息api
 */
@RestController
@RequestMapping("comm/message")
public class MessageController {
    @Autowired
    private MessageService messageService;

    @ApiOperation("获取所有留言")
    @GetMapping("/")
    public List<MessageVO> getMessages() {
        List<MessageVO> messages = messageService.findAllMessages();
        return messages;
    }

    @ApiOperation("提交留言")
    @PostMapping("/")
    public ResultVO leaveAMessage(@RequestBody @Validated MessageDTO messageDTO) {
        messageService.insMessage(messageDTO);
        return ResultVO.ok("留言成功!");
    }
}


/**
 * @description 全局异常处理
 */
@ControllerAdvice
@Slf4j
class ApiExceptionHandler {

    @ResponseBody
    @ExceptionHandler(value = BaseException.class)
    public ResponseEntity<ResultVO> handleApiException(Exception exception, HttpServletResponse response) {
        BaseException baseException = (BaseException) exception;
        if (baseException instanceof TokenExpiredException) {
            log.warn("message:{}", exception.getMessage());
            response.setStatus(403);
        } else {
            log.error("message:{}", exception.getMessage());
            response.setStatus(500);
        }
        ResultVO resultVO = ResultVO.error(baseException);
        return new ResponseEntity<>(resultVO, HttpStatus.valueOf(response.getStatus()));
    }

    @ExceptionHandler(value = NoHandlerFoundException.class)
    @ResponseBody
    public ResponseEntity<ResultVO> handleNoHandlerFoundException(Exception exception) {
        log.error("message:{}", exception.getMessage());
        ResultVO resultVO = ResultVO.error(exception.getMessage(), RespCode.RESOURCES_NOT_FOUND);

/**
 * @description 与文章相关的api
 */
@RestController("commArticleController")
@RequestMapping("comm/articles")
public class ArticleController {
    @Autowired
    private ArticleService articleService;
    @Autowired
    private ArticleMapper articleMapper;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @ApiOperation("根据条件分页显示文章")
    @GetMapping("/page")
    public PageInfoVO<SimpleArticleVO> getPageArticles(
            @ApiParam("页码") @RequestParam(value = "pageNumber", defaultValue = "1", required = false) Integer pageNumber,
            @ApiParam("约束条件") @RequestParam(required = false) String condition,
            @ApiParam("约束条件对应的信息") @RequestParam(required = false) String data
    ) {
        return articleService.findByCondition(pageNumber, DEFAULT_PAGE_SIZE, condition, data);
    }

    @ApiOperation("根据文章id获取文章信息")
    @GetMapping("/{id}")
    public ArticleVO getArticleById(@PathVariable String id) {
        return articleService.findArticleById(id);
    }

    @ApiOperation("获取热门文章列表")
    @GetMapping(value = "/hot", produces = "application/json;charset=UTF-8")
    public String getHotArticles() {
        return redisTemplate.opsForValue().get("hotArticles");
    }

    @ApiOperation("获取所有文章分类")
    @GetMapping("/categories")
    public List<Map<String, Object>> getCategories() {
        return articleMapper.findCategoriesCount();
    }

    public ResultVO profile(@RequestBody @Validated ProfileDTO profile) {
        configMapper.insert(new ConfigDO(Constants.ConfigKey.NAME, profile.getName()));
        configMapper.insert(new ConfigDO(Constants.ConfigKey.PEN_NAME, profile.getPenName()));
        configMapper.insert(new ConfigDO(Constants.ConfigKey.MOTTO, profile.getMotto()));
        configMapper.insert(new ConfigDO(Constants.ConfigKey.INTRODUCTION, profile.getIntroduction()));
        configMapper.insert(new ConfigDO(Constants.ConfigKey.AVATAR, profile.getAvatar()));
        configMapper.insert(new ConfigDO(Constants.ConfigKey.WEBSITES, StrUtil.EMPTY));
        configService.initConfig();
        return ResultVO.ok("个人信息初始化完成");
    }
}

/**
 * @e-mail 1413979079@qq.com
 * @description 自定义图床
 */
@Slf4j
@RestController
@RequestMapping("/admin/image")
public class ImageController {
    @Value("${blog.images.path}")
    private String imagesPath;
    @Value("${blog.url}")
    private BlogService blogService;
    @Autowired
    private Configs configs;

    @ApiOperation("获取博客信息")
    @GetMapping("/info")
    public BlogInfoVO getInfo() {
        BlogInfoVO blogInfo = blogService.getBlogInfo();
        return blogInfo;
    }

    @ApiOperation("获取博客配置信息")
    @GetMapping("/profile")
    public ProfileVO profile() {
        return ProfileVO.create(configs);
    }
}

/**
 * @description 留言信息api
 */
@RestController
@RequestMapping("comm/message")
public class MessageController {
    @Autowired
    private MessageService messageService;

    @ApiOperation("获取所有留言")
    @GetMapping("/")
    public List<MessageVO> getMessages() {
        List<MessageVO> messages = messageService.findAllMessages();
        return messages;
    }
    @ApiOperation("上传图片")
    @PostMapping("/upload")
    public String upload(@RequestParam("image") MultipartFile multipartFile) {
        // "." 、"\"、"|"需要转义
        String[] split = multipartFile.getOriginalFilename().split("\\.");
        String fileName = UUID.randomUUID().toString() + "." + split[split.length - 1];
        try {
            File dir = new File(imagesPath);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            FileUtil.writeFromStream(multipartFile.getInputStream(), imagesPath + fileName);
            String url = uri + "admin/image/get/" + fileName;
            log.debug("image-url:{}", url);
            return url;
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new ImageUploadFailureException(e);
        }
    }

    @ApiOperation("根据图片地址获取图片")
    @GetMapping("/get/{fileName}.{type}")
    public void get(HttpServletResponse res, @PathVariable String fileName, @PathVariable String type) {
        BufferedInputStream in = null;
        ServletOutputStream out = null;
        try {
            in = FileUtil.getInputStream(imagesPath + fileName + "." + type);
            out = res.getOutputStream();
            StreamUtils.copy(in, out);
            out.flush();
        } catch (IOException e) {
            log.error(e.getMessage());
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    log.error(e.getMessage());
                }
                if (out != null) {
                    try {
                        out.close();
                    } catch (IOException e) {
                        log.error(e.getMessage());
                    }
                }
            }

/**
 * @e-mail 1413979079@qq.com
 * @description 草稿
 */
@RestController
@RequestMapping("admin/draft")
public class DraftController {
    @Autowired
    private DraftMapper draftMapper;

    @ApiOperation("获取所有草稿")
    @GetMapping("/")
    public List<DraftVO> getAllDrafts() {
        List<DraftVO> draftVOS = draftMapper.findAll()
                .stream()
                .map(DraftVO::create)
                .collect(Collectors.toList());
        return draftVOS;
    }

    @ApiOperation("根据id获取对应草稿信息")
    @GetMapping("/{id}")
    public DraftDO getById(@PathVariable String id) {
        DraftDO draftDO = draftMapper.findById(id);
        return draftDO;
    }

    @ApiOperation("新增草稿")
    @PostMapping("/")
    public Map<String, Object> saveDraft(@RequestBody DraftDTO draftDTO) {
        // 生成唯一id
        String id = IdUtil.simpleUUID();
        DraftDO draftDO = new DraftDO();
        draftDO.setTitle(draftDTO.getTitle());
        draftDO.setContent(draftDTO.getContent());
        draftDO.setGmtUpdate(System.currentTimeMillis());
        draftDO.setGmtCreate(draftDO.getGmtUpdate());
 */
@RestController
@RequestMapping("comm/message")
public class MessageController {
    @Autowired
    private MessageService messageService;

    @ApiOperation("获取所有留言")
    @GetMapping("/")
    public List<MessageVO> getMessages() {
        List<MessageVO> messages = messageService.findAllMessages();
        return messages;
    }

    @ApiOperation("提交留言")
    @PostMapping("/")
    public ResultVO leaveAMessage(@RequestBody @Validated MessageDTO messageDTO) {
        messageService.insMessage(messageDTO);
        return ResultVO.ok("留言成功!");
    }
}

/**
 * @e-mail 1413979079@qq.com
 * @description 管理员用户
 */
@RestController("adminUserController")
@RequestMapping("/admin/user")
public class UserController {
    @Autowired
    private ConfigService configService;

    @RequestMapping("/token")
    public ResultVO token(String token) {
        boolean res = configService.checkToken(token);
        return res ? ResultVO.ok("已登录") : ResultVO.ok("token已经过期");
    }

    @PostMapping("/")
    public ResultVO login(@RequestBody AdminUserDTO user) {
        String token = configService.login(user);
        return token != null ? ResultVO.ok(token) : ResultVO.error("登录失败");
@RequestMapping("admin/comment")
public class CommentController {
    @Autowired
    private CommentService commentService;

    @ApiOperation("分页展示评论列表")
    @GetMapping("/")
    public PageInfoVO<CommentItemVO> getComment(
            @RequestParam(value = "pageNumber", defaultValue = "1", required = false) Integer pageNumber) {
        PageInfoVO<CommentItemVO> pageInfoVO = commentService.findAllComments(pageNumber);
        return pageInfoVO;
    }

    @ApiOperation("根据id删除对应评论")
    @DeleteMapping("/{id}")
    public ResultVO delById(@PathVariable Long id) {
        commentService.deleteById(id);
        return ResultVO.ok("操作成功!");
    }
}

/**
 * @description 获取blog的信息
 */
@Slf4j
@RestController("commBlogController")
@RequestMapping("/comm/blog")
public class BlogController {
    @Autowired
@RestController("commCommentController")
@RequestMapping("comm/comment")
public class CommentController {

    @Autowired
    private CommentService commentService;

    @ApiOperation("提交评论")
    @PostMapping("/")
    public ResultVO comment(@RequestBody @Validated CommentDTO commentDTO) {
        commentService.insComment(commentDTO);
        return ResultVO.ok("评论成功!");
    }

    @ApiOperation("根据文章id获取该文章下所有评论")
    @GetMapping("/{id}")
    public List<CommentVO> getAllComments(@PathVariable String id) {
        List<CommentVO> comments = commentService.findCommentByArticleId(id);
        return comments;
    }
}

/**
 * @description 与评论有关的api
 */
@RestController("adminCommentController")
@RequestMapping("admin/comment")
public class CommentController {
    @Autowired
    private CommentService commentService;

    @ApiOperation("分页展示评论列表")
    @GetMapping("/")
    public PageInfoVO<CommentItemVO> getComment(
            @RequestParam(value = "pageNumber", defaultValue = "1", required = false) Integer pageNumber) {
        PageInfoVO<CommentItemVO> pageInfoVO = commentService.findAllComments(pageNumber);
        return pageInfoVO;
    }

    @PutMapping("/")
    public ResultVO updArticle(@RequestBody @Validated ArticleDTO articleDTO) {
        articleService.updArticle(articleDTO);
        return ResultVO.ok("更新文章成功!");
    }

    @ApiOperation("根据对应文章id删除文章")
    @DeleteMapping("/{id}")
    public ResultVO delArticleById(@PathVariable String id) {
        articleService.delete(id);
        return ResultVO.ok("ID为" + id + "的文章删除成功!");
    }

    @ApiOperation("分页获取文章列表")
    @GetMapping("/")
    public PageInfoVO<SimpleArticleVO> getPageArticles(@RequestParam(value = "pageNumber", defaultValue = "1") Integer pageNumber) {
        PageInfoVO<SimpleArticleVO> pageInfoVO = articleService.findByCondition(pageNumber, ADMIN_PAGE_SIZE, null, null);
        return pageInfoVO;
    }

    @ApiOperation("根据查询条件筛选文章")
    @PostMapping("/query")
    public PageInfoVO<SimpleArticleVO> searchArticles(@RequestBody QueryConditionDTO condition) {
        PageInfoVO<SimpleArticleVO> pageInfoVO = articleService.findArticles(condition);
        return pageInfoVO;
    }
}

/**
 * @e-mail 1413979079@qq.com
 * @description 拦截器:用于日志打印
 */
@Component
@Slf4j
public class LogInterceptor implements HandlerInterceptor {
    @Override
    public synchronized boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {

/**
 * @description 管理员token拦截器
 */
@Component
@Slf4j
public class TokenInterceptor implements HandlerInterceptor {
    @Autowired
    private ConfigMapper configMapper;

    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) {
        if ("OPTIONS".equals(req.getMethod())) {
            res.setStatus(HttpServletResponse.SC_OK);
            return true;
        }

        String token = req.getHeader("Authorization");
        log.info("admin token:" + token);
        if (token == null) {
            res.setStatus(403);
            res.setHeader("Access-Control-Allow-Origin", "*");
            return false;
        }
        ConfigDO cdo = configMapper.findByKey("admin_token");
        if (!cdo.getValue().equals(token)) {
            res.setStatus(403);
            res.setHeader("Access-Control-Allow-Origin", "*");
            return false;
        }
        return true;
    }
}

        draftDO.setTitle(draftDTO.getTitle());
        draftDO.setContent(draftDTO.getContent());
        draftDO.setGmtUpdate(System.currentTimeMillis());
        draftMapper.updDraft(draftDO);
        Map<String, Object> map = new HashMap<>();
        map.put("msg", "文章已自动保存,上次保存时间:" + Utils.formatDate(draftDO.getGmtUpdate(), DATE_TIME_PATTERN));
        map.put("id", id);
        return map;
    }

    @ApiOperation("根据id删除指定草稿")
    @DeleteMapping("/{id}")
    public ResultVO get(@PathVariable String id) {
        draftMapper.deleteById(id);
        return ResultVO.ok("删除成功");
    }
}

/**
 * @e-mail 1413979079@qq.com
 * @description 博客初始化
 */
@RestController
@RequestMapping("/init")
public class InitController {
    @Autowired
    private ConfigMapper configMapper;
    @Autowired
    private ConfigService configService;

    @GetMapping("/check")
    public ResultVO check() {
        List<ConfigDO> all = configMapper.findAll();
        if (all.isEmpty()) {

    @ApiOperation("导入博客数据")
    @PostMapping("/import")
    public ResultVO importData(@RequestParam("blogData") MultipartFile file) {
        try {
            ObjectInputStream ois = new ObjectInputStream(file.getInputStream());
            BlogData blogData = (BlogData) ois.readObject();
            blogService.importData(blogData);
        } catch (IOException e) {
            log.error("导入博客数据,文件上传失败:{}", e.getMessage());
            return ResultVO.error("数据导入失败");
        } catch (ClassNotFoundException e) {
            log.error("导入博客数据,{}", e.getMessage());
            return ResultVO.error("数据导入失败");
        }
        return ResultVO.ok("数据导入成功");
    }

    @ApiOperation("修改或插入博客信息")
    @PostMapping("/profile")
    public ResultVO updProfile(@RequestBody ProfileDTO profileDTO) {
        configService.updConfig(profileDTO);
        return ResultVO.ok("操作成功");
    }

    @ApiOperation("获取统计图表的信息")
    @GetMapping("/chart")
    public Map<String, Object> getArticlesCountByMouth() {
        return blogService.countByMonth();
    }
}

                if (out != null) {
                    try {
                        out.close();
                    } catch (IOException e) {
                        log.error(e.getMessage());
                    }
                }
            }
        }
    }
}

/**
 * @description 与文章相关的api
 */
@RestController("commArticleController")
@RequestMapping("comm/articles")
public class ArticleController {
    @Autowired
    private ArticleService articleService;
    @Autowired
    private ArticleMapper articleMapper;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @ApiOperation("根据条件分页显示文章")
    @GetMapping("/page")
    public PageInfoVO<SimpleArticleVO> getPageArticles(
            @ApiParam("页码") @RequestParam(value = "pageNumber", defaultValue = "1", required = false) Integer pageNumber,
            @ApiParam("约束条件") @RequestParam(required = false) String condition,
            @ApiParam("约束条件对应的信息") @RequestParam(required = false) String data
    ) {
        return articleService.findByCondition(pageNumber, DEFAULT_PAGE_SIZE, condition, data);

请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java毕业

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值