基于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+mysql的SpringBoot个人博客系统(前后端分离+java+vue+springboot+ssm+mysql+maven+redis)
一、项目简述
本系统功能包括:文章展示、热门文章、文章分类、标签云用户登录评论、匿名评论用户留言、匿名留言评论管理、文章发布、文章管理文章数据统计等等.
二、项目运行
环境配置: Jdkl . 8 + Tomcats . 5 + Mysql + HBuilderX ( Webstorm 也行) + Eclispe ( IntelliJ 10 以,三 clispe , MyEclispe , Sts 都支持)。
项目技术: Springboot + Maven + Mybatis + Vue + Redis 组成, BIS 模式+ M aven 等等,附带支付宝沙箱环境以及支付环节代码。
/**
* @description 用户相关api
*/
@Controller("commUserController")
@RequestMapping("/comm/user")
@Slf4j
public class UserController {
@Autowired
private UserMapper userMapper;
@Autowired
private GiteeProvider giteeProvider;
@Autowired
private UserService userService;
@Autowired
private QQProvider qqProvider;
@Value("${blog.client}")
private String clientUrl;
@ApiOperation("获取用户信息")
@GetMapping("/info")
@ResponseBody
public UserVO getUserInfo(@ApiParam("用户登录态标识") @NotNull(message = "token不能为空") String token) {
UserDO userDO = userMapper.findByToken(token);
if (userDO != null) {
UserVO userVO = UserVO.create(userDO);
return userVO;
}
throw new TokenExpiredException();
}
@ApiOperation("用户登录,返回用户登录地址")
@GetMapping("/login")
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,
/**
* @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}")
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;
}
@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;
}
@ApiOperation("根据id删除对应评论")
@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;
}
@ApiOperation("根据id删除对应评论")
@DeleteMapping("/{id}")
public ResultVO delById(@PathVariable Long id) {
commentService.deleteById(id);
return ResultVO.ok("操作成功!");
@RestController
@RequestMapping("plugins")
public class WebSitesController {
@Autowired
private ConfigMapper configMapper;
@ApiOperation("获取网站导航信息")
@GetMapping("/websites")
public Map<String, String> get() {
ConfigDO configDO = configMapper.findByKey("websites");
return MapUtil.of("content", configDO != null ? configDO.getValue() : "");
}
@ApiOperation("增加或更新网站导航信息")
@PostMapping("/websites")
public ResultVO post(@RequestBody ConfigDO configDO) {
ConfigDO config = configMapper.findByKey(configDO.getKey());
if (config != null) {
configMapper.update(configDO);
} else {
configMapper.insert(configDO);
}
return ResultVO.ok("操作成功!");
}
}
/**
* @description 与评论相关的api
*/
@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("评论成功!");
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(
public ResponseEntity<ResultVO> handleMethodArgumentNotValidException(Exception exception, HttpServletResponse response) {
String message = getMessage((MethodArgumentNotValidException) exception);
log.error("message:{}", message);
ResultVO resultVO = ResultVO.error(message, RespCode.MISSING_PARAMETERS);
return new ResponseEntity<>(resultVO, HttpStatus.valueOf(response.getStatus()));
}
@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();
}
}
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;
}
@ApiOperation("根据id删除对应评论")
@DeleteMapping("/{id}")
public ResultVO delById(@PathVariable Long id) {
public ResponseEntity<ResultVO> handleNoHandlerFoundException(Exception exception) {
log.error("message:{}", exception.getMessage());
ResultVO resultVO = ResultVO.error(exception.getMessage(), RespCode.RESOURCES_NOT_FOUND);
return new ResponseEntity<>(resultVO, HttpStatus.NOT_FOUND);
}
@ExceptionHandler(value = MethodArgumentNotValidException.class)
@ResponseBody
public ResponseEntity<ResultVO> handleMethodArgumentNotValidException(Exception exception, HttpServletResponse response) {
String message = getMessage((MethodArgumentNotValidException) exception);
log.error("message:{}", message);
ResultVO resultVO = ResultVO.error(message, RespCode.MISSING_PARAMETERS);
return new ResponseEntity<>(resultVO, HttpStatus.valueOf(response.getStatus()));
}
@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();
}
}
public class WebSitesController {
@Autowired
private ConfigMapper configMapper;
@ApiOperation("获取网站导航信息")
@GetMapping("/websites")
public Map<String, String> get() {
ConfigDO configDO = configMapper.findByKey("websites");
return MapUtil.of("content", configDO != null ? configDO.getValue() : "");
}
@ApiOperation("增加或更新网站导航信息")
@PostMapping("/websites")
public ResultVO post(@RequestBody ConfigDO configDO) {
ConfigDO config = configMapper.findByKey(configDO.getKey());
if (config != null) {
configMapper.update(configDO);
} else {
configMapper.insert(configDO);
}
return ResultVO.ok("操作成功!");
}
}
/**
* @description 与评论相关的api
*/
@RestController("commCommentController")
@RequestMapping("comm/comment")
public class CommentController {
@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;
}
}
/**
* @description 用户相关api
*/
@Controller("commUserController")
@RequestMapping("/comm/user")
@Slf4j
public class UserController {
@Autowired
private UserMapper userMapper;
@Autowired
private GiteeProvider giteeProvider;
@Autowired
private UserService userService;
@Autowired
private QQProvider qqProvider;
@Value("${blog.client}")
private String clientUrl;
@ApiOperation("获取用户信息")
@GetMapping("/info")
@ResponseBody
private String uri;
@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 {
userService.giteeLogin(userDTO, token);
res.setStatus(302);
res.setHeader("location", clientUrl + "?token=" + token);
}
@ApiOperation("用户使用QQ登录的回调地址")
@GetMapping("/qq/callback")
public void qqCallback(AuthCallback callback, HttpServletResponse res) {
QQUserDTO userDTO = qqProvider.getUserInfo(callback);
//log.info(userDTO.toString());
String token = UUID.randomUUID().toString();
// 登录之后生成token
userService.qqLogin(userDTO, token);
res.setStatus(302);
res.setHeader("location", clientUrl + "?token=" + token);
}
}
/**
* @e-mail 1413979079@qq.com
* @description 草稿
*/
@RestController
@RequestMapping("admin/draft")
public class DraftController {
@Autowired
private DraftMapper draftMapper;
draftDO.setContent(draftDTO.getContent());
draftDO.setGmtUpdate(System.currentTimeMillis());
draftDO.setGmtCreate(draftDO.getGmtUpdate());
draftDO.setId(id);
draftMapper.insDraft(draftDO);
Map<String, Object> map = new HashMap<>();
map.put("msg", "文章已自动保存,上次保存时间:" + Utils.formatDate(draftDO.getGmtUpdate(), DATE_TIME_PATTERN));
map.put("id", id);
return map;
}
@ApiOperation("更新草稿")
@PutMapping("/")
public Map<String, Object> updDraft(@RequestBody DraftDTO draftDTO) {
DraftDO draftDO = new DraftDO();
String id = draftDTO.getId();
draftDO.setId(id);
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("删除成功");
}
}
@GetMapping("/export")
public void export(HttpServletResponse res, String token) {
boolean isValid = configService.checkToken(token);
if (!isValid) {
res.setStatus(HttpStatus.FORBIDDEN.value());
return;
}
res.setContentType("application/forc-download");
res.setHeader("Content-Disposition", "attachment;filename=blog_data.db");
BlogData blogData = blogService.export();
ServletOutputStream out = null;
try {
out = res.getOutputStream();
byte[] bytes = ObjectUtil.serialize(blogData);
out.write(bytes);
} catch (IOException e) {
log.error("导出博客数据中,文件下载失败:{}", e.getMessage());
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@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("获取统计图表的信息")
}
@ApiOperation("用户使用QQ登录的回调地址")
@GetMapping("/qq/callback")
public void qqCallback(AuthCallback callback, HttpServletResponse res) {
QQUserDTO userDTO = qqProvider.getUserInfo(callback);
//log.info(userDTO.toString());
String token = UUID.randomUUID().toString();
// 登录之后生成token
userService.qqLogin(userDTO, token);
res.setStatus(302);
res.setHeader("location", clientUrl + "?token=" + token);
}
}
/**
* @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)