豪翔天下

Change My World by Program

0%

前两天团队接到一个新项目,我需要为其配置Circle CI,于是就又折腾了一下,不过还好,毕竟之前做过运维的,CI的基本原理是知道的,所以很快就弄好了,这里也简单的记录一下。

1. 为项目开启Circle CI

这一步需要在circleci后台项目列表里面为指定的项目开启配置Set Up Project,因为第一步已经编写好了配置文件,所以这里可以直接选择start building。这一步circleci会自动在对应的项目里面添加Deploy Key并且会自动配置到circleci的项目管理里面,如下:

阅读全文 »

禁用csrf认证

全局禁用csrf

app/Http/Kernel.php中,$middleware表示全局中间件,而$routeMiddleware表示针对某个路由的中间件,所以只需要把csrf在$middleware中注释掉,然后在$routeMiddleware中添加'csrf' => 'App\Http\Middleware\VerifyCsrfToken'
如果要在某个路由上使用就这样:

1
2
3
Route::group(['middleware' => 'csrf'], function(){     // csrf保护的接口
Route::get('/', 'HomeController@index');
}
针对某几个接口单独禁用csrf

可以在app/Http/Middleware/VerifyCsrfToken$except添加,但是这里的添加只能以正则的方式来匹配,不能使用路由别名,如果路由中有参数可以用星号代替

1
2
3
4
protected $except = [
'webhook/*',
'users/*/profile'
];

一个页面调用多个接口如何传递CSRF Token

由于csrf_token是存储于session的,依照laravel的实现机制,同一时间只能有一个_token,所以无法实现一个页面设置多个csrf token,要解决这个问题要么将非必要的接口忽略csrf,要么每次请求api后从后台生成并返回一个新的token

阅读全文 »

在需要这个效果的时候首先在npm仓库找到了vue-dragscroll库,但是应用在我们自己项目上的时候拖动起来却非常慢,元素跟不上鼠标的移动速度,无奈,就自己简单的实现了一个拖拽指令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import Vue from 'vue'

Vue.directive('dragscroll', function (el) {
el.onmousedown = function (ev) {
const disX = ev.clientX
const disY = ev.clientY
const originalScrollLeft = el.scrollLeft
const originalScrollTop = el.scrollTop
const originalScrollBehavior = el.style['scroll-behavior']
const originalPointerEvents = el.style['pointer-events']
el.style['scroll-behavior'] = 'auto'
// 鼠标移动事件是监听的整个document,这样可以使鼠标能够在元素外部移动的时候也能实现拖动
document.onmousemove = function (ev) {
ev.preventDefault()
const distanceX = ev.clientX - disX
const distanceY = ev.clientY - disY
el.scrollTo(originalScrollLeft - distanceX, originalScrollTop - distanceY)
// 由于我们的图片本身有点击效果,所以需要在鼠标拖动的时候将点击事件屏蔽掉
el.style['pointer-events'] = 'none'
}
document.onmouseup = function () {
document.onmousemove = null
document.onmouseup = null
el.style['scroll-behavior'] = originalScrollBehavior
el.style['pointer-events'] = originalPointerEvents
}
}
})

由于我们项目使用了是Nuxtjs,如果完全由后端渲染,是无法在document上进行事件监听的,所以在nuxt.config.js中这样定义插件:

1
2
3
plugins: [
{ src: '@/plugins/dragscroll', ssr: false }
],

最后可以在任何元素上应用该指令:

1
<div dragscroll><img /></div>

最终的结果类似这样

布局

栅格布局

  • el-rowel-col可以搭配实现24格的栅格布局

  • el-row支持如下属性

参数 含义 说明 可选值 默认值
gutter 每两个栅格之间的间隔(单位是px) number - 0
type 布局模式 string - -
justify flex布局下的水平排列方式 string start/end/center/space-around/space-between start
align flex布局下的垂直排列方式 string top/middle/bottom top
tag 自定义元素标签 string * div
  • el-col支持如下属性
参数 含义 说明 可选值 默认值
span 栅格占据的列数 number - 24
offset 栅格左侧的间隔格数 number - 0
push 栅格向右移动格数 number - 0
pull 栅格向左移动格数 number - 0
xs <768px 响应式栅格数或者栅格属性对象 number/object (例如: {span: 4, offset: 4})
sm ≥768px 响应式栅格数或者栅格属性对象 number/object (例如: {span: 4, offset: 4})
md ≥992px 响应式栅格数或者栅格属性对象 number/object (例如: {span: 4, offset: 4})
lg ≥1200px 响应式栅格数或者栅格属性对象 number/object (例如: {span: 4, offset: 4})
xl ≥1920px 响应式栅格数或者栅格属性对象 number/object (例如: {span: 4, offset: 4}) - -
tag 自定义元素标签 string * Div

栅格布局一般会根据实际的各个分辨率下的情况来设置每个布局的宽度,如果想要直接换行,也可以某一种分辨率之和超过24,这样只要两个col超过24就会换行,例如:

1
2
3
4
5
6
<el-row :gutter="24">
<el-col :xs="20" :sm="6" :md="4" :lg="3" :xl="1"><div></div></el-col>
<el-col :xs="20" :sm="6" :md="8" :lg="9" :xl="11"><div></div></el-col>
<el-col :xs="20" :sm="6" :md="8" :lg="9" :xl="11"><div</div></el-col>
<el-col :xs="20" :sm="6" :md="4" :lg="3" :xl="1"><div</div></el-col>
</el-row>
阅读全文 »

为什么要用nuxt.js,主要就是因为它可以服务端渲染(SSR),相比于传统的vue单页应用,将渲染放到服务器这边,性能肯定能得到很大提升,并且首次加载无需加载特别大的资源,且对搜索引擎友好,所以没有什么理由不用它。

目录结构

assets: 资源目录,用于组织未编译的静态资源

components: 组件目录

layouts: 布局目录

middleware: 中间件目录

pages: 页面目录

plugins: 插件目录

static: 插件目录,会被直接映射到根目录下,可以放置favicon.ico/robots.txt等文件

store: 用于组织应用的vuex状态树文件

nuxt.config.js: 个性化配置文件

阅读全文 »

Spring Initializr:Spring项目初始化工具。

框架分层结构

调用顺序

Controller –> Service Interface –> Service Impl –> Dao Interface –> Dao Impl –> Mapper –> DB

BIZ层

Service(业务逻辑,可以建立子文件夹来进行分类,这样每个biz就可以更细分,如果Biz和Servic都单独作为一层,那么Biz的粒度更细,Service则是提供给别人的接口)、Schedule(定时任务)、Common(一些中间件认证登录等)、Manager、RPC Service、MQTask、JobTask。也有Service和BIZ平行的分层方式,这种情况,一般是Service在调用Biz,Biz执行数据库操作,类似于Manager。

BO(Business Object)

COMMON层

一些公共的对象,公共的抽象类、公共的异常、公共的帮助方法等

DAO层

一般是由MyBatis等工具自动生成的。

DO/PO(Data Object/Persistant Object,与数据表直接对应,也叫Entity层或者Model层):用于存放实体类,与数据库中的属性值保持一致。

Mapper: 对数据库进行数据持久化操作,它的内部方法就是直接对数据库进行操作的。它类似于manager层。可以封装对数据库的复杂的操作。

VO(value object,类似于将数据库的字段抽象为新的业务相关的字段): VO往往用于请求处理层,即Controller。

INTEGRATE层

外部系统的一些接口

Web层

Controller、Config(一些初始化配置,例如线程池、缓存池等配置的初始化)

阅读全文 »

模板语法

  • 模板中如果遇到这种类型的三目运算符a ? a : b,最好用{a || b}来代替
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// v-bind
<a v-bind:href="url">...</a>
<a v-bind:href="`/api/${item.id}`">...</a> // 属性绑定的时候拼接字符串,也可以用['/api/' + item.id]的方式
<a :href="url">...</a> // 缩写
<a title="test"></a>// 如果仅想传入一个字符串作为props给组件,那么不用加冒号
<a :hidden="shouldHidden==='letshidden'"> // 在v-bind中直接用表达式
<img v-bind:src="pic" v-for="pic in pics" />

// v-model
<input type="text" v-model="msg"> // 等价于<input type="text" :value='msg' @input='handleInput'>

// 遍历v-for
<li v-for="item in items">{{item}}</li>
<li v-for="(item, index) in items">{{item}}的索引是{{index}}</li>
<li v-for="(value, name, index) in items">遍历key=>value格式的数组,顺便还有索引</li>
<li v-for="(item,index) in items"><span v-if="index !== items.length-1">判断是否是列表最后一个元素,目前没找到更好的方法</span></li>

// v-on
<a v-on:click="doSomething">...</a>
<a @click="doSomething">...</a>

// v-html,将内容不转义直接展示为html内容,如果是用户输入的内容,这里一定要防止XSS攻击,最简单的方法就是使用https://github.com/leizongmin/js-xss在外面处理一下
<div v-html="XSS(data)"></div>
<div v-html="$options.filter.myfilter(data)"></div> // v-html中使用过滤器

// v-if, v-else, v-else-if, 条件判断
// v-show,只是控制是否展示,DOM是存在的
阅读全文 »

建议安装Mybatis-plus

Mybatis官方文档

目录结构

  • Mapper.xml文件是真实的SQL语句对应关系

MyBatis生成的DAO层文件目录如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.
├── entity
│   ├── Table1.java # 这是数据Model,即使数据记录对应的Java类,里面包含对应表的字段、注释及get和set方法
│   ├── Table1Example.java # MySQL查询相关的一些简单的语句拼接,针对每个字段都有几个常用的SQL语句拼接方法。比如等于、大于、小于等方法
│   ├── Table2.java
│   └── Table2Example.java
└── mapper
├── Table1Mapper.java
├── Table1Mapper.xml
├── Table2Mapper.java
├── Table2Mapper.xml
└── ext # MyBatis并不会默认生成,可以在这里编写自定义的查询方法
├── MyExtMapper.java
└── MyExtMapper.xml
阅读全文 »

每年的认知小结

人生

  • 当你老了,回顾一生,就会发觉:什么时候出国读书,什么时候决定做第一份职业,何时选定了对象而恋爱,什么时候结婚,其实都是命运的巨变。只是当时站在三岔路口,眼见风云千樯,你作出选择的那一日,在日记上,相当沉闷和平凡,当时还以为是生命中普通的一天。——陶杰《杀鹌鹑的少女》
  • 就算你觉得自己是一坨臭狗屎,也会遇到一个心地善良的屎壳郎,不远万里找到你,然后当成宝贝,再不远万里把你滚回家,一路上悉心呵护着你,怕你被抢了,被踩扁了,或者撞到石头,一心想着,把你变成家里的镇宅之宝,别怀疑,世界有时候就是这么好。
  • 曾经以为“老去”是很遥远的事情,突然发现“年轻”是很久以前的事了……时光,好不经用,抬眼,已然半生
  • 我尊重同性恋,我理解抑郁症,我会喂楼底下的流浪狗,会给老奶奶让座位,会对店员说谢谢……纵然,我平庸,长相普通,脾气不好,曾经悲伤难过望而不得,生活的苦也在吃,但我依然,想努力地成为一个温柔善良的人。——网易评论《借我》
  • 会做饭的男人又一个共同特点,那就是穷。
  • 废掉一个人最狠的方式,是让他忙到没时间成长——铭哥笔记
  • 人生短短急个球啊
  • 人者一辈子,走走瞧瞧,吃吃喝喝,不生病,就是夫妻,如果能遇到自己爱的也爱自己的人再发点小财,就是天大的福气。——摘自《不是因为寂寞才想你》王小帅
  • 少儿编程这玩意儿毫无意义,编程是工具,不是知识,送小孩去学编程等于送小孩去学说明书,急功近利也不是这么个急法。15岁之前只需要学数学和英语,前者是定义与解决,后者是表达与传播。其他学科本质上和冯唐诗集没什么区别。 ——微博 马茉莉
  • 我发现不能一下子挣个几百万的话,工资再高也没用,只有财务自由才可以安心
  • 最幸福的事,还有女孩子夜晚开着车,拉着那个为了未来奋斗而疲惫入睡的男孩子呀——抖音
  • 所有人都在要求内向的人多说话多社交走出舒适圈,这样说的话外向的人每天都活在舒适圈里,那让外向的人也走出舒适圈,少说电话少拉别人去聚会多独处多沉默ok吗——微博,高大威溜了溜了
  • 最幸福的事就是,你开着车,我坐在副驾驶,听着歌,吃着零食,跟你聊着未来,一起去找我们最想去的地方。
  • 最幸福的事莫过于两个男人一个开着车,另一个坐在副驾驶,一起抽着烟,讨论这去哪找最美技师。
  • 《小王子》说:仪式感就是使某一天与其他日子不同,使某一时刻与其他时刻不同。
  • 春有百花秋有月,夏有凉风冬有雪。若无闲事挂心头,便是人间好时节。
  • 其实我们很多人都无解了三观不合的意思,你喜欢吃西餐,我喜欢吃路边摊,这不是三观不合,但如果你喜欢吃喜欢我说你装,我喜欢吃路边摊你说我low,这才是三观不合——抖音

编程

  • 在同一个公司同一个职位上一旦错过了3-5年的跳槽黄金期,员工对安逸的需求大于上进求胜的欲望,随着年龄的增大、家庭琐事的负担,人的惰性将越来越束缚内心,最终沦为朝九晚五混日子的上班族。
  • 做得快不仅可以让你在单位时间内完成更多的工作,而且因为你工作得很快,所以你会觉得成本低,从而倾向于做更多。
  • 1万属性,100亿数据,每秒10万吞吐,架构如何设计?——Json格式存储不同的属性
  • 有些网站禁止未登录用户访问,但会对搜索引擎开绿灯。开绿灯的方式有可能只是简单地判断User-Agent。所以,只要把浏览器的User Agent改为搜索引擎的爬虫即可访问其内容。——微博tombkeeper
  • (微服务的)分布式事务没有最好的解决方案,甚至说没有比较简单的解决方案,所以,最好的方法是尽量避免分布式事务,具有强一致性要求的服务并不建议拆分到不同的服务中。这也是DDD(领域驱动设计)的思想

生活

  • 省一分钱真的比赚一分钱容易多了
  • 一个人可以捱穷,两个人就不行,因为会忍不住把自己的穷怪罪给他。——亦舒
  • 如果不能变得有钱,那就变得有趣吧
  • 在赚钱这件事上,谁转不到钱, 你就不要听他们的,包括你的父母兄弟姐妹,你身边这些最亲近的人,本质上他们说这些话,都是为你好,但他们的思维,会影响你去做一些超出他们认知的事,而这种影响会导致你跟他们过上一样的生活

安装

1
npm install pm2@latest -g

常用命令

  • 基本上能使用程序name的地方也可以使用id(id一般是从0开始的)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
pm2 start app.js	# 直接启动某个项目
pm2 start app.js --name my-app # 设置应用名称
pm2 start app.js --no-daemon # 以非daemon方式运行
pm2 start app.js --max-memory_restart 20M # 当内存超过20M时就重启应用
pm2 start npm --name my-app -- run start # npm run start方式启动
pm2 stop all # 停止所有程序
pm2 restart all # 重启所有程序
pm2 delete 0 # 删除某个进程
pm2 delete all # 删除所有进程

pm2 list # 列出所有使用pm2管理的程序
pm2 prettylist # 用json格式输出

pm2 describe 0 # 查看程序详情,比如日志文件位置,nodejs版本,开始时间,堆栈使用情况,延迟时间
pm2 show 0 # 同上
pm2 monit # 实时监听所有进程,和describe的输出差不多,不过这个是实时的,而且可以看到日志
pm2 monitor appname # 查看pm2管理的所有进城的详细状态
阅读全文 »