blog保姆级别开发流程一

基于SpringBoot开发blog

2020-9-29

个人博客介绍

博客地址:http://8.129.69.60/

技术栈:

  • 后端:Spring Boot 2 + JPA + thymeleaf
  • 数据库:MySQL
  • 前端UI:Semantic UI

开发环境:

  • IDEA 2020
  • Maven 3
  • JDK 8

需求分析

**角色:**访客和管理员(后面会添加普通用户)

具体功能:

*管理员:*登录博客后台管理和博客主页

  • 管理博客 :
    • 发布新博客
    • 对博客进行分类
    • 对博客打标签
    • 修改博客
    • 删除博客
    • 根据标题,分类,标签查询博客
  • 管理博客分类
    • 新增分类
    • 修改分类
    • 删除分类
    • 根据分类名称查询分类
  • 管理标签
    • 新增标签
    • 修改标签
    • 删除标签
    • 根据名称查询标签

*访客和普通用户:*浏览博客主页

  • 分页查看所有的博客

  • 快速查看博客数最多的6个分类

  • 查看所有的分类

  • 查看某个分类下的博客列表

  • 快速查看标记博客最多的10个标签

  • 查看所有的标签

  • 查看某个标签下的博客列表

  • 根据年度时间线查看博客列表

  • 快速查看最新的推荐博客

  • 用关键字全局搜索博客

  • 查看单个博客内容

  • 对博客内容进行评论

  • 赞赏博客内容

  • 微信扫码阅读博客内容

  • 在首页扫描公众号二维码关注我

    在这里插入图片描述

前端页面设计与开发

在这里插入图片描述

**静态资源:**resources/static

博客主页: resources/templates

  • 首页 index.html
  • 详情页 blog.html
  • 分类 types.html
  • 标签 tags.html
  • 归档 archives.html
  • 关于我 about.heml

后台管理: resources/templates/admin

  • 首页 index.html
  • 分类 types.html
  • 分类增加和修改 types-input.html
  • 标签 tags.html
  • 登录 login.html

thymeleaf布局: _fragments.html

错误处理: resources/templates/error

  • 404 : 404.html
  • 500 : 500.html
  • error : error.html

2020-9-30

后台开发

构建框架和配置

1·创建工程(不需要骨架)和pox.xml配置

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.lj</groupId>
	<artifactId>blog</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>
	<name>blog</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.6.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<!--  commonmark:markdown转换成text,html-->
		<dependency>
			<groupId>com.atlassian.commonmark</groupId>
			<artifactId>commonmark</artifactId>
			<version>0.10.0</version>
		</dependency>
		<!--        <h >标签id处理-->
		<dependency>
			<groupId>com.atlassian.commonmark</groupId>
			<artifactId>commonmark-ext-heading-anchor</artifactId>
			<version>0.10.0</version>
		</dependency>
		<!--        table处理-->
		<dependency>
			<groupId>com.atlassian.commonmark</groupId>
			<artifactId>commonmark-ext-gfm-tables</artifactId>
			<version>0.10.0</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
<!--		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<scope>provided</scope>&lt;!&ndash;由JDK或者容器提供&ndash;&gt;
		</dependency>-->
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-plugin</artifactId>
				<version>2.4.2</version>
				<configuration>
					<skipTests>true</skipTests>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>
2.springboot配置

springboot启动器**

package com.lj;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
public class BlogApplication extends SpringBootServletInitializer {

	public static void main(String[] args) {
		SpringApplication.run(BlogApplication.class, args);
	}

    //打成war包时要重写这个方法
	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
		return application.sources(BlogApplication.class);
	}
}

application.yml

spring:
  thymeleaf:
    mode: HTML
  profiles:
    active: dev  #测试时的配置

comment.avatar: /images/avatar.png

开发 application-dev.yml

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/blog?useUnicode=true&characterEncoding=utf-8
    username: root
    password: root
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
    open-in-view: true

logging:  #日志级别
  level:
    root: info
    com.lj: debug
  file: log/blog-dev.log

server:
  port: 8080

部署 application-pro.yml

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/blog?useUnicode=true&characterEncoding=utf-8
    username: root
    password: Root.123456
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
    open-in-view: true

logging:
  level:
    root: warn
    com.lj: info
  file: log/blog-pro.log

server:
  port: 80

整体结构

日志配置logback-spring.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <!--包含Spring boot对logback日志的默认配置-->
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />
    <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/spring.log}"/>
    <include resource="org/springframework/boot/logging/logback/console-appender.xml" />

    <!--重写了Spring Boot框架 org/springframework/boot/logging/logback/file-appender.xml 配置-->
    <appender name="TIME_FILE"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder>
            <pattern>${FILE_LOG_PATTERN}</pattern>
        </encoder>
        <file>${LOG_FILE}</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i</fileNamePattern>
            <!--保留历史日志一个月的时间-->
            <maxHistory>30</maxHistory>
            <!--
            Spring Boot默认情况下,日志文件10M时,会切分日志文件,这样设置日志文件会在100M时切分日志
            -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>

        </rollingPolicy>
    </appender>

    <root level="INFO">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="TIME_FILE" />
    </root>

</configuration>
        <!--
            1、继承Spring boot logback设置(可以在appliaction.yml或者application.properties设置logging.*属性)
            2、重写了默认配置,设置日志文件大小在100MB时,按日期切分日志,切分后目录:
                blog.2017-08-01.0   80MB
                blog.2017-08-01.1   10MB
                blog.2017-08-02.0   56MB
                blog.2017-08-03.0   53MB
                ......
        -->

3.异常处理

定义错误页面:

  • 404
  • 500
  • error

统一处理异常:

package lj.cn.handler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
/**
 * @author lj
 * @date 2020-10-01 17:13
 * @QQ 851477108
 */
//拦截有Controller注解的控制器
@ControllerAdvice
public class ControllerExceptionHandler {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    /**
     * 定义异常处理
     * @param request
     * @param e
     * @return
     * @throws Exception
     */
    @ExceptionHandler(Exception.class)
    public ModelAndView exceptionHander(HttpServletRequest request, Exception e) throws Exception {
        logger.error("Requst URL : {},Exception : {}", request.getRequestURL(),e);

//        当标识了状态码的时候就不拦截
        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;
    }
}

自定义异常配置类:

package lj.cn;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
/**
 * @author lj
 * @date 2020-10-01 17:33
 * @QQ 851477108
 */
//自定义异常
@ResponseStatus(HttpStatus.NOT_FOUND)
public class NotFoundException extends RuntimeException{
    public NotFoundException() {
    }
    public NotFoundException(String message) {
        super(message);
    }
    public NotFoundException(String message, Throwable cause) {
        super(message, cause);
    }
}
4.日志处理

记录日志切面类:

package lj.cn.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
/**
 * @Description: 日志切面处理
 * @author lj
 * @date 2020-10-01 18:27
 * @QQ 851477108
 * @Before: 前置通知, 在方法执行之前执行
 * @After: 后置通知, 在方法执行之后执行 。
 * @AfterRunning: 返回通知, 在方法返回结果之后执行
 * @AfterThrowing: 异常通知, 在方法抛出异常之后
 * @Around: 环绕通知, 围绕着方法执行
 */
@Aspect
@Component
public class LogAspect {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    //拦截controller控制器
    @Pointcut("execution(* lj.cn.controller.*.*(..))")
    public void log(){}
    /**
     * 前置通知
     */
    @Before("log()")
    public void doBefore(JoinPoint joinPoint){
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String url = request.getRequestURL().toString();
        String ip = request.getRemoteAddr();
        String classMethod = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        RequestLog requestLog = new RequestLog(url,ip,classMethod,args);
        logger.info("Request : {}", requestLog);
    }
    /**
     * 后置通知
     */
    @After("log()")
    public void doAfter(){
//        logger.info("---doAfter---");
    }
    /**
     * 返回通知
     * @param result
     */
    @AfterReturning(returning = "result",pointcut = "log()")
    public void doAfterReturn(Object result){
        logger.info("Result : {}",result);
    }
    /**
     * 封装的具体信息
     */
    private class RequestLog{
        private String url;
        private String ip;
        private String classMethod;
        private Object[] args;
        public RequestLog(String url, String ip, String classMethod, Object[] args){
            this.url = url;
            this.ip = ip;
            this.classMethod = classMethod;
            this.args = args;
        }
        @Override
        public String toString() {
            return "{" +
                    "url='" + url + '\'' +
                    ", ip='" + ip + '\'' +
                    ", classMethod='" + classMethod + '\'' +
                    ", args=" + Arrays.toString(args) +
                    '}';
        }
    }
}

b站上Spring Boot开发小而美的个人博客,感谢李仁密老师。博主是一个小白,漏洞勿喷。blog开发流程一,开发环境准备和功能简介以及整体框架的选择

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

木子津

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

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

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

打赏作者

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

抵扣说明:

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

余额充值