看小匠的视频,跟着一路做下来,感觉收获了很多东西, 这里总结一下,不然过不久就忘了。
方法/思想/技巧
- 不要过度设计,很多东西用到再说。(只是不要过度,该设计还是要设计的,否则要改了常常牵一发而动全身)
- 要学一个东西,看官方文档是最有效的,这里的有效不是快,而是理解掌握,否则看别人的二手资料,cv,终究不是自己的。而且遇到什么参数、名词不理解,随时ctrl+f在文档里面找。也容易对这个技术形成一个整体的概念
- 搜索是有方法的,遇到问题不应该直接cv+post到搜索框去,或者加上自己的上下文,而是用 关键词+空格 的方式,更加快捷和全面
功能
一环扣一环,从最根本最需要的地方出发。发布问题功能就是一开始的“根”功能。
功能流程图
功能模块
登陆接口
具体在下面
问题发布
问题列表
给开始页码和页面大小,取数据库查,然后在index页面显示出来
分页功能
根据传进来的参数设置好开始页数、总页数、导航总页数、导航页数,是否是第一页等信息,再把从数据库查的分好页的list集合赋值给它,传给前端就是带有分页信息的数据了。(如question->questionDTO)
拦截器
不管怎么样最后都会return true放行,只不过如果是带着银行卡来的话,会给相应的银行账户一个属性user
@Service
public class SessionInterceptor implements HandlerInterceptor {
@Autowired
UserMapper userMapper;
@Autowired
NotificationServiceImpl notificationService;
@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();
QueryWrapper<User> queryWrapper = new QueryWrapper();
queryWrapper.eq("token", token);
List<User> users = userMapper.selectList(queryWrapper);
if (users.size() != 0) {
HttpSession session=request.getSession();
session.setAttribute("user",users.get(0));
int unreadCount = notificationService.unreadCount(users.get(0).getId());
session.setAttribute("unreadCount", unreadCount);
}
break;
}
}
}
return true;
}
退出登陆
@GetMapping("/logout")
public String logout(
HttpServletRequest request,
HttpServletResponse response
){
request.getSession().removeAttribute("user");
Cookie cookie=new Cookie("token",null);
cookie.setMaxAge(0);
response.addCookie(cookie);
return "redirect:/";
}
问题详情
带着诸多信息去就行了
问题更新
用到了GetMapping("/publish/{id}") return “publish”;
异常处理
评论回复
这个评论回复涉及了三个对象,一个是评论的人,一个是被评论的人,还有一个是相关的 问题/评论。因为还有一个二级的评论,感觉就略复杂了一点。
相光问题
优化标签
public class TagCache {
public static List<TagDTO> get() {
List<TagDTO> tagDTOS = new ArrayList<>();
TagDTO program = new TagDTO();
program.setCategoryName("开发语言");
program.setTags(Arrays.asList("javascript", "php", "css", "html", "html5", "java", "node.js", "python", "c++", "c", "golang", "objective-c", "typescript", "shell", "swift", "c#", "sass", "ruby", "bash", "less", "asp.net", "lua", "scala", "coffeescript", "actionscript", "rust", "erlang", "perl"));
tagDTOS.add(program);
TagDTO framework = new TagDTO();
framework.setCategoryName("平台框架");
framework.setTags(Arrays.asList("laravel", "spring", "express", "django", "flask", "yii", "ruby-on-rails", "tornado", "koa", "struts"));
tagDTOS.add(framework);
TagDTO server = new TagDTO();
server.setCategoryName("服务器");
server.setTags(Arrays.asList("linux", "nginx", "docker", "apache", "ubuntu", "centos", "缓存 tomcat", "负载均衡", "unix", "hadoop", "windows-server"));
tagDTOS.add(server);
TagDTO db = new TagDTO();
db.setCategoryName("数据库");
db.setTags(Arrays.asList("mysql", "redis", "mongodb", "sql", "oracle", "nosql memcached", "sqlserver", "postgresql", "sqlite"));
tagDTOS.add(db);
TagDTO tool = new TagDTO();
tool.setCategoryName("开发工具");
tool.setTags(Arrays.asList("git", "github", "visual-studio-code", "vim", "sublime-text", "xcode intellij-idea", "eclipse", "maven", "ide", "svn", "visual-studio", "atom emacs", "textmate", "hg"));
tagDTOS.add(tool);
return tagDTOS;
}
}
我的问题
@Controller
public class ProfileController {
@Autowired
QuestionServiceImpl questionService;
@Autowired
NotificationServiceImpl notificationService;
@GetMapping("/profile/{action}")
public String profile(@PathVariable("action")String action, Model model,
@RequestParam(name = "page", defaultValue = "1") Integer page,
@RequestParam(name = "size", defaultValue = "5") Integer size,
HttpServletRequest request
){
User user = (User) request.getSession().getAttribute("user");
if ("questions".equals(action)){
model.addAttribute("section","questions");
model.addAttribute("sectionName","我的问题");
PaginationDTO pageInfo=questionService.selectList(user.getId(),page,size);
model.addAttribute("pageInfo",pageInfo);
}
else if("replies".equals(action)){
model.addAttribute("section","replies");
model.addAttribute("sectionName","最新回复");
PaginationDTO pageInfo=notificationService.selectList(user.getId(),page,size);
model.addAttribute("pageInfo",pageInfo);
}
return "profile";
}
}
通知功能
通知功能和评论功能涉及到的东西都比较多。
markdown功能
根据它的教程配置文件就可以用了,主要是html支持markdown,还有markdown转html,支持图片上传。
可拓展功能
- 搜索功能
这个因为想学了ElasticSerach再做这个功能,所以并没有实现搜索功能
- 个人信息
进入个人页面之后可以修改简介之类的
- 热门话题
根据浏览数回复数高的,展示在首页的右端
后端
HttpServletRequest request
- 它的对象是request
- HttpServletResponse同理
- request对象中封装了什么信息?
- HTTP的请求协议的全部内容,被自动封装到了request对象当中。 所以面向request接口可以获取请求协议中的所有信息。
- request对象生命周期是多久?
- 一次请求对应一个request对象。浏览器向服务器发送了一个URL,就会对应一次请求。
github登陆接口
图是小匠的。
流程:
- 用户点击登陆
- 客户端发送请求,调用github授权
- github返回callback,带着code
- 客户端再发送请求,带着code,换得accesstoken
- github返回accesstoken
- 客户端再发送请求,带着accesstoken,得到用户信息
- 给用户登陆成功/失败
掌握了一个,其他的看官方文档,也是大同小异的qq api
dto 数据传输层
- 方法如果需要两个以上的参数,可以把参数封装成一个dto类,用这个dto来传输
- 数据库尽量不使用外键,会降低检索的一个效率。如果需要用到另一个表的数据,可以用一个dto来装。
其实有些困惑:1.感觉这样子会很麻烦;2.这样子uml图之类的感觉会很难画啊
@Data
public class Question {
@TableId(type = IdType.AUTO)
private Long id;
private String title;
private String description;
private String tag;
private Long gmtCreate;
private Long gmtModified;
private Long creator;
private Long viewCount;
private Long likeCount;
private Long commentCount;
}
如上,question其实是不需要有user这个属性的。但是我们需要用,可以用questionDTO,把user放进去
@Data
public class QuestionDTO {
@TableId(type = IdType.AUTO)
private Long id;
private String title;
private String description;
private String tag;
private Long gmtCreate;
private Long gmtModified;
private Long creator;
private Long viewCount;
private Long likeCount;
private Long commentCount;
private User user;
}
枚举
以前其实不是很清楚枚举要怎么用的。现在明白了:
- 用枚举类型来限制参数,只能从里面选,就降低了出错的可能
- 增加可扩展性
- 便于别人理解阅读
- 而且它里面也可以有属于自己的方法
public enum CommentTypeEnum {
QUESTION(1),
COMMENT(2);
private Integer type;
public Integer getType() {
return type;
}
CommentTypeEnum(Integer type) {
this.type = type;
}
public static boolean isExist(Integer type) {
for (CommentTypeEnum commentTypeEnum : CommentTypeEnum.values()) {
if (commentTypeEnum.getType() == type) {
return true;
}
}
return false;
}
}
session和cookie
代码生成器
pageHelper
flyway
git
springboot配置文件和常用注释
mybatis plus 条件构造器
okHttp
配置
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.14.1</version>
</dependency>
使用
stream流
List<QuestionDTO> questionDTOS = questions.stream().map(q -> {
QuestionDTO questionDTO = new QuestionDTO();
BeanUtils.copyProperties(q, questionDTO);
return questionDTO;
}).collect(Collectors.toList());
前端
- 在js代码加上debugger可以调试
- 可以在页面调好样式,然后复制到css文件来
- ajax
- 属性:contentType,默认值: “application/x-www-form-urlencoded”。
发送信息至服务器时内容编码类型
- dataType 预期服务器返回的数据类型
- 发给服务器的一般都是字符串,所以一般用json.tostringify字符串化data
$.ajax({
type: "POST",
url: "/comment",
contentType: 'application/json',
data: JSON.stringify({
"parentId": targetId,
"content": content,
"type": type
}),
success: function (response) {
if (response.code == 200) {
// window.location.reload();
parent.location.reload();
} else {
if (response.code == 2003) {
let isAccepted = confirm(response.message);
if (isAccepted) {
window.open("https://github.com/login/oauth/authorize?client_id=c05a2ccc4a4995c1b2e2&redirect_uri=http://localhost:8080/callback&scope=user&state=1");
localStorage.setItem("closable","true");
localStorage.getItem("closable")
}
} else {
alert(response.message);
}
}
},
dataType: "json"
}
其他
- List strings = Arrays.asList(“abc”, “”, “bc”, “efg”, “abcd”,"", “jkl”);
- BeanUtils.copyProperties(user,userdto)
一个bean 属性到另一个bean,同一个类是不行的
- JSON.parseObject 和 JSON.toJSONString
- JSON.parseObject(string,person.class) 将json字符串转换为对象
{“name”:“dawang”} 转化为person类,有name属性 - JSON.toJSONString 对象转化为json字符串
- JSON.parseObject(string,person.class) 将json字符串转换为对象
需要有依赖。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>