集技术、艺术、运动于一身的个人博客。

1. 总述:

这是我在寝室写完的第一个博客项目,没有使用博客主题搭建,页面都是自己写的,花了挺多心思的。

项目除了基本的博客、分类、标签、归档模块以外,还有留言、资源库、音乐秀、跑步秀、图片库等模块,这些都是我后来想到结合我个人兴趣然后去写的。

整个前后端代码几乎一大半都是自己写的,没有使用第三方技术(项目简单),这个过程让我收获到了很多,以后继续加油。

1.1 主要使用技术

  • 前端:Semantic UI框架,Bootstrap 框架,Layui框架,jquery。
  • 后端:SpringBoot + MyBatis-Plus + Thymeleaf 引擎模板
  • 数据库:Mysql
  • 整合技术:JMS邮件

1.2 主要技术点

  1. 异步任务
  2. 定时任务
  3. 邮件任务
  4. session、cookie使用
  5. 统一异常处理
  6. 登录拦截
  7. 自定义日志注解

2. 部分效果图:

 

 

 

 

 

 

 

 

3. 部分代码

  • 博客controller
    @Slf4j
    @Controller
    public class UserBlogController {
        @Autowired
        private BlogService blogService;
    
        //整个博客首页
        @GetMapping
        @WebLog(description = "用户进入网站介绍首页")
        public String main(Model model, HttpServletRequest request){
            return blogService.main(model,request);
        }
    
        //去前台博客博客首页
        @GetMapping("/user")
        @WebLog(description = "用户进入首页")
        public String uindex(HttpSession session, Model model,HttpServletResponse response,HttpServletRequest request,
                            @RequestParam(value = "current",defaultValue = "1")Integer current,
                             @RequestParam(value = "pageSize",defaultValue = "9")Integer pageSize){
            return blogService.uindex(session,model,response,request,current,pageSize);
        }
    
        //访客查看博客详情
        @GetMapping("/user/blog/{id}")
        @WebLog(description = "用户查看博客详情")
        public String blog(@PathVariable("id") Long id,Model model,HttpServletRequest request){
            return blogService.userGetBlogById(id,model,request);
        }
    
        //通过博客名字搜索博客id和名字
        @ResponseBody
        @PostMapping("/blog")
        @WebLog(description = "用户全局搜索博客")
        public Msg blog(String title){
            return blogService.blog(title);
        }
    
        //博客相关信息
        @ResponseBody
        @GetMapping("/footer/blogMessage")
        public Msg blogMessage(){
            return Msg.success().add("blogcount",blogService.blogCount())
                                .add("viewcount",blogService.viewCount())
                                .add("visitorcount",blogService.visitorCount())
                                .add("commentcount",blogService.commentCount())
                                .add("messagecount",blogService.messageCount());
        }
    
        //点赞增加
        @ResponseBody
        @PostMapping("/user/blog/likes/add")
        @WebLog(description = "用户点赞博客")
        public Msg add(Long id){
            return blogService.addLike(id);
        }
    
    }
  • 统一异常处理
    @Slf4j
    @ControllerAdvice
    public class ExceptionController {
    
        @Autowired
        private SendEmail sendEmail;
        @Autowired
        JavaMailSender mailSender;
        @Autowired
        TemplateEngine templateEngine;
    
        @ExceptionHandler(Exception.class)
        public ModelAndView excetionHandler(HttpServletRequest request, HttpServletResponse response, Exception e) throws Exception {
            log.error("Request URL: {},Exception: {}",request.getRequestURL(),e);
    
            String title="网站发生错误!!!";
            StackTraceElement[] trace = e.getStackTrace();
            String to="xxxxxxxxx";
            String content=arrayToString(trace);
            Context context = new Context();
            context.setVariable("url",request.getRequestURL());
            context.setVariable("status",response.getStatus());
            context.setVariable("message",e.getMessage());
            context.setVariable("detail",content);
            String process=templateEngine.process("errorMail",context);
            sendEmail.sendHtmlMail(to,title,process,mailSender);
    
            if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null) {
                throw e;
            }
            ModelAndView mv=new ModelAndView();
            mv.addObject("url",request.getRequestURL());
            mv.addObject("exception",e);
            mv.setViewName("error/error");
    
            return mv;
        }
    
        public static String arrayToString(StackTraceElement[] arr){
            String content=new String();
            for (int i=0;i<arr.length;i++){
                content += arr[i]+"\n";
            }
            return content;
        }
    }
    

  • 自定义日志注解 
    @Aspect
    @Component
    @Slf4j
    public class LogAspect {
    
        /** 换行符 */
        private static final String LINE_SEPARATOR = System.lineSeparator();
    
        /** 以自定义 @WebLog 注解为切点 */
        @Pointcut("@annotation(com.example.my.aspect.WebLog)")
        public void webLog() {}
    
        /**
         * 在切点之前织入
         * @param joinPoint
         * @throws Throwable
         */
        @Before("webLog()")
        public void doBefore(JoinPoint joinPoint) throws Throwable {
            // 开始打印请求日志
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
    
            // 获取 @WebLog 注解的描述信息
            String methodDescription = getAspectLogDescription(joinPoint);
    
            // 打印请求相关参数
            log.warn("========================================== Start ==========================================");
            // 打印描述信息
            log.warn("Description    : {}", methodDescription);
            // 打印请求的 IP
            log.warn("IP             : {}", request.getRemoteAddr());
            /*// 打印请求 url
            log.warn("URL            : {}", request.getRequestURL().toString());
            // 打印请求入参
            //log.info("Request Args   : {}", new Gson().toJson(joinPoint.getArgs()));
            // 打印 Http method
            log.warn("HTTP Method    : {}", request.getMethod());
            // 打印调用 controller 的全路径以及执行方法
            log.warn("Class Method   : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());*/
        }
    
        /**
         * 在切点之后织入
         * @throws Throwable
         */
        @After("webLog()")
        public void doAfter() throws Throwable {
            // 接口结束后换行,方便分割查看
            log.warn("=========================================== End ===========================================" + LINE_SEPARATOR);
        }
    
        /**
         * 环绕
         * @param proceedingJoinPoint
         * @return
         * @throws Throwable
         */
    /*    @Around("webLog()")
        public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
            long startTime = System.currentTimeMillis();
            Object result = proceedingJoinPoint.proceed();
            // 打印出参
            log.warn("Response Args  : {}", new Gson().toJson(result));
            // 执行耗时
            log.warn("Time-Consuming : {} ms", System.currentTimeMillis() - startTime);
            return result;
        }*/
    
    
        /**
         * 获取切面注解的描述
         *
         * @param joinPoint 切点
         * @return 描述信息
         * @throws Exception
         */
        public String getAspectLogDescription(JoinPoint joinPoint)
                throws Exception {
            String targetName = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            Object[] arguments = joinPoint.getArgs();
            Class targetClass = Class.forName(targetName);
            Method[] methods = targetClass.getMethods();
            StringBuilder description = new StringBuilder("");
            for (Method method : methods) {
                if (method.getName().equals(methodName)) {
                    Class[] clazzs = method.getParameterTypes();
                    if (clazzs.length == arguments.length) {
                        description.append(method.getAnnotation(WebLog.class).description());
                        break;
                    }
                }
            }
            return description.toString();
        }
    
    }
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.METHOD})
    @Documented
    public @interface WebLog {
        /**
         * 日志描述信息
         *
         * @return
         */
        String description() default "";
    
    }

  • 定时任务
    @Service
    public class Records {
    
        @Autowired
        private VisitorMapper visitorMapper;
        @Autowired
        private BlogMapper blogMapper;
        @Autowired
        private CommentMapper commentMapper;
        @Autowired
        private MessageMapper messageMapper;
    
        //昨日访客新增,访问量新增,评论量新增,留言量新增
        //corn 秒 分 时 日 月 周几
        @Scheduled(cron="0 1 0 * * ?")  //凌晨一点获取前一周的数据
        public void update(){
            updateRecords(1);
            updateRecords(2);
            updateRecords(3);
            updateRecords(4);
            updateRecords(5);
            updateRecords(6);
            updateRecords(7);
        }
    
        public int updateRecords(Integer num ){
            Key key = get(num);
            int visitor = key.getVisitor();
            int blogview=key.getView() ;
            int comment=key.getComment() ;
            int message= key.getMessage();
            int i = visitorMapper.updateRecords(key, -num,visitor,  blogview , comment , message);
            return i;
        }
    
        public Key get(Integer num){
            DateTime dt = new DateTime();
            String yes = dt.minusDays(num).toString("yyyy-MM-dd");
            int visitor = visitorMapper.selectCount(new QueryWrapper<Visitor>().like("create_time", yes));
            int blogview = blogMapper.yesviewCount(yes);
            int comment = commentMapper.selectCount(new QueryWrapper<Comment>().like("create_time", yes));
            int message = messageMapper.selectCount(new QueryWrapper<Message>().like("create_time", yes));
            Key k=new Key();
            k.setVisitor(visitor);
            k.setView(blogview);
            k.setComment(comment);
            k.setMessage(message);
            return k;
        }
    }
    

 4. 总结

项目大概就是这样子,大二结束我写完这个项目知道了自己的不足也收获到了很多,后面继续加油,欢迎大家来访问留言,==》》(https:tgcsblog.top)~ 欢迎来到我的小栈 ~电脑访问效果更好哦。也可到b站查看动态效果视频:集技术、艺术、运动于一身的个人博客。_哔哩哔哩_bilibili。如果有错或更好的建议请指出,谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值