基于javaweb+mysql的springboot个人博客系统(java+springboot+springsecurity+thymeleaf+html+mysql+redis)

基于javaweb+mysql的springboot个人博客系统(java+springboot+springsecurity+thymeleaf+html+mysql+redis)

运行环境

Java≥8、MySQL≥5.7

开发工具

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

适用

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

功能说明

基于javaweb+mysql的SpringBoot个人博客系统(java+springboot+springsecurity+thymeleaf+html+mysql+redis)

项目介绍

本系统是一个个人博客的管理系统,用户可以注册账号并登陆系统查看发布的文章并进行阅读评论等 本系统主要有三种用户: 1、游客角色主要功能: 没有登陆的用户,可以查询文章,但是无法进行评论,系统中的所有文章可以通过内容搜索,可以通过分类搜索也可以通过标签就行搜索 2、注册用户主要功能 可以对所有的文章进行阅读以及评论等功能,可以对文章进行赞赏(支付宝或者微信付钱) 3、管理员主要功能: 拥有注册用户的所有权限,管理分类以及发布文章和管理标签等,友链管理,时间轴管理等

环境需要

1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。 2.IDE环境:IDEA,Eclipse,Myeclipse都可以。推荐IDEA; 3.硬件环境:windows 7/8/10 1G内存以上;或者 Mac OS; 4.数据库:MySql 5.7版本; 5.是否Maven项目:是;

技术栈

SpringBoot+SpringSecurity+Mybatis+Mysql+Redis+Thymeleaf+JQuery

使用说明

  1. 使用Navicat或者其它工具,在mysql中创建对应名称的数据库,并导入项目的sql文件; 2. 使用IDEA/Eclipse/MyEclipse导入项目,导入成功后请执行maven clean;maven install命令,然后运行; 3. 将项目中application.yml配置文件中的数据库配置改为自己的配置; 4. 运行项目,项目运行成功后,访问地址localhost:8080 管理员账号密码:zhangpeng98aliyun.com/mt2680324 用户账号密码:zhangpengaliyun.com/mt2680324

@Component
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    //ObjectMapper:Jackson框架的工具类,用于将对象转为json字符串
    private ObjectMapper mapper = new ObjectMapper ();

    @Autowired
    private UserService userService;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        Map map = new HashMap ();
        map.put ("login_info", true);
        response.setContentType ("application/json;charset=utf-8");

        //登录成功,将用户保存到session
        //获取认证成功保存的user
        SecurityContext context = SecurityContextHolder.getContext ();
        UserInfo user = (UserInfo) context.getAuthentication ().getPrincipal ();
        /*String email = user.getUsername ();
        UserInfo userInfo = userService.findByEmail (email);
        request.getSession ().setAttribute ("user", userInfo);*/

        boolean flag = false;
        Collection<GrantedAuthority> authorities = user.getAuthorities ();
        for (GrantedAuthority authority : authorities) {
            //判断是不是管理员
            if (authority.getAuthority ().equals ("ROLE_ADMIN")) {
                flag = true;
                break;
            }
        }

        if (flag){
            map.put ("admin",true);
        } else {
            map.put ("admin",false);
        }

        mapper.writeValue (response.getOutputStream (), map);
    }
}

        return "redirect:showAllMessages";
    }

    @RequestMapping("/showAllMessages")
    public String showAllMessages(@RequestParam(name = "pageNum", required = false, defaultValue = "1") Integer pageNum,
                                  @RequestParam(name = "pageSize", required = false, defaultValue = "6") Integer pageSize,
                                  Model model) {

        showAll (pageNum, pageSize, model);
        return "messages :: messageList";
    }

}

@Component
public class ImageCodeAuthenticationFilter extends OncePerRequestFilter {

    @Autowired
    private AuthenticationFailureHandler authenticationFailureHandler;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        //判断当前请求是否是登录请求
        if (request.getRequestURI ().contains ("/securityLogin")) {
            try {
                //获取用户输入的验证码
                String imageCode = request.getParameter ("vercode");

                //获取系统生成的验证码
                String key = (String) request.getSession ().getAttribute ("code");

                if (StringUtils.isEmpty (imageCode)) {
        //获取方法参数
        Object[] args = joinPoint.getArgs ();
        //通过反射获取Method
        if (args == null || args.length == 0) {
            method = clazz.getMethod (methodName); //获取无参的方法
        } else {
            Class[] classes = new Class[args.length];
            for (int i = 0; i < args.length; i++) {
                //Model 类型的参数注入的是BindingAwareModelMap类,这个类是Model接口实现类ExtendedModelMap类的子类
                if (args[i] instanceof BindingAwareModelMap) {
                    //将子类BindingAwareModelMap强转为父类ExtendedModelMap,这个类是Model接口的实现类  clazz.getMethod (methodName, classes); 就不会出现类型转换异常
                    classes[i] = Model.class;
                    continue;
                }
                if (args[i] instanceof RedirectAttributesModelMap) {
                    classes[i] = RedirectAttributes.class;
                    continue;
                }
                if (args[i] instanceof BeanPropertyBindingResult) {
                    classes[i] = BindingResult.class;
                    continue;
                }
                if (args[i] instanceof ArrayList) {
                    classes[i] = List.class;
                    continue;
                }

                classes[i] = args[i].getClass ();
            }
            method = clazz.getMethod (methodName, classes);

        }
    }

    //后置通知   主要获取日志中其它信息,时长、ip、url...
    @AfterReturning("pt()")
    public void doAfter() {
        //获取url -->  /orders/findAll.do
        String url = "";
        if (clazz != null && method != null) {
            //1.获取类上 @RequestMapping("/product") 注解中的value值
            RequestMapping clazzAnnotation = (RequestMapping) clazz.getAnnotation (RequestMapping.class);
            if (clazzAnnotation != null) {
                String[] classValue = clazzAnnotation.value ();
                //2.获取方法上 @RequestMapping("/findAll.do") 注解中的value值
                RequestMapping methodAnnotation = method.getAnnotation (RequestMapping.class);
                if (methodAnnotation != null) {

@Controller
@RequestMapping("/user")
public class UserController {

    private final Logger logger = LoggerFactory.getLogger (this.getClass ());

    @Autowired
    private UserService userService;

    @RequestMapping("/login")
    public String login() {
        return "user/login";
    }

    @RequestMapping("toRegister")
    public String toRegister() {
        return "user/register";
    }

    @RequestMapping("/toUpload")
    public String toUpload() {
        return "user/upload";
    }

    @RequestMapping("/updatePassword")
    @ResponseBody
    public Map<String, Object> updatePassword(String password){
        Map<String, Object> map = new HashMap<> ();
        UserInfo user = (UserInfo) SecurityContextHolder.getContext ().getAuthentication ().getPrincipal ();
        Long id = user.getId ();

        try {
            userService.updatePassword (id, password);
            user = null;
            map.put ("flag",true);
            map.put ("msg","修改成功");
        } catch (Exception e) {
            map.put ("flag",false);
            map.put ("msg","修改失败!服务器异常");
            e.printStackTrace ();
        }

        return map;
    }
}

@Controller
@RequestMapping("/admin/blog")
public class AdminBlogController {

    @Autowired
    private BlogService blogService;


        //调用service层删除类别
        Boolean aBoolean = typeService.deleteById (id);
        if (aBoolean){
            attributes.addFlashAttribute ("message","删除成功!");
        } else {
            attributes.addFlashAttribute ("message","删除失败,有博客是该类别!");
        }

        return "redirect:showAll";
    }
}

@Controller
@RequestMapping("/admin/tag")
public class AdminTagController {

    @Autowired
    private TagService TagService;

    @RequestMapping("/showAll")
    public ModelAndView showAll(@RequestParam(name = "pageNum", required = false, defaultValue = "1") Integer pageNum,
                                @RequestParam(name = "pageSize", required = false, defaultValue = "5") Integer pageSize,
                                @RequestParam(name = "name", required = false, defaultValue = "") String name){
        ModelAndView mv = new ModelAndView ();

        //调用service层获取数据
                         @RequestParam(name = "typeId", required = false, defaultValue = "0") Integer typeId,
                         @RequestParam(name = "recommend", required = false, defaultValue = "false") Boolean recommend,
                         Model model) {

        if (recommend == false) {
            recommend = null;
        }

        //调用业务层方法
        List<Blog> blogs = blogService.selectAll (pageNum, pageSize, title, typeId, recommend);
        PageInfo<Blog> pageInfo = new PageInfo<> (blogs, 5);

        model.addAttribute ("pageInfo", pageInfo);
        return "admin/blogs::blogList";
    }

    @RequestMapping("/toAdd")
    public String toAdd(Model model) {

        //添加博客页前展示所有类别
        List<Type> types = typeService.selectAll ();
        model.addAttribute ("types", types);

        //添加博客页前展示所有标签
        List<Tag> tags = tagService.selectAll ();
        model.addAttribute ("tags", tags);

        return "admin/blogs-input";
    }

    @RequestMapping("/add")
    public String add(Blog blog, @RequestParam(name = "tagIds", required = false) List<Integer> tagIds, RedirectAttributes attributes) {
        blog.setViews (0);
        blog.setCreateTime (new Date ());
        blog.setUpdateTime (new Date ());
        blog.setCommentCount (0);

        blog.setTags (getTags (tagIds));
        //获取用户id
        UserInfo userInfo = (UserInfo) SecurityContextHolder.getContext ().getAuthentication ().getPrincipal ();
        blog.setUserInfo (new UserInfo (userInfo.getId ()));

        //封装完成,调用service层保存
        Boolean save = blogService.save (blog);
        if (save) {
            attributes.addFlashAttribute ("message", "添加成功!");
        } else {

    @RequestMapping("/showAllMessages")
    public String showAllMessages(@RequestParam(name = "pageNum", required = false, defaultValue = "1") Integer pageNum,
                                  @RequestParam(name = "pageSize", required = false, defaultValue = "6") Integer pageSize,
                                  Model model) {

        showAll (pageNum, pageSize, model);
        return "messages :: messageList";
    }

}

@Component
public class ImageCodeAuthenticationFilter extends OncePerRequestFilter {

    @Autowired
    private AuthenticationFailureHandler authenticationFailureHandler;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        //判断当前请求是否是登录请求
        if (request.getRequestURI ().contains ("/securityLogin")) {
            try {
                //获取用户输入的验证码
                String imageCode = request.getParameter ("vercode");

                //获取系统生成的验证码
                String key = (String) request.getSession ().getAttribute ("code");

                if (StringUtils.isEmpty (imageCode)) {
                    throw new ImageCodeException ("验证码不能为空!");
                }

                if (!imageCode.equalsIgnoreCase (key)) {
                    throw new ImageCodeException ("验证码输入错误!");
                }

                    continue;
                }
                if (args[i] instanceof ArrayList) {
                    classes[i] = List.class;
                    continue;
                }

                classes[i] = args[i].getClass ();
            }
            method = clazz.getMethod (methodName, classes);

        }
    }

    //后置通知   主要获取日志中其它信息,时长、ip、url...
    @AfterReturning("pt()")
    public void doAfter() {
        //获取url -->  /orders/findAll.do
        String url = "";
        if (clazz != null && method != null) {
            //1.获取类上 @RequestMapping("/product") 注解中的value值
            RequestMapping clazzAnnotation = (RequestMapping) clazz.getAnnotation (RequestMapping.class);
            if (clazzAnnotation != null) {
                String[] classValue = clazzAnnotation.value ();
                //2.获取方法上 @RequestMapping("/findAll.do") 注解中的value值
                RequestMapping methodAnnotation = method.getAnnotation (RequestMapping.class);
                if (methodAnnotation != null) {
                    String[] methodValue = methodAnnotation.value ();
                    //3.获取URL
                    if (classValue[0] != null && methodValue[0] != null) {
                        url = classValue[0] + methodValue[0];
                    }

//                    String uri = request.getRequestURI ();

                    //获取执行时间
                    Integer executionTime = Math.toIntExact (new Date ().getTime () - visitTime.getTime ());

                    //获取ip  需要request获取 --》 获取request需要在web.xml中配置Listener  RequestContextListener类 在注入HttpServletRequest
                    //获取request对象
                    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes ();
                    HttpServletRequest request = attributes.getRequest ();

@Controller
@RequestMapping("/user")
public class UserController {

    private final Logger logger = LoggerFactory.getLogger (this.getClass ());

    @Autowired
    private UserService userService;

    @RequestMapping("/login")
    public String login() {
        return "user/login";
    }

    @RequestMapping("toRegister")
    public String toRegister() {
        return "user/register";
    }

    @RequestMapping("/toUpload")
    public String toUpload() {
        return "user/upload";
    }

    //更换图片
    @PostMapping("/upload")
    @ResponseBody

@Controller
@RequestMapping("/user")
public class UserController {

    private final Logger logger = LoggerFactory.getLogger (this.getClass ());

    @Autowired
    private UserService userService;

    @RequestMapping("/login")
    public String login() {
        return "user/login";
    }

    @RequestMapping("toRegister")
    public String toRegister() {
        return "user/register";
    }

    @RequestMapping("/toUpload")
    public String toUpload() {
        return "user/upload";
    }

    //更换图片
    @PostMapping("/upload")
    @ResponseBody
    public Map<String, Object> upload(MultipartFile file, HttpServletRequest request) throws FileNotFoundException {
        Map<String, Object> map = new HashMap<> ();
        //文件上传的地址  static下的upload文件夹
        String property = System.getProperty ("user.dir");  //获取当前目录。相当于linux的pwd命令
        String separator = System.getProperty ("file.separator");  //获取文件分隔符 Windows是\  linux是/
        property = property + separator + "upload";
        File file2 = new File (property);
        // 创建File对象,一会向该路径下上传文件
        //不存在则创建
        if (!file2.exists ()) {
            file2.mkdir ();
        }
        System.out.println (file2.getAbsolutePath ());
        //上传的文件
        userInfo.setUpdateTime (new Date ());

        boolean register = userService.register (userInfo);
        if (register) {
           // String message = "你好," + userInfo.getNickname () + "! <a href='http://59.110.60.4:80/user/active?email=" + userInfo.getEmail () + "'>点击激活</a>";
            // SendEmailUtil.sendMessage (userInfo.getEmail (),  message);
            map.put ("flag", true);
        } else {
            map.put ("flag", false);
            map.put ("reg_error", "邮箱已存在");
        }

        return map;
    }

    //邮箱激活
    @RequestMapping("/active")
    public String active(String email, RedirectAttributes attributes) {
        UserInfo userInfo = userService.findByEmail (email);
        Boolean status = userInfo.getStatus ();

        try {
            userService.updateStatus (email, !status);
            attributes.addFlashAttribute ("flag", true);
            attributes.addFlashAttribute ("msg", "激活成功!");
        } catch (Exception e) {
            e.printStackTrace ();
            attributes.addFlashAttribute ("flag", false);
            attributes.addFlashAttribute ("msg", "激活失败!服务器异常");
        }

        return "redirect:login";
    }

    //去忘记密码页面
    @RequestMapping("/forget")
    public String forget() {
        return "user/forget";
    }

    @RequestMapping("/forget/sendCode")
    @ResponseBody
    public Map<String, Object> sendCode(String email, Model model) {
        Map<String, Object> map = new HashMap<> ();
        //生成6位激活码
        String activeCode = RandomUtil.randomString (6);

        //发送激活码
        String message = "您好,你的个人博客激活码为:<strong>" + activeCode + "</strong>";
    public String showAll(@RequestParam(name = "pageNum", required = false, defaultValue = "1") Integer pageNum,
                          @RequestParam(name = "pageSize", required = false, defaultValue = "2") Integer pageSize,
                          @RequestParam(name = "email", required = false, defaultValue = "") String email, Model model) {

        show (pageNum, pageSize, email, model);
        return "admin/users";
    }

    public void show(Integer pageNum, Integer pageSize, String email, Model model){
        List<UserInfo> userInfos = userService.selectAll (pageNum, pageSize, email);
        PageInfo<UserInfo> pageInfo = new PageInfo<> (userInfos,8);
        model.addAttribute ("pageInfo",pageInfo);
        model.addAttribute ("email",email);
    }

    @RequestMapping("/showAll/search")
    public String search(@RequestParam(name = "pageNum", required = false, defaultValue = "1") Integer pageNum,
                          @RequestParam(name = "pageSize", required = false, defaultValue = "2") Integer pageSize,
                          @RequestParam(name = "email", required = false, defaultValue = "") String email, Model model) {

        show (pageNum, pageSize, email, model);
        return "admin/users :: userList";
    }

    @RequestMapping("/updateStatus")
    public String updateStatus(String email, RedirectAttributes attributes) {
        UserInfo userInfo = userService.findByEmail (email);
        Boolean status = userInfo.getStatus ();

        try {
            userService.updateStatus (email, !status);
            attributes.addFlashAttribute ("message","状态修改成功!");
        } catch (Exception e) {
            attributes.addFlashAttribute ("message","状态修改失败,服务器异常!");
            e.printStackTrace ();
        }

        return "redirect:showAll";
    }

}

        return "user/register";
    }

    @RequestMapping("/toUpload")
    public String toUpload() {
        return "user/upload";
    }

    //更换图片
    @PostMapping("/upload")
    @ResponseBody
    public Map<String, Object> upload(MultipartFile file, HttpServletRequest request) throws FileNotFoundException {
        Map<String, Object> map = new HashMap<> ();
        //文件上传的地址  static下的upload文件夹
        String property = System.getProperty ("user.dir");  //获取当前目录。相当于linux的pwd命令
        String separator = System.getProperty ("file.separator");  //获取文件分隔符 Windows是\  linux是/
        property = property + separator + "upload";
        File file2 = new File (property);
        // 创建File对象,一会向该路径下上传文件
        //不存在则创建
        if (!file2.exists ()) {
            file2.mkdir ();
        }
        System.out.println (file2.getAbsolutePath ());
        //上传的文件
        //获取到要上传文件的文件名
        String fileName = file.getOriginalFilename ();
        //生成一个唯一的文件名
        String uuid = UUID.randomUUID ().toString ().replace ("-", "").toUpperCase ();
        fileName = separator +  uuid + "-" + fileName;

        logger.info ("上传文件路径{}", file2.getAbsolutePath () + fileName);

        //上传
        try {
            file.transferTo (new File (file2.getAbsolutePath (), fileName));
            map.put ("code", -1);
            //设置保存在/static/upload下的访问路径 ---> /upload/图片名称
            String uploadPath = file2.getAbsolutePath () + fileName;
            uploadPath = uploadPath.substring (uploadPath.indexOf (separator+"upload"));
            //改变存储在session的头像地址
            UserInfo user = (UserInfo) SecurityContextHolder.getContext ().getAuthentication ().getPrincipal ();


}

@Controller
@RequestMapping("/admin/comment")
public class AdminCommentController {

    @Autowired
    private CommentService commentService;

    @RequestMapping("/showAll")
    public String showAll(@RequestParam(name = "pageNum", required = false, defaultValue = "1") Integer pageNum,
                          @RequestParam(name = "pageSize", required = false, defaultValue = "6") Integer pageSize,
                          @RequestParam(name = "content", required = false, defaultValue = "") String content,
                          @RequestParam(name = "email", required = false, defaultValue = "") String email,
                          @RequestParam(name = "blogId", required = false, defaultValue = "-1") Long blogId,
                          Model model) {

        if (blogId == -1){
            blogId = null;
        }

        show (pageNum, pageSize, content, email, blogId, model);
        model.addAttribute ("pageSize", pageSize);
        model.addAttribute ("content", content);
        model.addAttribute ("email", email);
        return "admin/comments";
    }

            }
            tagIds = tagIds.substring (1);
        }

        model.addAttribute ("tagIds", tagIds);

        return "admin/blogs-update";
    }

    @RequestMapping("/update")
    public String update(Blog blog, @RequestParam(name = "tagIds", required = false) List<Integer> tagIds, RedirectAttributes attributes) {
        blog.setUpdateTime (new Date ());
        blog.setTags (getTags (tagIds));
        //获取用户id
        UserInfo userInfo = (UserInfo) SecurityContextHolder.getContext ().getAuthentication ().getPrincipal ();
        blog.setUserInfo (new UserInfo (userInfo.getId ()));
        Boolean update = blogService.update (blog);
        if (update) {
            attributes.addFlashAttribute ("message", "修改成功!");
        } else {
            attributes.addFlashAttribute ("message", "修改失败!");
        }

        return "redirect:showAll";
    }

    @RequestMapping("/deleteById")
    public String deleteById(Long id, RedirectAttributes attributes) {

        Boolean aBoolean = blogService.deleteById (id);
        if (aBoolean) {
            attributes.addFlashAttribute ("message", "删除成功!");
        } else {
            attributes.addFlashAttribute ("message", "删除失败!");
        }

        return "redirect:showAll";
    }
}

        if (save){
            attributes.addFlashAttribute ("message","添加成功!");
        } else {
            attributes.addFlashAttribute ("message","添加失败!");
        }

        return "redirect:showAll";
    }

    @RequestMapping("/toUpdate")
    public ModelAndView toUpdate(Integer id){
        ModelAndView mv = new ModelAndView ();

        Type type = typeService.selectById (id);

        mv.addObject ("type",type);
        mv.setViewName ("admin/types-update");
        return mv;
    }

    @RequestMapping("/update")
    public String update(@Valid Type type, BindingResult result, RedirectAttributes attributes){

        Type type1 = typeService.selectByName (type.getName ());
        if (type1 != null){
            result.rejectValue ("name","nameError","该类别名称已存在,不能修改!");
        }

        if (result.hasErrors ()){
            return "admin/types-update";
        }

        Boolean update = typeService.update (type);
        if (update){
            attributes.addFlashAttribute ("message","修改成功!");
        } else {
            attributes.addFlashAttribute ("message","修改失败!");
        }

        return "redirect:showAll";
    }

    @RequestMapping("/deleteById")
    public String deleteById(Integer id, RedirectAttributes attributes){

        //调用service层删除类别

@Aspect
@Component
public class BlogAspectLog {

    @Autowired
    private SysLogService sysLogService;

    private Date visitTime;  //访问时间
    private Class clazz;  //访问的类
    private Method method; //访问的方法

    @Pointcut("execution(* com.zp.blog.web.*.*.*(..)) && !execution(* com.zp.blog.web.back.AdminSysLogController.*(..)) && !execution(* com.zp.blog.web.comment.*.*(..))")
    public void pt() {
    }

    @Before("pt()")
    public void doBefore(JoinPoint joinPoint) throws NoSuchMethodException {
        visitTime = new Date ();  //获取访问时间
        clazz = joinPoint.getTarget ().getClass ();  //获取访问的类
        String methodName = joinPoint.getSignature ().getName ();  //获取访问的方法的名称
        //获取方法参数
        Object[] args = joinPoint.getArgs ();
        //通过反射获取Method
        if (args == null || args.length == 0) {
            method = clazz.getMethod (methodName); //获取无参的方法
        } else {
            Class[] classes = new Class[args.length];
            for (int i = 0; i < args.length; i++) {

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值