记录论坛项目中的一些重要功能的实现
$ git init //初始化文件为本地仓库
$ git add .
$ git commit -m "提交信息"
$ git remote add origin '远程仓库url'
$ git push -u origin 对应远程分支名
以后修改文件后push上去不需要网址了:
$ git add --all
$ git commit -m "信息"
$ git push
当前网页地址,即
看到已经成功,从github端携带了code,用于获取accesstoken
@GetMapping("/callback")
public String callback(@RequestParam(name="code") String code,
@RequestParam(name="state") String state,
HttpServletResponse response) {
AccessTokenDTO accessTokenDTO = new AccessTokenDTO();
accessTokenDTO.setClient_id(clientId);
accessTokenDTO.setClient_secret(clientSecret);
accessTokenDTO.setCode(code);
accessTokenDTO.setRedirect_uri(redirectUri);
accessTokenDTO.setState(state);
String accessToken = githubProvider.getAccessToken(accessTokenDTO);
GithubUser githubUser = githubProvider.getUser(accessToken);
...//返回项目根目录
}
public GithubUser getUser(String accessToken){
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://api.github.com/user?access_token="+accessToken)
.build();
try {
Response response = client.newCall(request).execute();
String string = response.body().string();//Json样式
GithubUser githubUser = JSON.parseObject(string, GithubUser.class);//将JSON样式的string转换为java的类
return githubUser;
} catch (IOException e) {
}
return null;
}
使用数据库保存登录状态。需要自己设置一个value。当登录成功,将此value设置到cookie里面,等传递过来,拿value去数据库里查,将value命名为token。
if (githubUser != null) {
User user = new User();
String token = UUID.randomUUID().toString();
user.setToken(token);
user.setName(githubUser.getName());
user.setAccountId(String.valueOf(githubUser.getId()));
user.setAvatarUrl(githubUser.getAvatarUrl());
userService.createOrUpdate(user);
response.addCookie(new Cookie("token", token));
//登录成功,写入cookie
return "redirect:/";
} else {
log.error("callback get github error,{}",githubUser);
//登录失败
return "redirect:/";
}
将插入数据库的数据当做登录状态,拿token来验证是否已经登录。
数据库实物存储代替了session。下面手动创建cookie的key和value,并根据key识别出value,去数据库中查询,如果存在,则登录成功,如果不存在,则登录失败。
token在网页前端可查看:
整个流程:
当访问“/”之前,拦截器prehandle中,遍历cookie,当找到name=token的cookie时,将cookie的value去数据库中查询,若查询到,将数据库中对应此cookie的user数据和未读数写入session。只有登录过,才有token。
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Cookie[] cookies = request.getCookies();
if (cookies!=null&&cookies.length!=0){
for (Cookie cookie : cookies) {
if (cookie.getName().equals("token")){
String token = cookie.getValue();
UserExample userExample = new UserExample();
userExample.createCriteria()
.andTokenEqualTo(token);
List<User> users=userMapper.selectByExample(userExample);
if(users.size() != 0){
request.getSession().setAttribute("user",users.get(0));
Long unreadCount=notificationService.unreadCount(users.get(0).getId());
request.getSession().setAttribute("unreadCount",unreadCount);//将未读数信息写入session,便于导航栏和我的回复的未读数
}
break;
}
}
}
return true;
}
前端页面通过session获取用户信息,并显示。
Flyway是独立于数据库的应用、管理并跟踪数据库变更的数据库版本管理工具。用通俗的话讲,Flyway可以像Git管理不同人的代码那样,管理不同人的sql脚本,从而做到数据库同步。
flyway在执行脚本时,会在源数据表中检查checksum值,并确定上次运行到哪一个脚本文件,本次执行时从下一条脚本文件开始执行。所以编写脚本的时候不能修改原有的脚本内容,并且新的脚本版本号要连续。
1.引入pom依赖以及插件(5.2.4可用)
<dependency>
<groupId>org.flywaydbgroupId>
<artifactId>flyway-coreartifactId>
<version>5.2.4version>
dependency>
<plugin>
<groupId>org.flywaydbgroupId>
<artifactId>flyway-maven-pluginartifactId>
<version>5.2.4version>
<configuration>
<url>jdbc:h2:~/communityurl>
<user>sauser>
<password>123password>
configuration>
<dependencies>
<dependency>
<groupId>com.h2databasegroupId>
<artifactId>h2artifactId>
<version>1.4.199version>
dependency>
dependencies>
plugin>
2.建立db/migration/文件名.sql:注意格式:V1后面是双下划线
3.写入sql语句
create table USER
(
ID INT AUTO_INCREMENT PRIMARY KEY NOT NULL ,
ACCOUNT_ID VARCHAR(100),
NAME VARCHAR(50),
TOKEN CHAR(36),
GMT_CREATE BIGINT,
GMT_MODIFIED BIGINT,
constraint USER_PK
primary key (ID)
);
4.保证删库的情况下再在终端执行mvn flyway:migrate,来通过sql文件生成数据库的表。
页面和html文件以及后端对应关系:
id和label绑定,就是requestParam中“title”
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<fork>truefork>
configuration>
plugin>
2.某快捷键设置热部署自动编译
为了更改静态页面时,浏览器能实时地变化,需要添加liveReload,并点击图标。
将公共元素抽成一个html文件,用于多处文件的使用
将需要插入的地方通过以下语句插入:
<div th:insert="~{navigation :: nav}">div>
当提交发布问题的表单时,“hidden”使得id不会在前端显现出来
当需要更新查询等功能时,不需要每次都修改自定义的mapper文件。将自定义的mapper文件换成generator产生的mapper文件
为了防止数据库表结构改变时,mapper要重新写的问题,引入了Mybatis generator插件
mvn flyway:migrate //对数据库进行变更
mvn -Dmybatis.generator.overwrite=true mybatis-generator:generate //对xml和mapper进行变更
生成了mapper.xml(包括增删改查),类和mapper接口
通过@ControllerAdvice和@ExceptionHandler处理上下文的业务异常
用此类拦截MVC可以处理的异常,而对于拦截不到的异常,需要自定义一个controller来处理。
通过实现ErrorController的类来自定义异常界面。
而异常信息的上下文传递,则通过exception包下的三个类来实现:
当多人同时点击问题时,要考虑问题被阅读数增加时的并发情况,保证问题增加数目正确。
通过QuestionExtMapper接口和QuestionExtMapper.xml的方法处理并发。xml文件有如下关键incView方法:
<update id="incView" parameterType="life.majiang.community.model.Question">
update QUESTION
set
VIEW_COUNT=VIEW_COUNT+#{viewCount,jdbcType=INTEGER}
where id = #{id}
update>
VIEW_COUNT在当前VIEW_COUNT上的基础上相加,从而处理并发问题。
<script type="text/javascript">
$(function() {
var editor = editormd("question-editor", {
width : "100%",
height : 350,
path: "/js/lib/",
delay:0,
watch:false,
imageUpload: true,
imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
imageUploadURL: "/file/upload",
});
});
script>
. 4. 创建令牌
5. 设置一个UcloudProvider配置BucketName和publicKey,privateKey等参数。