个人博客功能:
技术组合:
工具与环境:
课程内容模块:
你能学得什么?
用户故事是敏捷框架中的一种开发方法。可以帮助开发者转换视角,以用户的角度更好的把握需求,从而实现具有商业价值的功能。
用户故事最好是用户团队编写
用户故事模板:
关键点:角色、功能、商业价值
举例:
个人博客系统的用户故事:
角色:普通访客,管理员(我)
页面规划:
前端展示:首页、详情页、分类、标签、归档、关于我
后台管理:模板页
Semantic UI官网
Semantic UI中文官网
WebStorm下载与破解
背景图片资源
编辑器 Markdown
内容排版 typo.css
动画 animate.css
代码高亮 prism
目录生成 Tocbot
滚动侦测 waypoints
平滑滚动 jquery.scrollTo
二维码生成 qrcode.js
IDEA下载 https://www.jetbrains.com/idea/
1、引入Spring Boot模块:
2、application.yml配置
使用 thymeleaf 3
pom.xml:
<thymeleaf.version>3.0.2.RELEASEthymeleaf.version>
<thymeleaf-layout-dialect.version>2.1.1thymeleaf-layout-dialect.version>
application.yml:
spring:
thymeleaf:
mode: HTML
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
日志配置
application.yml:
logging:
level:
root: info
com.imcoding: debug
file: log/imcoding.log
logback-spring.xml:
<configuration>
<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" />
<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}.%ifileNamePattern>
<maxHistory>30maxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MBmaxFileSize>
timeBasedFileNamingAndTriggeringPolicy>
rollingPolicy>
appender>
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="TIME_FILE" />
root>
configuration>
1、定义错误页面
2、全局处理异常
统一处理异常:
@ControllerAdvice
public class ControllerExceptionHandler {
private final Logger logger = LoggerFactory.getLogger(ControllerExceptionHandler.class);
/**
* 异常处理
* @param request
* @param e
* @return
*/
@ExceptionHandler({Exception.class})
public ModelAndView handleException(HttpServletRequest request, Exception e) throws Exception {
logger.error("Request URL : {} , Exception : {}", request.getRequestURL(), e);
if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null) {
throw e;
}
ModelAndView mav = new ModelAndView();
mav.addObject("url", request.getRequestURL());
mav.addObject("exception", e);
mav.setViewName("error/error");
return mav;
}
}
错误页面异常信息显示处理:
<div>
<div th:utext="'<!--'" th:remove="tag">div>
<div th:utext="'Failed Request URL : ' + ${url}" th:remove="tag">div>
<div th:utext="'Exception message : ' + ${exception.message}" th:remove="tag">div>
<ul th:remove="tag">
<li th:each="st : ${exception.stackTrace}" th:remove="tag"><span th:utext="${st}" th:remove="tag">span>li>
ul>
<div th:utext="'-->'" th:remove="tag">div>
div>
3、资源找不到异常
@ResponseStatus(HttpStatus.NOT_FOUND)
public class NotFoundExcepiton extends RuntimeException {
public NotFoundExcepiton() {
}
public NotFoundExcepiton(String message) {
super(message);
}
public NotFoundExcepiton(String message, Throwable cause) {
super(message, cause);
}
}
1、记录日志内容
2、记录日志类:
@Aspect
@Component
public class LogAspect {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 定义切面
*/
@Pointcut("execution(* com.imcoding.web.*.*(..))")
public void log() {
}
@Before("log()")
public void doBefore(JoinPoint joinPoint) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String classMethod = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
ReqeustLog reqeustLog = new ReqeustLog(
request.getRequestURL().toString(),
request.getRemoteAddr(),
classMethod,
joinPoint.getArgs()
);
logger.info("Rquest ----- {}",reqeustLog);
}
@After("log()")
public void doAfter() {
//logger.info("---------- doAfter 2 ----------");
}
@AfterReturning(returning = "result",pointcut = "log()")
public void doAtfertRturning(Object result) {
logger.info("Return ------ {}",result );
}
private class ReqeustLog {
private String url;
private String ip;
private String classMethod;
private Object[] args;
public ReqeustLog(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 "ReqeustLog{" +
"url='" + url + '\'' +
", ip='" + ip + '\'' +
", classMethod='" + classMethod + '\'' +
", args=" + Arrays.toString(args) +
'}';
}
}
}
1、静态页面导入project
2、thymeleaf布局
3、错误页面美化
4、设计与规范
实体类:
实体关系:
评论类自关联关系:
Comment类:
User类:
Service/DAO层命名约定:
1、构建登录页面和后台管理首页
2、UserService和UserRepository
3、LoginController实现登录
4、MD5加密
5、登录拦截器
1、分类管理页面
2、分类列表分页
{
"content":[
{"id":123,"title":"blog122","content":"this is blog content"},
{"id":122,"title":"blog121","content":"this is blog content"},
{"id":121,"title":"blog120","content":"this is blog content"},
{"id":120,"title":"blog119","content":"this is blog content"},
{"id":119,"title":"blog118","content":"this is blog content"},
{"id":118,"title":"blog117","content":"this is blog content"},
{"id":117,"title":"blog116","content":"this is blog content"},
{"id":116,"title":"blog115","content":"this is blog content"},
{"id":115,"title":"blog114","content":"this is blog content"},
{"id":114,"title":"blog113","content":"this is blog content"},
{"id":113,"title":"blog112","content":"this is blog content"},
{"id":112,"title":"blog111","content":"this is blog content"},
{"id":111,"title":"blog110","content":"this is blog content"},
{"id":110,"title":"blog109","content":"this is blog content"},
{"id":109,"title":"blog108","content":"this is blog content"}],
"last":false,
"totalPages":9,
"totalElements":123,
"size":15,
"number":0,
"first":true,
"sort":[{
"direction":"DESC",
"property":"id",
"ignoreCase":false,
"nullHandling":"NATIVE",
"ascending":false
}],
"numberOfElements":15
}
3、分类新增、修改、删除
1、博客分页查询
2、博客新增
3、博客修改
4、博客删除
1、博客列表
2、top分类
3、top标签
4、最新博客推荐
5、博客详情
1、Markdown 转换 HTML
<dependency>
<groupId>com.atlassian.commonmarkgroupId>
<artifactId>commonmarkartifactId>
<version>0.10.0version>
dependency>
<dependency>
<groupId>com.atlassian.commonmarkgroupId>
<artifactId>commonmark-ext-heading-anchorartifactId>
<version>0.10.0version>
dependency>
<dependency>
<groupId>com.atlassian.commonmarkgroupId>
<artifactId>commonmark-ext-gfm-tablesartifactId>
<version>0.10.0version>
dependency>
2、评论功能
项目下载地址:https://download.csdn.net/download/weixin_43664418/12029379