[记录学习]分析学习第一个SSM项目:ForestBlog _01

2023-11-02 409 0

首先感谢原作者的倾囊相授!

资源链接:https://github.com/saysky/ForestBlog

本内容仅为个人对整个项目的分析展示,用作学习,如有错误之处还望指点,本项目前端采用LayUI+前端三件套+jQuery实现,本人没有学过LayUI因此不做前端分析,仅展示部分运行部分的页面效果,打算在后续学习使用Vue框架进行实现,再根据分析经验重新对后端进行新的构建,尽力实现自己学习的第一个SSM项目,加油。

分析学习第一个SSM项目:ForestBlog

文章目录

    • 首先感谢原作者的倾囊相授!
  • 分析学习第一个SSM项目:ForestBlog
    • 目录基础结构
    • 一、分析pom.xml文件和web.xml文件
      • 1. pox.xml
      • 2. src/main/webapp/WEB-INF/web.xml
    • 二、分析main文件夹下文件
      • 1. 分析resources文件夹
        • 1.1 文件夹结构
        • 1.2 db.properties
        • 1.3 logback.xml
        • 1.4 mybatis/mybatis-config.xml
        • 1.5 spring文件夹
          • 1.5.1 spring-mvc.xml
          • 1.5.2 spring-mybatis.xml
      • 2. 分析java文件夹
        • 2.1 文件夹结构
        • 2.2 entity实体类
          • 2.2.0 实例关系分析
          • 2.2.1 Article
          • 2.2.2 ArticleCategoryRef
          • 2.2.3 ArticleTagRef
          • 2.2.4 Category
          • 2.2.5 Comment
          • 2.2.6 Link
          • 2.2.7 Menu
          • 2.2.8 Notice
          • 2.2.9 Options
          • 2.2.10 Page
          • 2.2.11 Tag
          • 2.2.12 User
        • 2.3 enums枚举类
          • 2.3.1 ArticleCommentStatus
          • 2.3.2 ArticleStatus
          • 2.3.3 CategoryStatus
          • 2.3.4 LinkStatus
          • 2.3.5 MenuLevel
          • 2.3.6 NoticeStatus
          • 2.3.7 PageStatus
          • 2.3.8 Role
          • 2.3.9 UserRole
        • 2.4 dto数据传输对象
          • 2.4.1 ArticleParam
          • 2.4.2 JsonResult
          • 2.4.3 ResultVO
          • 2.4.4 UploadFileVO
        • 2.5 util工具类
          • 2.5.1 MyUtils 我的工具类
          • 2.2.11 Tag
          • 2.2.12 User
        • 2.3 enums枚举类
          • 2.3.1 ArticleCommentStatus
          • 2.3.2 ArticleStatus
          • 2.3.3 CategoryStatus
          • 2.3.4 LinkStatus
          • 2.3.5 MenuLevel
          • 2.3.6 NoticeStatus
          • 2.3.7 PageStatus
          • 2.3.8 Role
          • 2.3.9 UserRole
        • 2.4 dto数据传输对象
          • 2.4.1 ArticleParam
          • 2.4.2 JsonResult
          • 2.4.3 ResultVO
          • 2.4.4 UploadFileVO
        • 2.5 util工具类
          • 2.5.1 MyUtils 我的工具类

目录基础结构

在这里插入图片描述

一、分析pom.xml文件和web.xml文件

1. pox.xml

<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/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.liuyanzhao</groupId><artifactId>ForestBlog</artifactId><packaging>war</packaging><version>1.0.0-SNAPSHOT</version><name>ForestBlog Maven Webapp</name><url>http://maven.apache.org</url><properties><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><spring.version>4.3.19.RELEASE</spring.version><jackson-databind-version>2.10.1</jackson-databind-version></properties><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.22</version></dependency><!-- 添加sevlet支持 --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><!-- 添加jsp支持 --><dependency><groupId>javax.servlet.jsp</groupId><artifactId>javax.servlet.jsp-api</artifactId><version>2.3.1</version></dependency><!-- 添加jstl支持 --><dependency><groupId>javax.servlet</groupId><artifactId>jstl</artifactId><version>1.1.2</version></dependency><dependency><groupId>taglibs</groupId><artifactId>standard</artifactId><version>1.1.2</version></dependency><!-- 添加spring支持 --><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>${spring.version}</version></dependency><!--spring test支持--><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${spring.version}</version></dependency><!--spring mvc支持--><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><!--spring 事务管理支持--><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>${spring.version}</version></dependency><!--spring jdbc操作支持--><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version></dependency><!--spring aop编程支持--><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>${spring.version}</version></dependency><!-- 添加mybatis支持 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.0</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>1.3.0</version></dependency><!--  jdbc驱动包 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.11</version></dependency><!-- 添加阿里巴巴连接池Druid支持 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.0.16</version></dependency><!-- 添加logback日志 --><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.1.2</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-core</artifactId><version>1.1.2</version></dependency><dependency><groupId>org.logback-extensions</groupId><artifactId>logback-ext-spring</artifactId><version>0.1.1</version></dependency><!-- 添加junit支持 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.3</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.4</version></dependency><!-- jackson --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.8</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.9.8</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>2.9.0</version></dependency><dependency><groupId>org.json</groupId><artifactId>json</artifactId><version>20170516</version></dependency><dependency><groupId>com.googlecode.rapid-framework</groupId><artifactId>rapid-core</artifactId><version>4.0.5</version></dependency><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>26.0-jre</version></dependency><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>4.2.1</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.72</version></dependency><!-- hutool工具包 --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>4.1.13</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>${jackson-databind-version}</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>${jackson-databind-version}</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>${jackson-databind-version}</version></dependency></dependencies><build><resources><!-- 编译之后包含xml --><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes><filtering>true</filtering></resource><!-- 编译之后包含xml和properties --><resource><directory>src/main/resources</directory><includes><include>**/*</include></includes><filtering>true</filtering></resource></resources></build>
</project>

pom.xml文件使用的依赖:

  • lombok

  • 添加sevlet支持

    • javax.servlet-api
  • 添加jsp支持

    • javax.servlet.jsp-api
  • 添加jstl支持

    • jstl
    • standard
  • 添加spring支持

    • spring-core
    • spring-beans
    • spring-context
    • spring-context-support
    • spring-web
  • spring test支持

    • spring-test
  • spring mvc支持

    • spring-webmvc
  • spring 事务管理支持

    • spring-tx
  • spring jdbc操作支持

    • spring-jdbc
  • spring aop编程支持

    • spring-aop
    • spring-aspects
  • 添加mybatis支持

    • mybatis
    • mybatis-spring
  • jdbc驱动包

    • mysql-connector-java
  • 添加阿里巴巴连接池Druid支持

    • druid
  • 添加logback日志

    • logback-classic
    • logback-core
    • logback-ext-spring
  • 添加junit支持

    • junit
  • 文件上传

    • commons-fileupload
    • commons-io
  • jackson

    • jackson-databind
    • jackson-core
    • jackson-annotations
  • rapid-framework是谷歌的一个项目,可以实现jsp网页的继承,也就是书写模板页。

    • json
    • rapid-core
  • Guava是Google的一个开源Java框架,包含许多Google 内部Java项目依赖的核心类,包括:从集合类型、不可变集合、图结构处理、并发工具、I/O、哈希、缓存等等各个方面的工具。Guava是对Java API的补充,对Java开发中常用功能进行更优雅的实现,Guava库经过高度的优化,使得编码更加轻松,代码容易理解。

    • guava
  • 添加分页插件pagehelper

    • pagehelper
    • fastjson
  • hutool工具包

    • hutool-all
  • <build>方式

    <build><resources><!-- 编译之后包含xml --><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes><filtering>true</filtering></resource><!-- 编译之后包含xml和properties --><resource><directory>src/main/resources</directory><includes><include>**/*</include></includes><filtering>true</filtering></resource></resources>
    </build>
    

2. src/main/webapp/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://java.sun.com/xml/ns/javaee" xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"><display-name>ForestBlog</display-name><!--post乱码过滤器--><!-- 配置springMVC编码过滤器 --><filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><!-- 设置过滤器中的属性值 --><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><!-- 启动过滤器 --><init-param><param-name>forceEncoding</param-name><param-value>true</param-value></init-param></filter><!-- 过滤所有请求 --><filter-mapping><filter-name>CharacterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><!--加载spring容器--><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/spring-*.xml,</param-value></context-param><!--配置监听器,来加载spring容器--><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!-- logback日志打印 --><context-param><param-name>logbackConfigLocation</param-name><param-value>classpath:logback.xml</param-value></context-param><listener><listener-class>ch.qos.logback.ext.spring.web.LogbackConfigListener</listener-class></listener><!--springmvc前端控制器 --><servlet><servlet-name>ForestBlog</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/spring-mvc.xml</param-value></init-param></servlet><servlet-mapping><servlet-name>ForestBlog</servlet-name><url-pattern>/</url-pattern></servlet-mapping><!--随时获得request--><listener><listener-class>org.springframework.web.context.request.RequestContextListener</listener-class></listener><!-- 4、使用Rest风格的URI,将页面普通的post请求转为指定的delete或者put请求 --><filter><filter-name>HiddenHttpMethodFilter</filter-name><filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class></filter><filter-mapping><filter-name>HiddenHttpMethodFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><filter><filter-name>HttpPutFormContentFilter</filter-name><filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class></filter><filter-mapping><filter-name>HttpPutFormContentFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><filter><filter-name>DruidWebStatFilter</filter-name><filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class><init-param><param-name>exclusions</param-name><param-value>*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*</param-value></init-param></filter><filter-mapping><filter-name>DruidWebStatFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list><!--去掉jsp页面的空白--><jsp-config><jsp-property-group><url-pattern>*.jsp</url-pattern><trim-directive-whitespaces>true</trim-directive-whitespaces></jsp-property-group></jsp-config></web-app>

web.xml文件的作用

  • 配置欢迎页面

  • 配置springMVC编码过滤器

  • 加载spring容器

  • 配置监听器,来加载spring容器

  • 配置logback日志打印

  • springmvc前端控制器

  • 配置监听器,随时获得request

  • 使用Rest风格的URI,将页面普通的post请求转为指定的delete或者put请求

  • 配置WebStatFilter用于采集web-jdbc关联监控的数据。

  • 去掉jsp页面的空白

二、分析main文件夹下文件

1. 分析resources文件夹

1.1 文件夹结构

│ db.properties
│ logback.xml

├─mapper
│ ArticleCategoryRefMapper.xml
│ ArticleMapper.xml
│ ArticleTagRefMapper.xml
│ CategoryMapper.xml
│ CommentMapper.xml
│ LinkMapper.xml
│ MenuMapper.xml
│ NoticeMapper.xml
│ OptionsMapper.xml
│ PageMapper.xml
│ TagMapper.xml
│ UserMapper.xml

├─mybatis
│ mybatis-config.xml

└─spring
spring-mvc.xml
spring-mybatis.xml

mapper 文件夹暂不分析,等分析具体映射时再一起分析

1.2 db.properties
  • 此文件为数据库连接配置文件

    #MySQL
    mysql.driver=com.mysql.cj.jdbc.Driver
    mysql.url=jdbc:mysql://localhost:3306/forest_blog?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
    mysql.username=root
    mysql.password=123
    
1.3 logback.xml
  • 此文件为logback日志配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration><!-- 尽量别用绝对路径,如果带参数不同容器路径解释可能不同,以下配置参数在pom.xml里 --><property name="log.root.level" value="INFO"/> <!-- 日志级别 --><property name="log.other.level" value="ERROR"/> <!-- 其他日志级别 --><property name="log.base" value="logs"/> <!-- 日志路径,这里是相对路径,默认会输出到tomcat/bin目录 下 --><property name="log.moduleName" value="ForestBlog"/>  <!-- 模块名称, 影响日志配置名,日志文件名 --><property name="log.max.size" value="20MB"/> <!-- 日志文件大小 --><!--控制台输出 --><appender name="stdout" class="ch.qos.logback.core.ConsoleAppender"><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><Pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread]%logger{56}.%method:%L -%msg%n</Pattern></encoder></appender><!-- 日志文件输出 --><appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender"><File>${log.base}/${log.moduleName}.log</File><!-- 设置日志不超过${log.max.size}时的保存路径,注意如果 是web项目会保存到Tomcat的bin目录 下 --><!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件。--><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><FileNamePattern>${log.base}/archive/${log.moduleName}_all_%d{yyyy-MM-dd}.%i.log.zip</FileNamePattern><!-- 当天的日志大小 超过${log.max.size}时,压缩日志并保存 --><timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>${log.max.size}</maxFileSize></timeBasedFileNamingAndTriggeringPolicy></rollingPolicy><!-- 日志输出的文件的格式  --><layout class="ch.qos.logback.classic.PatternLayout"><pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread]%logger{56}.%method:%L -%msg%n</pattern></layout></appender>
    </configuration>
    
1.4 mybatis/mybatis-config.xml
  • 此文件为mybatis配置文件

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration><!-- 全局配置 --><settings><!--允许 JDBC 支持自动生成主键--><setting name="useGeneratedKeys" value="false"/><!--是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典Java 属性名 aColumn 的类似映射。 --><setting name="mapUnderscoreToCamelCase" value="true"/><!-- 打印查询语句 -->
    <!--        <setting name="logImpl" value="STDOUT_LOGGING" />--></settings><!-- 注册分页插件PageHelper --><plugins><plugin interceptor="com.github.pagehelper.PageHelper"><!--<property name="dialect" value="mysql"/>--><property name="offsetAsPageNum" value="false"/><property name="rowBoundsWithCount" value="false"/><property name="pageSizeZero" value="true"/><property name="reasonable" value="true"/><property name="supportMethodsArguments" value="false"/><property name="returnPageInfo" value="none"/></plugin></plugins></configuration>
    
  • 主要任务

    • 允许 JDBC 支持自动生成主键
    • 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典Java 属性名 aColumn 的类似映射。
    • 注册分页插件PageHelper
1.5 spring文件夹
1.5.1 spring-mvc.xml
  • springmvc配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.2.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc-4.2.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.2.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><context:component-scan base-package="com.liuyanzhao.ssm.blog"/><!-- 一个配置节解决映射器和适配器的配置注解配置 --><mvc:annotation-driven></mvc:annotation-driven><!-- 配置视图解析器进行jsp解析,默认使用jstl标签,classpath下得有jstl的包--><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><!--配置前缀和后缀,也可以不指定--><property name="prefix" value="/WEB-INF/view/"/><property name="suffix" value=".jsp"/></bean><!--&lt;!&ndash;文件上传&ndash;&gt;--><bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><!--设置上传最大尺寸为50MB--><property name="maxUploadSizePerFile" value="52428800"/><property name="defaultEncoding" value="UTF-8"/><property name="resolveLazily" value="true"/></bean><!-- 静态资源映射 --><mvc:resources mapping="/css/**" location="/resource/assets/css/"></mvc:resources><mvc:resources mapping="/js/**" location="/resource/assets/js/"></mvc:resources><mvc:resources mapping="/img/**" location="/resource/assets/img/"></mvc:resources><mvc:resources mapping="/plugin/**" location="/resource/assets/plugin/"></mvc:resources><mvc:interceptors><mvc:interceptor><mvc:mapping path="/**"/><bean class="com.liuyanzhao.ssm.blog.util.interceptor.HomeResourceInterceptor"/></mvc:interceptor><mvc:interceptor><mvc:mapping path="/admin"/><bean class="com.liuyanzhao.ssm.blog.util.interceptor.LoginInterceptor"/></mvc:interceptor><mvc:interceptor><mvc:mapping path="/admin/**"/><bean class="com.liuyanzhao.ssm.blog.util.interceptor.LoginInterceptor"/></mvc:interceptor><mvc:interceptor><mvc:mapping path="/admin/page"/><bean class="com.liuyanzhao.ssm.blog.util.interceptor.AdminInterceptor"/></mvc:interceptor><mvc:interceptor><mvc:mapping path="/admin/page/**"/><bean class="com.liuyanzhao.ssm.blog.util.interceptor.AdminInterceptor"/></mvc:interceptor><mvc:interceptor><mvc:mapping path="/admin/tag"/><bean class="com.liuyanzhao.ssm.blog.util.interceptor.AdminInterceptor"/></mvc:interceptor><mvc:interceptor><mvc:mapping path="/admin/tag/**"/><bean class="com.liuyanzhao.ssm.blog.util.interceptor.AdminInterceptor"/></mvc:interceptor><mvc:interceptor><mvc:mapping path="/admin/category"/><bean class="com.liuyanzhao.ssm.blog.util.interceptor.AdminInterceptor"/></mvc:interceptor><mvc:interceptor><mvc:mapping path="/admin/category/**"/><bean class="com.liuyanzhao.ssm.blog.util.interceptor.AdminInterceptor"/></mvc:interceptor><mvc:interceptor><mvc:mapping path="/admin/user"/><bean class="com.liuyanzhao.ssm.blog.util.interceptor.AdminInterceptor"/></mvc:interceptor><mvc:interceptor><mvc:mapping path="/admin/user/**"/><bean class="com.liuyanzhao.ssm.blog.util.interceptor.AdminInterceptor"/></mvc:interceptor><mvc:interceptor><mvc:mapping path="/admin/menu"/><bean class="com.liuyanzhao.ssm.blog.util.interceptor.AdminInterceptor"/></mvc:interceptor><mvc:interceptor><mvc:mapping path="/admin/menu/**"/><bean class="com.liuyanzhao.ssm.blog.util.interceptor.AdminInterceptor"/></mvc:interceptor><mvc:interceptor><mvc:mapping path="/admin/options"/><bean class="com.liuyanzhao.ssm.blog.util.interceptor.AdminInterceptor"/></mvc:interceptor><mvc:interceptor><mvc:mapping path="/admin/options/**"/><bean class="com.liuyanzhao.ssm.blog.util.interceptor.AdminInterceptor"/></mvc:interceptor><mvc:interceptor><mvc:mapping path="/admin/link"/><bean class="com.liuyanzhao.ssm.blog.util.interceptor.AdminInterceptor"/></mvc:interceptor><mvc:interceptor><mvc:mapping path="/admin/link/**"/><bean class="com.liuyanzhao.ssm.blog.util.interceptor.AdminInterceptor"/></mvc:interceptor></mvc:interceptors>
    </beans>
  • 主要任务

    • 配置包扫描器对动态java文件进行扫描实例化
    • 配置视图解析器进行jsp解析,默认使用jstl标签,classpath下得有jstl的包
    • 配置文件上传限制
    • 对静态资源进行映射
    • 注册拦截器
1.5.2 spring-mybatis.xml
  • spring与mybatis的配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><!--加载db.properties--><context:property-placeholder location="classpath:db.properties"/><!--配置druid连接池--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"><!-- 基本属性 url、user、password --><property name="driverClassName" value="${mysql.driver}" /><property name="url" value="${mysql.url}" /><property name="username" value="${mysql.username}" /><property name="password" value="${mysql.password}" /><!-- 配置初始化大小、最小、最大 --><property name="initialSize" value="1" /><property name="minIdle" value="1" /><property name="maxActive" value="20" /><!-- 配置获取连接等待超时的时间,单位是毫秒 --><property name="maxWait" value="60000" /><!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --><property name="timeBetweenEvictionRunsMillis" value="60000" /><!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --><property name="minEvictableIdleTimeMillis" value="300000" /><property name="validationQuery" value="SELECT 'x'" /><property name="testWhileIdle" value="true" /><property name="testOnBorrow" value="false" /><property name="testOnReturn" value="false" /><!-- 打开PSCache,并且指定每个连接上PSCache的大小 --><property name="poolPreparedStatements" value="true" /><property name="maxPoolPreparedStatementPerConnectionSize" value="20" /><!-- 配置监控统计拦截的filters,去掉后监控界面sql无法统计 --><property name="filters" value="stat" /></bean><!--  mybatis核心配置  --><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><!--数据库连接池--><property name="dataSource" ref="dataSource"/><!--加载mybatis全局配置文件--><property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/><!--mapper.xml所在位置--><property name="mapperLocations" value="classpath*:mapper/*Mapper.xml" /><!--指定需要使用别名的PO类所在的包--><property name="typeAliasesPackage" value="com.liuyanzhao.ssm.blog.entity" /></bean><!--mapper扫描器--><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><!--如果需要扫描多个包,中间使用半角逗号隔开--><property name="basePackage" value="com.liuyanzhao.ssm.blog.mapper"></property><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/></bean><!-- 对mybatis操作数据事务控制,spring使用jdbc的事务控制类 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!-- 数据源dataSource在spring-mybatis.xml中配置了 --><property name="dataSource" ref="dataSource"/></bean><!-- 通知 --><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="save*" propagation="REQUIRED"/><tx:method name="delete*" propagation="REQUIRED"/><tx:method name="update*" propagation="REQUIRED"/><tx:method name="insert*" propagation="REQUIRED"/><tx:method name="find*" propagation="SUPPORTS" read-only="true"/><tx:method name="get*" propagation="SUPPORTS" read-only="true"/><tx:method name="select*" propagation="SUPPORTS" read-only="true"/></tx:attributes></tx:advice><aop:config><aop:advisor advice-ref="txAdvice" pointcut="execution(* com.liuyanzhao.ssm.blog.service.impl.*.*(..))"/></aop:config>
    </beans>
    
  • 主要任务

    • 加载db.properties数据库信息配置文件
    • 配置druid连接池信息
      • 基本属性 url、user、password
      • 配置初始化大小、最小、最大
      • 配置获取连接等待超时的时间
      • 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
      • 配置一个连接在池中最小生存的时间,单位是毫秒
      • 打开PSCache,并且指定每个连接上PSCache的大小
      • 配置监控统计拦截的filters,去掉后监控界面sql无法统计
    • mybatis核心配置
      • 数据库连接池
      • 加载mybatis全局配置文件
      • mapper.xml所在位置
      • 指定需要使用别名的PO类所在的包
    • mapper扫描器
      • 如果需要扫描多个包,中间使用半角逗号隔开
    • 对mybatis操作数据事务控制,spring使用jdbc的事务控制类
      • 数据源dataSource在spring-mybatis.xml中配置了
    • 定义通知advice
    • 配置切面

2. 分析java文件夹

2.1 文件夹结构

└─com
└─liuyanzhao
└─ssm
└─blog
├─controller
│ ├─admin
│ │ AdminController.java
│ │ BackArticleController.java
│ │ BackCategoryController.java
│ │ BackCommentController.java
│ │ BackLinkController.java
│ │ BackMenuController.java
│ │ BackNoticeController.java
│ │ BackOptionsController.java
│ │ BackPageController.java
│ │ BackTagController.java
│ │ BackUserController.java
│ │ UploadFileController.java
│ │
│ └─home
│ ArticleController.java
│ CategoryController.java
│ CommentController.java
│ IndexController.java
│ LinkController.java
│ NoticeController.java
│ PageController.java
│ TagController.java

├─dto
│ ArticleParam.java
│ JsonResult.java
│ ResultVO.java
│ UploadFileVO.java

├─entity
│ Article.java
│ ArticleCategoryRef.java
│ ArticleTagRef.java
│ Category.java
│ Comment.java
│ Link.java
│ Menu.java
│ Notice.java
│ Options.java
│ Page.java
│ Tag.java
│ User.java

├─enums
│ ArticleCommentStatus.java
│ ArticleStatus.java
│ CategoryStatus.java
│ LinkStatus.java
│ MenuLevel.java
│ NoticeStatus.java
│ PageStatus.java
│ Role.java
│ UserRole.java

├─mapper
│ ArticleCategoryRefMapper.java
│ ArticleMapper.java
│ ArticleTagRefMapper.java
│ CategoryMapper.java
│ CommentMapper.java
│ LinkMapper.java
│ MenuMapper.java
│ NoticeMapper.java
│ OptionsMapper.java
│ PageMapper.java
│ TagMapper.java
│ UserMapper.java

├─service
│ │ ArticleService.java
│ │ CategoryService.java
│ │ CommentService.java
│ │ LinkService.java
│ │ MenuService.java
│ │ NoticeService.java
│ │ OptionsService.java
│ │ PageService.java
│ │ TagService.java
│ │ UserService.java
│ │
│ └─impl
│ ArticleServiceImpl.java
│ CategoryServiceImpl.java
│ CommentServiceImpl.java
│ LinkServiceImpl.java
│ MenuServiceImpl.java
│ NoticeServiceImpl.java
│ OptionsServiceImpl.java
│ PageServiceImpl.java
│ TagServiceImpl.java
│ UserServiceImpl.java

└─util
│ MyUtils.java

└─interceptor
AdminInterceptor.java
HomeResourceInterceptor.java
LoginInterceptor.java

由于包名为com.liuyanzhao.ssm.blog,其余文件都在该目录下进行分类,因此以下分析默认在此目录下进行。

2.2 entity实体类
2.2.0 实例关系分析
  • 实体基础需求

    • 文章(文章ID,用户ID,文章标题,文章访问量,文章评论数,文章点赞数,文章创建时间,文章更新时间,文章能否评论,文章状态,文章排序值,文章内容,文章摘要,文章缩略图)
    • 分类(分类ID,父亲ID,分类名称,分类描述,分类排序值,分类图标)
    • 标签(标签ID,标签名称,标签描述)
    • 用户(用户ID,用户名,密码,用户昵称,用户邮箱,用户主页url,用户头像,用户上次登录IP,用户注册时间,用户上次登录时间,用户状态,用户角色)
    • 评论(评论ID,上级评论人ID,上级评论人名称,评论文章ID,评论人昵称,评论人email,评论人主页url,评论人头像,评论内容,评论浏览器信息,评论IP,评论时间,评论角色,评论用户ID)

    ------------------------下方为管理员管理内容-------------------------------

    • 链接(链接ID,链接url,链接名称,链接头像,链接描述,链接所属人昵称,链接所属人联系方式,链接创建时间,链接更新时间,链接排序值,链接状态)
    • 菜单(菜单ID,菜单名称,菜单url,菜单等级,菜单图标,菜单排序值)
    • 公告(公告ID,公告标题,公告内容,公告创建时间,公告更新时间,公告状态,公告排序值)
    • 基本信息(基本信息ID,站点标题,站点描述,媒体描述,媒体关键字,相关站点头像,相关站点标题,相关站点内容,相关站点微信,相关站点QQ,相关站点GitHub,相关站点微博,基本信息统计,基本信息状态)
    • 页面(页面ID,页面别称key,页面标题,页面内容,页面创建时间,页面更新时间,页面访问量,页面评论数,页面状态)
  • 关系模式

    • 文章:分类 = m:n
    • 文章:标签 = m:n
    • 文章:用户 = n:1
    • 文章:评论 = 1:n
    • 父分类:子分类 = 1:1
    • 用户:评论 = 1:n
    • 父评论:子评论 = 1:1
  • 加入关系模式后的实体类设计

    • 文章(文章ID,文章标题,文章访问量,文章评论数,文章点赞数,文章创建时间,文章更新时间,文章能否评论,文章状态,文章排序值,文章内容,文章摘要,文章缩略图,用户ID)
      • PK:文章ID,用户ID
      • FK:用户ID
    • 分类(分类ID,父亲分类ID,分类名称,分类描述,分类排序值,分类图标)
      • PK:分类ID,父亲分类ID
      • FK:父亲分类ID
    • 标签(标签ID,标签名称,标签描述)
      • PK:标签ID
      • FK:
    • 用户(用户ID,用户名,密码,用户昵称,用户邮箱,用户主页url,用户头像,用户上次登录IP,用户注册时间,用户上次登录时间,用户状态,用户角色)
      • PK:用户ID
      • FK:
    • 评论(评论ID,评论人昵称,评论人email,评论人主页url,评论人头像,评论内容,评论浏览器信息,评论IP,评论时间,评论角色,上级评论人ID,上级评论人名称,评论文章ID,评论用户ID)
      • PK:评论ID,评论文章ID,上级评论人ID,评论用户ID
      • FK:评论文章ID,上级评论人ID,评论用户ID
    • 文章与分类关系(文章ID,分类ID)
      • PK:文章ID,分类ID
      • FK:文章ID,分类ID
    • 文章与标签关系(文章ID,标签ID)
      • PK:文章ID,标签ID
      • FK:文章ID,标签ID

    ------------------------下方为管理员管理内容-------------------------------

    • 链接(链接ID,链接url,链接名称,链接头像,链接描述,链接所属人昵称,链接所属人联系方式,链接创建时间,链接更新时间,链接排序值,链接状态)
      • PK:链接ID
      • FK:
    • 菜单(菜单ID,菜单名称,菜单url,菜单等级,菜单图标,菜单排序值)
      • PK:菜单ID
      • FK:
    • 公告(公告ID,公告标题,公告内容,公告创建时间,公告更新时间,公告状态,公告排序值)
      • PK:公告ID
      • FK:
    • 基本信息(基本信息ID,站点标题,站点描述,媒体描述,媒体关键字,相关站点头像,相关站点标题,相关站点内容,相关站点微信,相关站点QQ,相关站点GitHub,相关站点微博,基本信息统计,基本信息状态)
      • PK:基本信息ID
      • FK:
    • 页面(页面ID,页面别称key,页面标题,页面内容,页面创建时间,页面更新时间,页面访问量,页面评论数,页面状态)
      • PK:页面ID
      • FK:
  • 为增加查询效率,增加冗余,最终实体类设计

    • 文章(文章ID,文章标题,文章访问量,文章评论数,文章点赞数,文章创建时间,文章更新时间,文章能否评论,文章状态,文章排序值,文章内容,文章摘要,文章缩略图,用户ID,用户,标签列表,分类列表)
      • PK:文章ID,用户ID
      • FK:用户ID
      • 冗余属性:用户,标签列表,分类列表
    • 分类(分类ID,父亲分类ID,分类名称,分类描述,分类排序值,分类图标,该分类下的文章数量)
      • PK:分类ID,父亲分类ID
      • FK:父亲分类ID
      • 冗余属性:该分类下的文章总数
    • 标签(标签ID,标签名称,标签描述,该标签下的文章数量)
      • PK:标签ID
      • FK:
      • 冗余属性:该标签下的文章总数
    • 用户(用户ID,用户名,密码,用户昵称,用户邮箱,用户主页url,用户头像,用户上次登录IP,用户注册时间,用户上次登录时间,用户状态,用户角色,该用户写的文章数量)
      • PK:用户ID
      • FK:
      • 冗余属性:该用户写的文章数量
    • 评论(评论ID,评论人昵称,评论人email,评论人主页url,评论人头像,评论内容,评论浏览器信息,评论IP,评论时间,评论角色,上级评论人ID,上级评论人名称,评论文章ID,评论用户ID,文章)
      • PK:评论ID,评论文章ID,上级评论人ID,评论用户ID
      • FK:评论文章ID,上级评论人ID,评论用户ID
      • 冗余属性:文章
    • 文章与分类关系(文章ID,分类ID)
      • PK:文章ID,分类ID
      • FK:文章ID,分类ID
    • 文章与标签关系(文章ID,标签ID)
      • PK:文章ID,标签ID
      • FK:文章ID,标签ID

    ------------------------下方为管理员管理内容-------------------------------

    • 链接(链接ID,链接url,链接名称,链接头像,链接描述,链接所属人昵称,链接所属人联系方式,链接创建时间,链接更新时间,链接排序值,链接状态)
      • PK:链接ID
      • FK:
    • 菜单(菜单ID,菜单名称,菜单url,菜单等级,菜单图标,菜单排序值)
      • PK:菜单ID
      • FK:
    • 公告(公告ID,公告标题,公告内容,公告创建时间,公告更新时间,公告状态,公告排序值)
      • PK:公告ID
      • FK:
    • 基本信息(基本信息ID,站点标题,站点描述,媒体描述,媒体关键字,相关站点头像,相关站点标题,相关站点内容,相关站点微信,相关站点QQ,相关站点GitHub,相关站点微博,基本信息统计,基本信息状态)
      • PK:基本信息ID
      • FK:
    • 页面(页面ID,页面别称key,页面标题,页面内容,页面创建时间,页面更新时间,页面访问量,页面评论数,页面状态)
      • PK:页面ID
      • FK:

├─entity
│ Article.java
│ ArticleCategoryRef.java
│ ArticleTagRef.java
│ Category.java
│ Comment.java
│ Link.java
│ Menu.java
│ Notice.java
│ Options.java
│ Page.java
│ Tag.java
│ User.java

  • 该目录下的实体类均采用@Data注解,简化代码。

  • @Data 的用途是:注在类上,提供类的get、set、equals、hashCode、toString等方法。

  • 使用该注解需要引入lombok依赖,idea中需要引入lombok相关插件。

    <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.22</version>
    </dependency>
    

    在这里插入图片描述

2.2.1 Article
  1. com.liuyanzhao.ssm.blog.entity.Article

    package com.liuyanzhao.ssm.blog.entity;import lombok.Data;import java.io.Serializable;
    import java.util.Date;
    import java.util.List;/*** @author liuyanzhao*/
    @Data
    public class Article implements Serializable{private static final long serialVersionUID = 5207865247400761539L;// 文章IDprivate Integer articleId;// 文章用户IDprivate Integer articleUserId;// 文章标题private String articleTitle;// 文章访问量private Integer articleViewCount;// 文章评论数private Integer articleCommentCount;// 文章点赞数private Integer articleLikeCount;// 文章创建时间private Date articleCreateTime;// 文章更新时间private Date articleUpdateTime;// 文章是否允许评论private Integer articleIsComment;// 文章状态private Integer articleStatus;// 文章排序值private Integer articleOrder;// 文章内容private String articleContent;// 文章摘要private String articleSummary;// 文章缩略图private String articleThumbnail;private User user;private List<Tag> tagList;private List<Category> categoryList;
    }
    
    • 文章实体类

      • 增加了三个非数据库属性
        • User:用户
        • tagList:标签列表
        • categoryList:分类列表
    • 数据库设计

      在这里插入图片描述

2.2.2 ArticleCategoryRef
  1. com.liuyanzhao.ssm.blog.entity.ArticleCategoryRef

    package com.liuyanzhao.ssm.blog.entity;import lombok.Data;import java.io.Serializable;/*** 文章分类关联表** @author liuyanzhao*/
    @Data
    public class ArticleCategoryRef implements Serializable{private static final long serialVersionUID = -6809206515467725995L;// 文章IDprivate Integer articleId;// 分类IDprivate Integer categoryId;public ArticleCategoryRef() {}public ArticleCategoryRef(Integer articleId, Integer categoryId) {this.articleId = articleId;this.categoryId = categoryId;}
    }
    
    • 文章分类关联表实体类

    • 数据库设计

      在这里插入图片描述

2.2.3 ArticleTagRef
  1. com.liuyanzhao.ssm.blog.entity.ArticleTagRef

    package com.liuyanzhao.ssm.blog.entity;import lombok.Data;import java.io.Serializable;/*** 文章和标签关联** @author 言曌* @date 2018/11/17 下午5:20*/
    @Data
    public class ArticleTagRef implements Serializable {private static final long serialVersionUID = -5816783232020910492L;// 文章IDprivate Integer articleId;// 标签IDprivate Integer tagId;public ArticleTagRef() {}public ArticleTagRef(Integer articleId, Integer tagId) {this.articleId = articleId;this.tagId = tagId;}
    }
    
    • 文章和标签关联实体类

    • 数据库设计

      在这里插入图片描述

2.2.4 Category
  1. com.liuyanzhao.ssm.blog.entity.Category

    package com.liuyanzhao.ssm.blog.entity;import lombok.Data;import java.io.Serializable;/*** @author liuyanzhao*/
    @Data
    public class Category implements Serializable {private static final long serialVersionUID = 6687286913317513141L;// 分类IDprivate Integer categoryId;// 分类父IDprivate Integer categoryPid;// 分类名称private String categoryName;// 分类描述private String categoryDescription;// 分类排序值private Integer categoryOrder;// 分类图标private String categoryIcon;/*** 文章数量(非数据库字段)*/private Integer articleCount;public Category(Integer categoryId, Integer categoryPid, String categoryName, String categoryDescription, Integer categoryOrder, String categoryIcon,Integer articleCount) {this.categoryId = categoryId;this.categoryPid = categoryPid;this.categoryName = categoryName;this.categoryDescription = categoryDescription;this.categoryOrder = categoryOrder;this.categoryIcon = categoryIcon;this.articleCount = articleCount;}public Category(Integer categoryId, String categoryName) {this.categoryId = categoryId;this.categoryName = categoryName;}public Category(Integer categoryId) {this.categoryId = categoryId;}public Category() {}/*** 未分类** @return 分类*/public static Category Default() {return new Category(100000000, "未分类");}
    }
    
    • 分类实体类

      • 增加了一个非数据库属性
        • articleCount:该分类下的文章数量
      • 设计了构造方法,包括:
        • 仅有分类ID
        • 有分类ID、分类名称
        • 全参
      • 设置了一个静态方法:Default(),用于返回一个固定内容的未分类对象
    • 数据库设计

      在这里插入图片描述

2.2.5 Comment
  1. com.liuyanzhao.ssm.blog.entity.Comment

    package com.liuyanzhao.ssm.blog.entity;import lombok.Data;import java.io.Serializable;
    import java.util.Date;/*** 文章评论** @author liuyanzhao*/
    @Data
    public class Comment implements Serializable {private static final long serialVersionUID = -1038897351672911219L;// 评论IDprivate Integer commentId;// 上级评论IDprivate Integer commentPid;// 上级评论名称private String commentPname;// 文章IDprivate Integer commentArticleId;// 评论人名称private String commentAuthorName;// 评论人邮箱private String commentAuthorEmail;// 评论人个人主页private String commentAuthorUrl;// 评论人头像private String commentAuthorAvatar;// 内容private String commentContent;// 浏览器信息private String commentAgent;// IPprivate String commentIp;// 评论时间private Date commentCreateTime;/*** 角色(管理员1,访客0)*/private Integer commentRole;/*** 评论用户ID*/private Integer commentUserId;/*** 非数据库字段*/private Article article;
    }
    
    • 评论实体类

      • 增加了一个非数据库属性:article:文章
    • 数据库设计

      在这里插入图片描述

2.2.6 Link
  1. com.liuyanzhao.ssm.blog.entity.Link

    package com.liuyanzhao.ssm.blog.entity;import lombok.Data;import java.io.Serializable;
    import java.util.Date;/*** @author liuyanzhao*/
    @Data
    public class Link  implements Serializable{private static final long serialVersionUID = -259829372268790508L;// 链接IDprivate Integer linkId;// URLprivate String linkUrl;// 姓名private String linkName;// 头像private String linkImage;// 描述private String linkDescription;// 所属人名称private String linkOwnerNickname;// 联系方式private String linkOwnerContact;// 更新时间private Date linkUpdateTime;// 创建时间private Date linkCreateTime;// 排序号private Integer linkOrder;// 状态private Integer linkStatus;}
    
    • 连接实体类

    • 数据库设计

      在这里插入图片描述

2.2.7 Menu
  1. com.liuyanzhao.ssm.blog.entity.Menu

    package com.liuyanzhao.ssm.blog.entity;import lombok.Data;import java.io.Serializable;/*** @author liuyanzhao*/
    @Data
    public class Menu implements Serializable {private static final long serialVersionUID = 489914127235951698L;// 菜单IDprivate Integer menuId;// 名称private String menuName;// URLprivate String menuUrl;// 等级private Integer menuLevel;// 图标private String menuIcon;// 排序值private Integer menuOrder;}
    
    • 菜单实体类

    • 数据库设计

      在这里插入图片描述

2.2.8 Notice
  1. com.liuyanzhao.ssm.blog.entity.Notice

    package com.liuyanzhao.ssm.blog.entity;import lombok.Data;import java.io.Serializable;
    import java.util.Date;/*** @author liuyanzhao*/
    @Data
    public class Notice implements Serializable{private static final long serialVersionUID = -4901560494243593100L;// 公告IDprivate Integer noticeId;// 公告标题private String noticeTitle;// 内容private String noticeContent;// 创建时间private Date noticeCreateTime;// 更新时间private Date noticeUpdateTime;// 状态private Integer noticeStatus;// 排序值private Integer noticeOrder;
    }
    
    • 公告实体类

    • 数据库设计

      在这里插入图片描述

2.2.9 Options
  1. com.liuyanzhao.ssm.blog.entity.Options

    package com.liuyanzhao.ssm.blog.entity;import lombok.Data;import java.io.Serializable;/*** @author liuyanzhao*/
    @Data
    public class Options implements Serializable{private static final long serialVersionUID = -776792869602511933L;// private Integer optionId;// private String optionSiteTitle;// private String optionSiteDescrption;// private String optionMetaDescrption;// private String optionMetaKeyword;// private String optionAboutsiteAvatar;// private String optionAboutsiteTitle;// private String optionAboutsiteContent;// private String optionAboutsiteWechat;// private String optionAboutsiteQq;// private String optionAboutsiteGithub;// private String optionAboutsiteWeibo;// private String optionTongji;// private Integer optionStatus;}
    
    • 系统设置实体类

    • 数据库设计

      在这里插入图片描述

2.2.10 Page
  1. com.liuyanzhao.ssm.blog.entity.Page

    package com.liuyanzhao.ssm.blog.entity;import lombok.Data;import java.io.Serializable;
    import java.util.Date;/*** @author liuyanzhao*/
    @Data
    public class Page implements Serializable{private static final long serialVersionUID = 3927496662110298634L;// 自定义页面IDprivate Integer pageId;// keyprivate String pageKey;// 标题private String pageTitle;// 内容private String pageContent;// 创建时间private Date pageCreateTime;// 更新时间private Date pageUpdateTime;// 访问量private Integer pageViewCount;// 评论数private Integer pageCommentCount;// 状态private Integer pageStatus;}
    
    • 页面实体类

    • 数据库设计

      在这里插入图片描述

2.2.11 Tag
  1. com.liuyanzhao.ssm.blog.entity.Tag

    package com.liuyanzhao.ssm.blog.entity;import lombok.Data;import java.io.Serializable;/*** @author liuyanzhao*/
    @Data
    public class Tag implements Serializable{private static final long serialVersionUID = 605449151900057035L;// 标签IDprivate Integer tagId;// 标签名称private String tagName;// 描述private String tagDescription;/*** 文章数量(不是数据库字段)*/private Integer articleCount;public Tag() {}public Tag(Integer tagId) {this.tagId = tagId;}public Tag(Integer tagId, String tagName, String tagDescription, Integer articleCount) {this.tagId = tagId;this.tagName = tagName;this.tagDescription = tagDescription;this.articleCount = articleCount;}
    }
    
    • 标签实体类

      • 增加了一个非数据库属性:articleCount:文章数量总计
      • 增加了三个构造方法
        • 无参
        • 单一标签ID
        • 全参
    • 数据库设计

      在这里插入图片描述

2.2.12 User
  1. com.liuyanzhao.ssm.blog.entity.User

    package com.liuyanzhao.ssm.blog.entity;import lombok.Data;import java.io.Serializable;
    import java.util.Date;/*** @author liuyanzhao*/
    @Data
    public class User implements Serializable{private static final long serialVersionUID = -4415517704211731385L;// 用户IDprivate Integer userId;// 用户名private String userName;// 密码private String userPass;// 昵称private String userNickname;// 邮箱private String userEmail;// 个人主页private String userUrl;// 头像private String userAvatar;// 上次登录IPprivate String userLastLoginIp;// 注册时间private Date userRegisterTime;// 上次登录时间private Date userLastLoginTime;// 状态private Integer userStatus;/*** 用户角色:admin/user*/private String userRole;/*** 文章数量(不是数据库字段)*/private Integer articleCount;}
    
    • 用户实体类

      • 增加一个非数据库属性:articleCount:发布文章总数
    • 数据库设计

      在这里插入图片描述

2.3 enums枚举类

├─enums
│ ArticleCommentStatus.java
│ ArticleStatus.java
│ CategoryStatus.java
│ LinkStatus.java
│ MenuLevel.java
│ NoticeStatus.java
│ PageStatus.java
│ Role.java
│ UserRole.java

2.3.1 ArticleCommentStatus
  1. com.liuyanzhao.ssm.blog.enums.ArticleCommentStatus

    package com.liuyanzhao.ssm.blog.enums;/*** @author 言曌* @date 2018/11/17 下午4:47*/public enum ArticleCommentStatus {ALLOW(1, "允许"),NOT_ALLOW(0, "不允许");private Integer value;private String message;ArticleCommentStatus(Integer value, String message) {this.value = value;this.message = message;}public Integer getValue() {return value;}public void setValue(Integer value) {this.value = value;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
    }
    
    • 文章是否允许评论
      • 1:允许
      • 0:不允许
2.3.2 ArticleStatus
  1. com.liuyanzhao.ssm.blog.enums.ArticleStatus

    package com.liuyanzhao.ssm.blog.enums;/*** @author 言曌* @date 2018/11/17 下午4:47*/public enum ArticleStatus {PUBLISH(1, "已发布"),DRAFT(0, "草稿");private Integer value;private String message;ArticleStatus(Integer value, String message) {this.value = value;this.message = message;}public Integer getValue() {return value;}public void setValue(Integer value) {this.value = value;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
    }
    
    • 文章状态
      • 1:已发布
      • 0:草稿
2.3.3 CategoryStatus
  1. com.liuyanzhao.ssm.blog.enums.CategoryStatus

    package com.liuyanzhao.ssm.blog.enums;import lombok.Data;/*** @author 言曌* @date 2018/11/17 下午4:47*/public enum CategoryStatus {NORMAL(1, "正常"),HIDDEN(0, "隐藏");private Integer value;private String message;CategoryStatus(Integer value, String message) {this.value = value;this.message = message;}public Integer getValue() {return value;}public void setValue(Integer value) {this.value = value;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
    }
    
    • 分类状态
      • 1:正常
      • 0:隐藏
2.3.4 LinkStatus
  1. com.liuyanzhao.ssm.blog.enums.LinkStatus

    package com.liuyanzhao.ssm.blog.enums;/*** @author 言曌* @date 2018/11/17 下午4:47*/public enum LinkStatus {NORMAL(1, "显示"),HIDDEN(0, "隐藏");private Integer value;private String message;LinkStatus(Integer value, String message) {this.value = value;this.message = message;}public Integer getValue() {return value;}public void setValue(Integer value) {this.value = value;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
    }
    
    • 链接状态
      • 1:显示
      • 0:隐藏
2.3.5 MenuLevel
  1. com.liuyanzhao.ssm.blog.enums.MenuLevel

    package com.liuyanzhao.ssm.blog.enums;/*** @author 言曌* @date 2018/11/17 下午4:47*/public enum MenuLevel {TOP_MENU(1, "顶部菜单"),MAIN_MENU(2, "主体菜单");private Integer value;private String message;MenuLevel(Integer value, String message) {this.value = value;this.message = message;}public Integer getValue() {return value;}public void setValue(Integer value) {this.value = value;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
    }
    
    • 菜单等级
      • 1:顶部菜单
      • 2:主体菜单
2.3.6 NoticeStatus
  1. com.liuyanzhao.ssm.blog.enums.NoticeStatus

    package com.liuyanzhao.ssm.blog.enums;/*** @author 言曌* @date 2018/11/17 下午4:47*/public enum NoticeStatus {NORMAL(1, "显示"),HIDDEN(0, "隐藏");private Integer value;private String message;NoticeStatus(Integer value, String message) {this.value = value;this.message = message;}public Integer getValue() {return value;}public void setValue(Integer value) {this.value = value;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
    }
    
    • 通知状态
      • 1:显示
      • 0:隐藏
2.3.7 PageStatus
  1. com.liuyanzhao.ssm.blog.enums.PageStatus

    package com.liuyanzhao.ssm.blog.enums;/*** @author 言曌* @date 2018/11/17 下午4:47*/public enum PageStatus {NORMAL(1, "显示"),HIDDEN(0, "隐藏");private Integer value;private String message;PageStatus(Integer value, String message) {this.value = value;this.message = message;}public Integer getValue() {return value;}public void setValue(Integer value) {this.value = value;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
    }
    
    • 页面状态
      • 1:显示
      • 0:隐藏
2.3.8 Role
  1. com.liuyanzhao.ssm.blog.enums.Role

    package com.liuyanzhao.ssm.blog.enums;/*** @author 言曌* @date 2018/11/17 下午4:47*/public enum Role {OWNER(1, "博主"),VISITOR(0, "其他用户");private Integer value;private String message;Role(Integer value, String message) {this.value = value;this.message = message;}public Integer getValue() {return value;}public void setValue(Integer value) {this.value = value;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
    }
    
    • 浏览角色
      • 1:博主
      • 0:其他用户
2.3.9 UserRole
  1. com.liuyanzhao.ssm.blog.enums.UserRole

    package com.liuyanzhao.ssm.blog.enums;/*** 角色枚举** @author 言曌* @date 2021/2/25 2:31 下午*/public enum UserRole {ADMIN("admin", "管理员"),USER("user", "用户");private String value;private String message;UserRole(String value, String message) {this.value = value;this.message = message;}public String getValue() {return value;}public void setValue(String value) {this.value = value;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
    }
    
    • 用户角色
      • admin:管理员
      • user:用户
2.4 dto数据传输对象

├─dto
│ ArticleParam.java
│ JsonResult.java
│ ResultVO.java
│ UploadFileVO.java

2.4.1 ArticleParam
  1. com.liuyanzhao.ssm.blog.dto.ArticleParam

    package com.liuyanzhao.ssm.blog.dto;import lombok.Data;import java.util.List;/*** @author 言曌* @date 2018/11/25 下午3:56*/
    @Data
    public class ArticleParam {private Integer articleId;private String articleTitle;private String articleContent;private Integer articleParentCategoryId;private Integer articleChildCategoryId;private Integer articleOrder;private Integer articleStatus;private String articleThumbnail;private List<Integer> articleTagIds;}
    
    • 文章参数
2.4.2 JsonResult
  1. com.liuyanzhao.ssm.blog.dto.JsonResult

    package com.liuyanzhao.ssm.blog.dto;import lombok.Data;/*** @author 言曌* @date 2017/11/30 下午7:04*/@Data
    public class JsonResult<T> {/*** 错误码*/private Integer code;/*** 提示信息*/private String msg;/*** 返回的具体内容*/private T data;public JsonResult(Integer code, String msg, T data) {this.code = code;this.msg = msg;this.data = data;}public JsonResult() {}public JsonResult fail() {return new JsonResult(1, "操作失败", null);}public JsonResult fail(String msg) {return new JsonResult(1, msg, null);}public JsonResult ok() {return new JsonResult(0, "操作成功", null);}public JsonResult ok(T data) {return new JsonResult(0, "操作成功", data);}
    }
    
    • json传输结果
2.4.3 ResultVO
  1. com.liuyanzhao.ssm.blog.dto.ResultVO

    package com.liuyanzhao.ssm.blog.dto;import lombok.Data;/*** @author 言曌* @date 2017/11/30 下午7:04*/@Data
    public class ResultVO<T> {/*** 错误码*/private Integer code;/*** 提示信息*/private String msg;/*** 返回的具体内容*/private T data;public ResultVO(Integer code, String msg, T data) {this.code = code;this.msg = msg;this.data = data;}public ResultVO() {}
    }
    
    • 结果显示层对象
2.4.4 UploadFileVO
  1. com.liuyanzhao.ssm.blog.dto.UploadFileVO

    package com.liuyanzhao.ssm.blog.dto;import lombok.Data;/*** @author 言曌* @date 2017/11/30 下午7:41*/@Data
    public class UploadFileVO {private String src;private String title;}
    
    • 上传文件显示层对象
2.5 util工具类

└─util
│ MyUtils.java

└─interceptor
AdminInterceptor.java
HomeResourceInterceptor.java
LoginInterceptor.java

2.5.1 MyUtils 我的工具类
  • com.liuyanzhao.ssm.blog.util.MyUtils

    package com.liuyanzhao.ssm.blog.util;import javax.servlet.http.HttpServletRequest;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;/*** 常用的方法* Created by 言曌 on 2017/8/24.*/public class MyUtils {/*** 获得IP地址** @param request* @return*/public static String getIpAddr(HttpServletRequest request) {String ipAddress = request.getHeader("x-forwarded-for");if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("Proxy-Client-IP");}if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("WL-Proxy-Client-IP");}if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getRemoteAddr();}//对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割if (ipAddress != null && ipAddress.length() > 15) {if (ipAddress.indexOf(",") > 0) {ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));}}return ipAddress;}/*** 获得Md5加密** @param str 原字符串* @return 加密后的字符串*/public static String strToMd5(String str) {String md5Str = null;if (str != null && str.length() != 0) {try {MessageDigest md = MessageDigest.getInstance("MD5");md.update(str.getBytes());byte b[] = md.digest();int i;StringBuffer buf = new StringBuffer("");for (int offset = 0; offset < b.length; offset++) {i = b[offset];if (i < 0) {i += 256;}if (i < 16) {buf.append("0");}buf.append(Integer.toHexString(i));}//32位md5Str = buf.toString();//16位//md5Str = buf.toString().substring(8, 24);} catch (NoSuchAlgorithmException e) {e.printStackTrace();}}return md5Str;}/*** 根据email获取gravatar头像** @param email Email* @return 头像URL*/public static String getGravatar(String email) {String emailMd5 = strToMd5(email);//设置图片大小32pxString avatar = "http://cn.gravatar.com/avatar/" + emailMd5 + "?s=128&d=identicon&r=PG";return avatar;}}
    
    • getIpAddr(HttpServletRequest request)

      • 获得IP地址

        • @param request HttpServletRequest请求
        • @return IP地址
      • 源代码

        public static String getIpAddr(HttpServletRequest request) {String ipAddress = request.getHeader("x-forwarded-for");if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("Proxy-Client-IP");}if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("WL-Proxy-Client-IP");}if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getRemoteAddr();}//对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割if (ipAddress != null && ipAddress.length() > 15) {if (ipAddress.indexOf(",") > 0) {ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));}}return ipAddress;
        }
        
      • 自上而下分别从request.getHeader("x-forwarded-for");、request.getHeader("Proxy-Client-IP");request.getHeader("WL-Proxy-Client-IP");request.getRemoteAddr();获取IP地址,若未从上方获取则进入下层获取。

      • 获取完毕后,若是多个代理的情况,则取第一个IP为客户端真实IP

    • String strToMd5(String str)

      • 获得Md5加密

        • @param str 原字符串
        • @return 加密后的字符串
      • 源代码

        public static String strToMd5(String str) {String md5Str = null;if (str != null && str.length() != 0) {try {MessageDigest md = MessageDigest.getInstance("MD5");md.update(str.getBytes());byte b[] = md.digest();int i;StringBuffer buf = new StringBuffer("");for (int offset = 0; offset < b.length; offset++) {i = b[offset];if (i < 0) {i += 256;}if (i < 16) {buf.append("0");}buf.append(Integer.toHexString(i));}//32位md5Str = buf.toString();//16位//md5Str = buf.toString().substring(8, 24);} catch (NoSuchAlgorithmException e) {e.printStackTrace();}}
        
    • String getGravatar(String email)

      • 根据email获取gravatar头像

        • @param email Email
        • @return 头像URL
      • 源代码

        public static String getGravatar(String email) {String emailMd5 = strToMd5(email);//设置图片大小32pxString avatar = "http://cn.gravatar.com/avatar/" + emailMd5 + "?s=128&d=identicon&r=PG";return avatar;
        }
        
2.2.11 Tag
  1. com.liuyanzhao.ssm.blog.entity.Tag

    package com.liuyanzhao.ssm.blog.entity;import lombok.Data;import java.io.Serializable;/*** @author liuyanzhao*/
    @Data
    public class Tag implements Serializable{private static final long serialVersionUID = 605449151900057035L;// 标签IDprivate Integer tagId;// 标签名称private String tagName;// 描述private String tagDescription;/*** 文章数量(不是数据库字段)*/private Integer articleCount;public Tag() {}public Tag(Integer tagId) {this.tagId = tagId;}public Tag(Integer tagId, String tagName, String tagDescription, Integer articleCount) {this.tagId = tagId;this.tagName = tagName;this.tagDescription = tagDescription;this.articleCount = articleCount;}
    }
    
    • 标签实体类

      • 增加了一个非数据库属性:articleCount:文章数量总计
      • 增加了三个构造方法
        • 无参
        • 单一标签ID
        • 全参
    • 数据库设计

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pbeg5QkS-1675858523534)(C:\Users\ShiningSong\AppData\Roaming\Typora\typora-user-images\image-20230205151553132.png)]

2.2.12 User
  1. com.liuyanzhao.ssm.blog.entity.User

    package com.liuyanzhao.ssm.blog.entity;import lombok.Data;import java.io.Serializable;
    import java.util.Date;/*** @author liuyanzhao*/
    @Data
    public class User implements Serializable{private static final long serialVersionUID = -4415517704211731385L;// 用户IDprivate Integer userId;// 用户名private String userName;// 密码private String userPass;// 昵称private String userNickname;// 邮箱private String userEmail;// 个人主页private String userUrl;// 头像private String userAvatar;// 上次登录IPprivate String userLastLoginIp;// 注册时间private Date userRegisterTime;// 上次登录时间private Date userLastLoginTime;// 状态private Integer userStatus;/*** 用户角色:admin/user*/private String userRole;/*** 文章数量(不是数据库字段)*/private Integer articleCount;}
    
    • 用户实体类

      • 增加一个非数据库属性:articleCount:发布文章总数
    • 数据库设计

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AljMObZN-1675858523535)(C:\Users\ShiningSong\AppData\Roaming\Typora\typora-user-images\image-20230205151644431.png)]

2.3 enums枚举类

├─enums
│ ArticleCommentStatus.java
│ ArticleStatus.java
│ CategoryStatus.java
│ LinkStatus.java
│ MenuLevel.java
│ NoticeStatus.java
│ PageStatus.java
│ Role.java
│ UserRole.java

2.3.1 ArticleCommentStatus
  1. com.liuyanzhao.ssm.blog.enums.ArticleCommentStatus

    package com.liuyanzhao.ssm.blog.enums;/*** @author 言曌* @date 2018/11/17 下午4:47*/public enum ArticleCommentStatus {ALLOW(1, "允许"),NOT_ALLOW(0, "不允许");private Integer value;private String message;ArticleCommentStatus(Integer value, String message) {this.value = value;this.message = message;}public Integer getValue() {return value;}public void setValue(Integer value) {this.value = value;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
    }
    
    • 文章是否允许评论
      • 1:允许
      • 0:不允许
2.3.2 ArticleStatus
  1. com.liuyanzhao.ssm.blog.enums.ArticleStatus

    package com.liuyanzhao.ssm.blog.enums;/*** @author 言曌* @date 2018/11/17 下午4:47*/public enum ArticleStatus {PUBLISH(1, "已发布"),DRAFT(0, "草稿");private Integer value;private String message;ArticleStatus(Integer value, String message) {this.value = value;this.message = message;}public Integer getValue() {return value;}public void setValue(Integer value) {this.value = value;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
    }
    
    • 文章状态
      • 1:已发布
      • 0:草稿
2.3.3 CategoryStatus
  1. com.liuyanzhao.ssm.blog.enums.CategoryStatus

    package com.liuyanzhao.ssm.blog.enums;import lombok.Data;/*** @author 言曌* @date 2018/11/17 下午4:47*/public enum CategoryStatus {NORMAL(1, "正常"),HIDDEN(0, "隐藏");private Integer value;private String message;CategoryStatus(Integer value, String message) {this.value = value;this.message = message;}public Integer getValue() {return value;}public void setValue(Integer value) {this.value = value;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
    }
    
    • 分类状态
      • 1:正常
      • 0:隐藏
2.3.4 LinkStatus
  1. com.liuyanzhao.ssm.blog.enums.LinkStatus

    package com.liuyanzhao.ssm.blog.enums;/*** @author 言曌* @date 2018/11/17 下午4:47*/public enum LinkStatus {NORMAL(1, "显示"),HIDDEN(0, "隐藏");private Integer value;private String message;LinkStatus(Integer value, String message) {this.value = value;this.message = message;}public Integer getValue() {return value;}public void setValue(Integer value) {this.value = value;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
    }
    
    • 链接状态
      • 1:显示
      • 0:隐藏
2.3.5 MenuLevel
  1. com.liuyanzhao.ssm.blog.enums.MenuLevel

    package com.liuyanzhao.ssm.blog.enums;/*** @author 言曌* @date 2018/11/17 下午4:47*/public enum MenuLevel {TOP_MENU(1, "顶部菜单"),MAIN_MENU(2, "主体菜单");private Integer value;private String message;MenuLevel(Integer value, String message) {this.value = value;this.message = message;}public Integer getValue() {return value;}public void setValue(Integer value) {this.value = value;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
    }
    
    • 菜单等级
      • 1:顶部菜单
      • 2:主体菜单
2.3.6 NoticeStatus
  1. com.liuyanzhao.ssm.blog.enums.NoticeStatus

    package com.liuyanzhao.ssm.blog.enums;/*** @author 言曌* @date 2018/11/17 下午4:47*/public enum NoticeStatus {NORMAL(1, "显示"),HIDDEN(0, "隐藏");private Integer value;private String message;NoticeStatus(Integer value, String message) {this.value = value;this.message = message;}public Integer getValue() {return value;}public void setValue(Integer value) {this.value = value;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
    }
    
    • 通知状态
      • 1:显示
      • 0:隐藏
2.3.7 PageStatus
  1. com.liuyanzhao.ssm.blog.enums.PageStatus

    package com.liuyanzhao.ssm.blog.enums;/*** @author 言曌* @date 2018/11/17 下午4:47*/public enum PageStatus {NORMAL(1, "显示"),HIDDEN(0, "隐藏");private Integer value;private String message;PageStatus(Integer value, String message) {this.value = value;this.message = message;}public Integer getValue() {return value;}public void setValue(Integer value) {this.value = value;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
    }
    
    • 页面状态
      • 1:显示
      • 0:隐藏
2.3.8 Role
  1. com.liuyanzhao.ssm.blog.enums.Role

    package com.liuyanzhao.ssm.blog.enums;/*** @author 言曌* @date 2018/11/17 下午4:47*/public enum Role {OWNER(1, "博主"),VISITOR(0, "其他用户");private Integer value;private String message;Role(Integer value, String message) {this.value = value;this.message = message;}public Integer getValue() {return value;}public void setValue(Integer value) {this.value = value;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
    }
    
    • 浏览角色
      • 1:博主
      • 0:其他用户
2.3.9 UserRole
  1. com.liuyanzhao.ssm.blog.enums.UserRole

    package com.liuyanzhao.ssm.blog.enums;/*** 角色枚举** @author 言曌* @date 2021/2/25 2:31 下午*/public enum UserRole {ADMIN("admin", "管理员"),USER("user", "用户");private String value;private String message;UserRole(String value, String message) {this.value = value;this.message = message;}public String getValue() {return value;}public void setValue(String value) {this.value = value;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
    }
    
    • 用户角色
      • admin:管理员
      • user:用户
2.4 dto数据传输对象

├─dto
│ ArticleParam.java
│ JsonResult.java
│ ResultVO.java
│ UploadFileVO.java

2.4.1 ArticleParam
  1. com.liuyanzhao.ssm.blog.dto.ArticleParam

    package com.liuyanzhao.ssm.blog.dto;import lombok.Data;import java.util.List;/*** @author 言曌* @date 2018/11/25 下午3:56*/
    @Data
    public class ArticleParam {private Integer articleId;private String articleTitle;private String articleContent;private Integer articleParentCategoryId;private Integer articleChildCategoryId;private Integer articleOrder;private Integer articleStatus;private String articleThumbnail;private List<Integer> articleTagIds;}
    
    • 文章参数
2.4.2 JsonResult
  1. com.liuyanzhao.ssm.blog.dto.JsonResult

    package com.liuyanzhao.ssm.blog.dto;import lombok.Data;/*** @author 言曌* @date 2017/11/30 下午7:04*/@Data
    public class JsonResult<T> {/*** 错误码*/private Integer code;/*** 提示信息*/private String msg;/*** 返回的具体内容*/private T data;public JsonResult(Integer code, String msg, T data) {this.code = code;this.msg = msg;this.data = data;}public JsonResult() {}public JsonResult fail() {return new JsonResult(1, "操作失败", null);}public JsonResult fail(String msg) {return new JsonResult(1, msg, null);}public JsonResult ok() {return new JsonResult(0, "操作成功", null);}public JsonResult ok(T data) {return new JsonResult(0, "操作成功", data);}
    }
    
    • json传输结果
2.4.3 ResultVO
  1. com.liuyanzhao.ssm.blog.dto.ResultVO

    package com.liuyanzhao.ssm.blog.dto;import lombok.Data;/*** @author 言曌* @date 2017/11/30 下午7:04*/@Data
    public class ResultVO<T> {/*** 错误码*/private Integer code;/*** 提示信息*/private String msg;/*** 返回的具体内容*/private T data;public ResultVO(Integer code, String msg, T data) {this.code = code;this.msg = msg;this.data = data;}public ResultVO() {}
    }
    
    • 结果显示层对象
2.4.4 UploadFileVO
  1. com.liuyanzhao.ssm.blog.dto.UploadFileVO

    package com.liuyanzhao.ssm.blog.dto;import lombok.Data;/*** @author 言曌* @date 2017/11/30 下午7:41*/@Data
    public class UploadFileVO {private String src;private String title;}
    
    • 上传文件显示层对象
2.5 util工具类

└─util
│ MyUtils.java

└─interceptor
AdminInterceptor.java
HomeResourceInterceptor.java
LoginInterceptor.java

2.5.1 MyUtils 我的工具类
  • com.liuyanzhao.ssm.blog.util.MyUtils

    package com.liuyanzhao.ssm.blog.util;import javax.servlet.http.HttpServletRequest;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;/*** 常用的方法* Created by 言曌 on 2017/8/24.*/public class MyUtils {/*** 获得IP地址** @param request* @return*/public static String getIpAddr(HttpServletRequest request) {String ipAddress = request.getHeader("x-forwarded-for");if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("Proxy-Client-IP");}if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("WL-Proxy-Client-IP");}if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getRemoteAddr();}//对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割if (ipAddress != null && ipAddress.length() > 15) {if (ipAddress.indexOf(",") > 0) {ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));}}return ipAddress;}/*** 获得Md5加密** @param str 原字符串* @return 加密后的字符串*/public static String strToMd5(String str) {String md5Str = null;if (str != null && str.length() != 0) {try {MessageDigest md = MessageDigest.getInstance("MD5");md.update(str.getBytes());byte b[] = md.digest();int i;StringBuffer buf = new StringBuffer("");for (int offset = 0; offset < b.length; offset++) {i = b[offset];if (i < 0) {i += 256;}if (i < 16) {buf.append("0");}buf.append(Integer.toHexString(i));}//32位md5Str = buf.toString();//16位//md5Str = buf.toString().substring(8, 24);} catch (NoSuchAlgorithmException e) {e.printStackTrace();}}return md5Str;}/*** 根据email获取gravatar头像** @param email Email* @return 头像URL*/public static String getGravatar(String email) {String emailMd5 = strToMd5(email);//设置图片大小32pxString avatar = "http://cn.gravatar.com/avatar/" + emailMd5 + "?s=128&d=identicon&r=PG";return avatar;}}
    
    • getIpAddr(HttpServletRequest request)

      • 获得IP地址

        • @param request HttpServletRequest请求
        • @return IP地址
      • 源代码

        public static String getIpAddr(HttpServletRequest request) {String ipAddress = request.getHeader("x-forwarded-for");if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("Proxy-Client-IP");}if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getHeader("WL-Proxy-Client-IP");}if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getRemoteAddr();}//对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割if (ipAddress != null && ipAddress.length() > 15) {if (ipAddress.indexOf(",") > 0) {ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));}}return ipAddress;
        }
        
      • 自上而下分别从request.getHeader("x-forwarded-for");、request.getHeader("Proxy-Client-IP");request.getHeader("WL-Proxy-Client-IP");request.getRemoteAddr();获取IP地址,若未从上方获取则进入下层获取。

      • 获取完毕后,若是多个代理的情况,则取第一个IP为客户端真实IP

    • String strToMd5(String str)

      • 获得Md5加密

        • @param str 原字符串
        • @return 加密后的字符串
      • 源代码

        public static String strToMd5(String str) {String md5Str = null;if (str != null && str.length() != 0) {try {MessageDigest md = MessageDigest.getInstance("MD5");md.update(str.getBytes());byte b[] = md.digest();int i;StringBuffer buf = new StringBuffer("");for (int offset = 0; offset < b.length; offset++) {i = b[offset];if (i < 0) {i += 256;}if (i < 16) {buf.append("0");}buf.append(Integer.toHexString(i));}//32位md5Str = buf.toString();//16位//md5Str = buf.toString().substring(8, 24);} catch (NoSuchAlgorithmException e) {e.printStackTrace();}}
        
    • String getGravatar(String email)

      • 根据email获取gravatar头像

        • @param email Email
        • @return 头像URL
      • 源代码

        public static String getGravatar(String email) {String emailMd5 = strToMd5(email);//设置图片大小32pxString avatar = "http://cn.gravatar.com/avatar/" + emailMd5 + "?s=128&d=identicon&r=PG";return avatar;
        }
        
代码编程
赞赏

相关文章

不伤原图电脑在线去水印网站
在线视频转换器工具
图片如何在线无痕去除水印
图片带满屏水印怎么去除?
超详细Hyperledger Fabric2.3.3开发教程
入门卷积神经网络必备,基础、理论、实战一网打尽!