源码解析四步走
-
了解项目是干嘛用的,涉及到哪些知识点
-
把项目跑起来
-
阅读源码并进行调试,把组件弄熟,看日志,打印变量
浏览顺序参照:controller—service—respository—model
-
加入自己的功能和想法,实现
Halo
配置文件解析
build.gradle
plugins {
id 'org.springframework.boot' version '2.2.2.RELEASE'
id "io.freefair.lombok" version "3.6.6"
// id 'war'
id 'java'
}
apply plugin: 'io.spring.dependency-management'
group = 'run.halo.app'
archivesBaseName = 'halo'
version = '1.2.0'
sourceCompatibility = '1.8'
description = 'Halo, personal blog system developed in Java.'
repositories {
maven {
url 'https://maven.aliyun.com/nexus/content/groups/public'
}
mavenCentral()
jcenter()
}
configurations {
implementation {
exclude module: 'spring-boot-starter-tomcat'
exclude module: 'slf4j-log4j12'
}
developmentOnly
runtimeClasspath {
extendsFrom developmentOnly
}
}
bootJar {
manifest {
attributes('Implementation-Title': 'Halo Application',
'Implementation-Version': version)
}
}
ext {
ohMyEmailVersion = '0.0.4'
hutoolVersion = '5.0.3'
upyunSdkVersion = '4.0.1'
qiniuSdkVersion = '7.2.18'
aliyunSdkVersion = '3.4.2'
baiduSdkVersion = '0.10.36'
qcloudSdkVersion = '5.5.7'
swaggerVersion = '2.9.2'
commonsLangVersion = '3.8.1'
httpclientVersion = '4.5.7'
dataformatYamlVersion = '2.9.2'
jgitVersion = '5.3.0.201903130848-r'
flexmarkVersion = '0.42.12'
thumbnailatorVersion = '0.4.8'
image4jVersion = '0.7zensight1'
flywayVersion = '6.1.0'
h2Version = '1.4.196'
levelDbVersion = '0.12'
jsonVersion = '20190722'
fastJsonVersion = '1.2.56'
templateInheritance = "0.4.RELEASE"
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-undertow'
implementation 'org.springframework.boot:spring-boot-starter-freemarker'
implementation "kr.pe.kwonnam.freemarker:freemarker-template-inheritance:$templateInheritance"
implementation "io.github.biezhi:oh-my-email:$ohMyEmailVersion"
implementation "cn.hutool:hutool-core:$hutoolVersion"
implementation "cn.hutool:hutool-crypto:$hutoolVersion"
implementation "cn.hutool:hutool-extra:$hutoolVersion"
implementation "com.upyun:java-sdk:$upyunSdkVersion"
implementation "com.qiniu:qiniu-java-sdk:$qiniuSdkVersion"
implementation "com.aliyun.oss:aliyun-sdk-oss:$aliyunSdkVersion"
implementation "com.baidubce:bce-java-sdk:$baiduSdkVersion"
implementation "com.qcloud:cos_api:$qcloudSdkVersion"
implementation "io.springfox:springfox-swagger2:$swaggerVersion"
implementation "io.springfox:springfox-swagger-ui:$swaggerVersion"
implementation "org.apache.commons:commons-lang3:$commonsLangVersion"
implementation "org.apache.httpcomponents:httpclient:$httpclientVersion"
implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:$dataformatYamlVersion"
implementation "org.eclipse.jgit:org.eclipse.jgit:$jgitVersion"
implementation "com.vladsch.flexmark:flexmark:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-attributes:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-autolink:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-emoji:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-escaped-character:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-gfm-strikethrough:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-gfm-tasklist:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-ins:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-media-tags:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-tables:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-toc:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-yaml-front-matter:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-ext-gitlab:$flexmarkVersion"
implementation "com.vladsch.flexmark:flexmark-html-parser:$flexmarkVersion"
implementation "net.coobird:thumbnailator:$thumbnailatorVersion"
implementation "net.sf.image4j:image4j:$image4jVersion"
implementation "org.flywaydb:flyway-core:$flywayVersion"
implementation "org.json:json:$jsonVersion"
implementation "com.alibaba:fastjson:$fastJsonVersion"
implementation "org.iq80.leveldb:leveldb:$levelDbVersion"
runtimeOnly "com.h2database:h2:$h2Version"
runtimeOnly 'mysql:mysql-connector-java'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
}
都是halo的项目管理的文件,一些依赖
看项目涉及哪些知识点,直奔build.gradle
Idea中快捷键的用法
F9 resume programe 恢复程序
Alt+F10 show execution point 显示执行断点
F8 Step Over 相当于eclipse的f6 跳到下一步
F7 Step Into 相当于eclipse的f5就是 进入到代码
Alt+shift+F7 Force Step Into 这个是强制进入代码
Shift+F8 Step Out 相当于eclipse的f8跳到下一个断点,也相当于eclipse的f7跳出函数
Atl+F9 Run To Cursor 运行到光标处
ctrl+shift+F9 debug运行java类
ctrl+shift+F10 正常运行java类
alt+F8 debug时选中查看值
有关Halo后台登陆模块的调试
@Override
public AuthToken authenticate(LoginParam loginParam) {
Assert.notNull(loginParam, "Login param must not be null");
String username = loginParam.getUsername();
String mismatchTip = "用户名或者密码不正确";
final User user;
try {
// Get user by username or email
//isEmail检验是否为可用邮箱,是返回true执行按邮箱查找用户,否则返回false执行按用户名查找
user = Validator.isEmail(username) ?
userService.getByEmailOfNonNull(username) : userService.getByUsernameOfNonNull(username);
} catch (NotFoundException e) {
log.error("Failed to find user by name: " + username, e);
eventPublisher.publishEvent(new LogEvent(this, loginParam.getUsername(), LogType.LOGIN_FAILED, loginParam.getUsername()));
throw new BadRequestException(mismatchTip);
}
//判断是否账号停用
userService.mustNotExpire(user);
//判断密码是否匹配
if (!userService.passwordMatch(user, loginParam.getPassword())) {
// If the password is mismatch
eventPublisher.publishEvent(new LogEvent(this, loginParam.getUsername(), LogType.LOGIN_FAILED, loginParam.getUsername()));
throw new BadRequestException(mismatchTip);
}
if (SecurityContextHolder.getContext().isAuthenticated()) {
// If the user has been logged in
throw new BadRequestException("您已登录,请不要重复登录");
}
// Log it then login successful
eventPublisher.publishEvent(new LogEvent(this, user.getUsername(), LogType.LOGGED_IN, user.getNickname()));
// Generate new token
return buildAuthToken(user);
}
三元运算符:
如名字表示的三元运算符需要三个操作数。
语法为:条件表达式?表达式1:表达式2。
说明:问号前面的位置是判断的条件,判断结果为bool型,为true时调用表达式1,为false时调用表达式2。
其逻辑为:“如果条件表达式成立或者满足则执行表达式1,否则执行第二个。”常用在设置默认值,例如某个值不一定存在,则判断这个值是否存在,不存在给默认值(表达式2)。
简述:?前面判断,true执行表达式1,false执行表达式2
用户表信息:
@NonNull
private AuthToken buildAuthToken(@NonNull User user) {
Assert.notNull(user, "User must not be null");
// Generate new token
AuthToken token = new AuthToken();
//令牌添加随机ID
token.setAccessToken(HaloUtils.randomUUIDWithoutDash());
//设置令牌过期时长,这个是写死的
token.setExpiredIn(ACCESS_TOKEN_EXPIRED_SECONDS);
token.setRefreshToken(HaloUtils.randomUUIDWithoutDash());
// Cache those tokens, just for clearing
cacheStore.putAny(SecurityUtils.buildAccessTokenKey(user), token.getAccessToken(), ACCESS_TOKEN_EXPIRED_SECONDS, TimeUnit.SECONDS);
cacheStore.putAny(SecurityUtils.buildRefreshTokenKey(user), token.getRefreshToken(), REFRESH_TOKEN_EXPIRED_DAYS, TimeUnit.DAYS);
// Cache those tokens with user id
cacheStore.putAny(SecurityUtils.buildTokenAccessKey(token.getAccessToken()), user.getId(), ACCESS_TOKEN_EXPIRED_SECONDS, TimeUnit.SECONDS);
cacheStore.putAny(SecurityUtils.buildTokenRefreshKey(token.getRefreshToken()), user.getId(), REFRESH_TOKEN_EXPIRED_DAYS, TimeUnit.DAYS);
return token;
}
返回一个令牌实体
security中大都是跟登录模块相关的