基于‘纯洁的微笑’开源项目 — Favorites 源码分析

Posted Android小码家

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于‘纯洁的微笑’开源项目 — Favorites 源码分析相关的知识,希望对你有一定的参考价值。

引言:

对于某语言不算熟悉的话自创项目是很痛苦的过程,即便笔者是一位掌握java的android码农,对于java入门也是深感无力,毕竟语言是基础,但框架设计模式却与Android有出入,且学习成本较高,mybatisc,Spring-boot,thleaf,Spring Data JPA,Tomcat,IDEA,MVC,等等。有的似曾相识,有的一脸蒙蔽,笔者正陷入这漩涡当中,本章笔者将对Favorites的源码分析中,整理出完整的项目结构思路以及架构思想,层层剥离,以至融会贯通。

源码链接如下:https://github.com/cloudfavorites/favorites-web
调试提示:
 1//作者使用thymeleaf拆分模块,如需单独调试请将该head单独粘贴到需要观察的页面。
2  <head>
3      <meta charset="utf-8"></meta>
4      <meta http-equiv="X-UA-Compatible" content="IE=edge"></meta>
5      <meta name="renderer" content="webkit"/>
6      <meta name="viewport" content="width=device-width, initial-scale=1.0"></meta>
7      <meta name="description" content=""></meta>
8      <meta name="author" content=""></meta>
9      <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"></meta>
10      <link rel="icon" href="/img/icon.ico" type="image/x-icon"/>
11      <title>云收藏 | 让收藏更简单</title>
12
13      <link rel="stylesheet" href="../../static/vendor/fontawesome/css/font-awesome.min.css"/>
14      <link rel="stylesheet" href="../../static/vendor/simple-line-icons/css/simple-line-icons.css"/>
15      <link rel="stylesheet" href="../../static/vendor/animate.css/animate.min.css"/>
16      <link rel="stylesheet" href="../../static/vendor/toastr/toastr.min.css"/>
17      <link rel="stylesheet" href="../../static/media/css/bootstrap.css"/>
18      <link rel="stylesheet" href="../../static/media/css/app.css"/>
19      <link rel="stylesheet" href="../../static/media/css/theme-i.css"/>
20  </head>
项目架构
  • MVC 
    理解:负责项目的整体架构 简单说就是Controller 调用Repository和Service 通过thymeleaf来响应界面
    学习:

  • Maven+Spring-Boot 
    理解:Maven负责导包,Spring-Boot负责启动程序,找到SpringBootApplication即可,全局唯一。
    学习:

  • thymeleaf

  1. 理解:首页的 return "index";即表示映射到templates文件夹下的index.html

 1    @RequestMapping(value="/index",method=RequestMethod.GET)
2    @LoggerManage(description="首页")
3    public String index(Model model){
4//        IndexCollectorView indexCollectorView = collectorService.getCollectors();
5        model.addAttribute("collector","");
6        User user = super.getUser();
7        if(null != user){
8            model.addAttribute("user",user);
9        }
10        return "index";
11    }
  1. 基础:
    2.1. https://www.cnblogs.com/ityouknow/p/5833560.html
    2.2 https://www.jianshu.com/p/810ace1aeeae

  • Spring Data 
    理解:绑定bean对象

  • Spring Data JPA
    理解:绑定bean对象执行相关操作的工具类
    学习:

  1. 基本操作:https://www.cnblogs.com/zjfjava/p/8456771.html

  2. 操作手册:https://docs.spring.io/spring-data/jpa/docs/2.0.4.RELEASE/reference/html/

  3. 复杂查询:http://www.cnblogs.com/dixinyunpan/p/5856884.html

  4. 例子:

增:

1userRepository.save(new User("aa", "aa@126.com", "aa""aa123456"));

删:

1//方式一  
2@Transactional
3void deleteById(Long id);    
4
5//方式二
6@Transactional
7@Modifying
8@Query("delete from Collect where favoritesId = ?1")
9void deleteByFavoritesId(Long favoritesId);    

查:

 1//方式一  固定写法
2User findByUserName(String userName);
3User findByUserNameOrEmail(String username, String email);
4User findByEmail(String email);
5User findById(long  id);
6
7//方式二
8public String baseSql="select c.id as id,c.title as title, c.type as type,c.url as url,c.logoUrl as logoUrl,c.userId as userId, "
9            + "
c.remark as remark,c.description as description,c.lastModifyTime as lastModifyTime,c.createTime as createTime, "
10            + "
u.userName as userName,u.profilePicture as profilePicture,f.id as favoritesId,f.name as favoriteName "
11            + "
from Collect c,User u,Favorites f WHERE c.userId=u.id and c.favoritesId=f.id and c.isDelete='NO'";
12
13//随便看看根据类别查询收藏
14@Query(baseSql+ "
 and c.type='public' and c.category=?1 ")
15Page<CollectView> findExploreViewByCategory(String category,Pageable pageable);
16
17//方式三 联查+分页
18public String baseSql="
select c.id as id,c.title as title, c.type as type,c.url as url,c.logoUrl as logoUrl,c.userId as userId, "
19            + "
c.remark as remark,c.description as description,c.lastModifyTime as lastModifyTime,c.createTime as createTime, "
20            + "
u.userName as userName,u.profilePicture as profilePicture,f.id as favoritesId,f.name as favoriteName "
21            + "
from Collect c,User u,Favorites f WHERE c.userId=u.id and c.favoritesId=f.id and c.isDelete='NO'";
22
23@Query(baseSql+ "
 and c.userId=?1 ")
24Page<CollectView> findViewByUserId(Long userId,Pageable pageable);
25

改:

 1//方式一
2@Modifying(clearAutomatically=true)
3@Transactional
4@Query("update User set passWord=:passWord where email=:email") 
5int setNewPassword(@Param("passWord") String passWord, @Param("email") String email);
6//方式二
7@Transactional
8@Modifying
9@Query("update Collect c set c.type = ?1 where c.id = ?2 and c.userId=?3 ")
10int modifyByIdAndUserId(CollectType type, Long id, Long userId);    
安全机制
  1. AOP

  2. SecurityFilter

  3. 错误URL提示页面

 1//在common.js中统一处理
2function handleServerResponse() {
3    if (xmlhttp.readyState == 4) {
4        //document.getElementById("mainSection").innerHTML =xmlhttp.responseText;
5        var text = xmlhttp.responseText;
6        if(text.indexOf("<title>Favorites error Page</title>") >= 0){
7            window.location.href="/error.html";
8        }else{
9            $("#content").html(xmlhttp.responseText);
10        }
11    }
12}
  1. 统一错误提示(JSON)

  2. 密码学

统一外部接口
Session 和Cookie
  1. Cookie返回给客户端

 1//保存
2Cookie cookie = new Cookie(Const.LOGIN_SESSION_KEY, cookieSign(loginUser.getId().toString()));
3cookie.setMaxAge(Const.COOKIE_TIMEOUT);
4cookie.setPath("/");
5response.addCookie(cookie)
6
7//取值验证
8Cookie[] cookies = request.getCookies();
9if (cookies != null) {
10    boolean flag = true;
11    for (int i = 0; i < cookies.length; i++) {
12        Cookie cookie = cookies[i];
13        if (cookie.getName().equals(Const.LOGIN_SESSION_KEY)) {
14            if (StringUtils.isNotBlank(cookie.getValue())) {
15                flag = false;
16            } else {
17                break;
18            }
19        }
20    }
21}
  1. Session :相当于是SP

 1protected HttpServletRequest getRequest() {
2    return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
3}
4
5protected HttpSession getSession() {
6    return getRequest().getSession();
7}
8
9getSession().setAttribute(Const.LOGIN_SESSION_KEY, user);
10
11protected User getUser() {
12    return (User) getSession().getAttribute(Const.LOGIN_SESSION_KEY);
13}
Session与Cookie的
cookie数据存放在客户的浏览器上,session数据放在服务器上。
cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗 考虑到安全应当使用session。
session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能 考虑到减轻服务器性能方面,应当使用COOKIE。
单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
---------------------建议---------------------
将登陆信息等重要信息存放为SESSION
其他信息如果需要保留,可以放在COOKIE中
Spring-Boot注解
  1. 参考:https://www.cnblogs.com/ldy-blogs/p/8550406.html

  • @profile的用法 
    https://blog.csdn.net/wild46cat/article/details/71189858-

  • @Server("") 括号内作用

 1//接口
2public interface FeedbackService {
3
4    public void saveFeeddback(Feedback feedback,Long userId);
5}
6
7//实现一
8@Service("feedbackService")
9public class FeedbackServiceImpl implements FeedbackService {
10
11    @Autowired
12    private FeedbackRepository feedbackRepository;
13
14    @Override
15    public void saveFeeddback(Feedback feedback,Long userId) {
16    // 一的方法
17    }
18}
19
20//实现二
21@Service("feedbackService2")
22public class FeedbackServiceImpl2 implements FeedbackService {
23
24    @Autowired
25    private FeedbackRepository feedbackRepository;
26
27    @Override
28    public void saveFeeddback(Feedback feedback,Long userId) {
29       // 二的方法
30    }
31}
32//一般情况下这样写就可以了
33初始化
34@RestController
35@RequestMapping("/feedback")
36public class FeedbackController extends BaseController{
37    @Autowired
38    private FeedbackService feedbackService;
39}
40//出现两个实现时
41初始化
42@RestController
43@RequestMapping("/feedback")
44public class FeedbackController extends BaseController{
45
46    @Autowired 
47    @Qualifier("feedbackService")
48    private FeedbackService feedbackService;
49
50    @Autowired 
51    @Qualifier("feedbackService2")
52    private FeedbackService feedbackService2;
53}
配置文件
  • @Configuration
    理解:用于定义配置类,@Bean的对象将被加入(Context)上下文中作为全局变量。
    学习:

  • https://blog.csdn.net/leoxyk/article/details/79800020(基础)

  • https://blog.csdn.net/qq_34531925/article/details/78194651(高级)

测试

直接看源码即可,嘿嘿

打包上线

参考:https://blog.csdn.net/qq_20330595/article/details/83862486#javaweb_38

总结:
  1. 分析了源码之后我们得到了什么
    1.1. 基本掌握MVC设计模式
    1.2. 基本掌握thymeleaf
    1.3. 基本掌握项目的部署与搭建(Tomcat)
    1.4. 基本理解项目整体架构
    1.5. 基本掌握Spring-boot框架
    1.6. 基本掌握spring-data-jpa框架

  2. 我们应该如何去孵化自己的项目
    答:其实这个问题应该问下自己,最终学习的目的是什么,如果只是为了学习而学习是很可怕的,因为没有目的性,我们很难坚持,且没有实战的学习毫无意义。笔者也时常问自己究竟想做什么?就在此刻笔者也没有想清楚,但是秉着全栈的初衷,笔者掌握一门后台语言的想法始终不变,就笔者的学习思路,笔者打算就地取材,直接站在巨人的肩膀上面,修修改改,最终改造成一个笔者满意的个人后台系统,可能其中充满着原作者的代码以及版权声明,不过那只是后话。循序渐进的学习才能真正的掌握一门语言,即便笔者有java基础也绝不可能一步登天,任何人都一样,个中的原因笔者不想解释。原作者的项目是从2016年中写到今年下半年,2年之久的项目,加之其精进的代码风格,笔者本着敬畏之心慢慢阅读,断续的花了将近2周的时间,虽收获颇丰,但碍于对java的认知程度不够,仍未能完全理解。

3.碍于篇幅,查看完整版请点击下方 原文链接

以上是关于基于‘纯洁的微笑’开源项目 — Favorites 源码分析的主要内容,如果未能解决你的问题,请参考以下文章

上周热点回顾(8.19-8.25)

被抓了。

盈利了。

薪资倒挂!

工程方面

麻了,Logback也爆雷了。。。