Leetao's Blog

Talk is cheap, show me the code

0%

导言

这是原本计划在四月读的第一本书,最后拖延到五一假期的第四天才把它读完,这是今年的第5本书。

个人感想

老实说,这本书我不怎么喜欢,从读小说的开篇的故事开始就不喜欢。可能故事的男主人公的是外国人,其性格特点和我大相径庭吧,他和故事的女主在一次飞机上邂逅,按照他的意思来说,就立马坠入了爱河。他的爱情就如同杰伦的歌词那样,“爱情来的太快就像龙卷风”。龙卷风来的快,去的也快,他也一样,像所有刚恋爱的人的一样,他和女主度过了几个月的甜蜜时光,然后冲突开始产生、升级接着分道扬镳,然后分手后过渡期的一系列消极行为到末尾的醒悟。冷静之后,将整段情感经历写下来进行辩证性的思考

可能最让我觉得不喜欢的就是对感情进行理性的思考吧。本来感情就不是理性的产物,不然也不会有情不知所起,一往而深。什么东西都去追根究底,感觉生活中就会少了很多乐趣。

推荐指数

三颗星

内容简介

这是一部逼使理性与感性、细腻生动的恋爱过程全记录。

其间,才子德波顿细述一段情缘中的邂逅、迷恋、平凡中的幸福、熟悉后的倦怠、女友移情别恋、挽回无望、自杀、醒悟,以至一段情完全成为过去。他认真思辩自己的感觉,忠实记下与女友交往中的各个细节,特别是心理和哲学层面的思考,文字生动、处处机锋,不仅有极大的阅读乐趣,阅毕更令人回味无穷。

来吧,想爱、正在爱、曾经爱过的读者诸君,来看看“我”谈的那场恋爱是怎么回事。

英伦才子阿兰·德波顿,一位不乏米兰·昆德拉的批评深度,深具罗兰·巴特尔的解构气质;但,比昆德拉有更立体的爱情思维,比巴特尔更熨贴恋人的爱情神经,激活人们全新的阅读体验。 本书是一部融合理性与感性,细腻生动的恋爱过程的全记录。忠实记下与女友交往中的各个细节,特别是心理和哲学层面的思考 ,文字生动,处处机锋,不仅有极大的阅读乐趣,阅毕更令人回味无穷。

摘录

  1. 在我看来,她对情人的看法可比作是紧身的套装,而我认为真实的自我却很肥胖,所以,那整个晚上似乎都是一个胖男人在努力想让一套太小的衣服显得合身。我得拼命把多余的赘肉塞进不合身的衣服里,紧缩腰身,屏住呼吸,防止衣料撕裂。如果我的动作不如往常反应自如,那么一点都不奇怪,一个被过瘦衣服缠身的胖男人如何能反应自如?他太害怕衣服裂开,不得不一动不动地坐在那儿,屏住呼吸,祷告上天保佑这个夜晚不出大祸,平安度过。爱情已让我瘫痪。

  2. 但是为了被爱而说谎,则包含了更有违常情的假设:如果我不说谎,我就不会被爱。这是一种态度,认为要富有魅力就得消除所有个性(因此也可能会事与愿违),认为真正的自我不可避免地会与心上人的完美发生冲突(因而配不上心上人的完美)。

  3. 吸引是一种表演行为,是从自发的行为向符合观众要求的行为的转变。

  4. 目标的实现,往往是因为偶然性,而非来自事先算计。

  5. 只有当人们知道自己是另一个人的所爱时,才会既欣喜若狂又惊恐不安。如果完全没有认识到自己值得爱恋,那么接受他人爱情时的感受,与被授予了巨大的荣誉却不知这荣誉的凭借没什么两样。

  6. 在绝大多数的男女关系中,通常都会有马克斯主义的思维(当爱明显得到回应时),这种思维的解决得借助自我喜爱和自我痛恨之间的平衡。如果自我痛恨占了上风,那么接受爱的一方就会断言心上人(有各种各样的理由)不适合自己(因为和坏东西有了联系);如果自我喜爱占了上风,那么双方都会接受这样一种看法:爱得到回应不是因为心上人低贱,而是自己原本值得爱恋。

  7. 爱情是一个孤独的追求,爱情至多只能为另一个人——被爱的人——所理解。

  8. 两个人越是熟悉,他们在一起使用的语言就越会脱离常用的、词典里的释义。熟悉会创造出一种全新的语言,一种亲密的室内语,有关他们共同的故事,不易为他人理解。这语言凝结了他们共同的经历,包含了关系进展的过程,使得与心上人谈话有异于跟他人交谈。

  9. 我们只注意到感情在继续,却没有意识到在我们的关系中并没有什么是不可以破坏的。

  10. 我们想验证彼此忍受的限度:只有当我们徒劳地尝试过摧毁对方,我们才知道自己是安全的。

  11. 人生气的时候是一个复杂的动物,发出极度矛盾的信息,哀求着救助与关注,然而当这一切到来时,却又拒绝,希望无须言语就可以得到理解。

前言

重新安装了 Docker,然后启动其中的 MySQL 镜像,通过 pymysql 去连接数据库,出现了下面错误:

cryptography is required for sha256_password or caching_sha2_password

解决方法1

解决方法其实很简答,安装 cryptography 这个库就可以解决问题了。

1
pip install cryptography

出现问题的原因

但是为什么会出现这个问题呢?然后查阅了一下 MySQL 的相关资料发现,MySQL8.0会默认使用caching_sha2_password作为身份验证插件,这个也就是导致出错的原因。这就意味着,我们也可以通过关闭 caching_sha2_password 这个插件解决问题。

解决方法2

在MySQL8.0前采用的是 mysql_native_password 认证方式,修改步骤如下:

1
2
3
4
$ mysql -u root -p
>use mysql; 选择数据库(这一步不可省略)
>select host, user, plugin from user; // 查看plugin设置
>ALTER USER root@localhost IDENTIFIED WITH mysql_native_password BY 'xxxxx'; // 将 root 用户的认证方式修改为 mysql_native_password

前言

Flutter 在桌面软件端还需要走很长的路~跨平台支持的通用插件是在是太少了…

问题列表

1.

1
2
3
4
ProcessException: Process exited abnormally:
xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer
directory '/Library/Developer/CommandLineTools' is a command line tools instance
Command: /usr/bin/xcodebuild -list -project Runner.xcodeproj

解决办法

打开命令行,再命令行输出以下命令:

1
2
xcode-select --install # 如果没有安装 Command Line Tools 的,需要执行这条命令
sudo xcode-select --switch /Library/Developer/CommandLineTools # 启动 Command Line Tools

可能会出现warning信息,可以忽略。如果你安装了 Xcode 的话,可以再执行下面的命令:

1
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer # 后面是 Xcode 的路径,默认路径是这个

2.

1
The argument type 'MyState' can't be assigned to the parameter type 'TickerProvider'.

解决办法

在State类的末尾添加 with TickerProviderStateMixin

1
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin{}

这段时间在写稿子之余,为了让自己能够偶尔放松一下,决定将之前的博客更新一番。

更新

  1. 更新主页的UI
  2. 更新了文章详情页的UI
  3. 移除了原来的时间轴,由归档替换了
  4. 更新了标签页
  5. 更新了原本的管理页面的主页
  6. 为文章增加了可以上传封面的选项
  7. 使用bootstrap4替换了原本的bootstrap4
  8. 使用了 font-awesome作为图标库

下个版本计划

下个版本希望可以完成:

  1. 自动备份文章
  2. 自动升级,一键升级

在书稿没有完成之前,是不可能更新的。天天写稿子,感觉自己头发都快秃了。

写一本书难,写一本好书更难,写一本读者喜欢的书更是难上加难。同类的书已经有好几本了,写的也挺详实的,不过还是喜欢能写出一点新的东西来,还是希望到时候读者能够从我这里获取一点不一样的东西。

吐槽完了,接着去干活了。白天干活,晚上赶稿子~~~

前言

在实际开发过程中,经常需要对前端传来的数据模型进行校验,一般情况下都是写一个专门的校验函数去校验,这种方式很显然不适合复杂的项目,因为随着项目复杂度的增加需要校验的数据模型越来越多,并且在开发过程中可能也需要时常修改数据模型,这就导致原来的校验方法可能需要时常的变动,也不利于维护。因为我们需要一种更简单的方式去完成这个工作。

@Valid 和 BindingResult

SpringBoot 在内部通过集成 hibernate-validation 已经实现了JSR-349验证规范接口,在SpringBoot项目中只要直接使用就行了。接下来通过一个简单的例子完整的介绍使用方法

Example

以注册用户为例

定义 Bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class User{
@NotBlank(message="手机号不能为空")
private String phone;
@NotBlank(message="手机号不能为空")
private String password;

public void setPhone(String phone) {
this.phone = phone;
}

public void setPassword(String password) {
this.password = password;
}

public String getPhone() {
return phone;
}

public String getPassword() {
return password;
}
}

定义 Controller

在 controller 类里面对相应的接口添加 @Valid,BindingResult 验证,如果检验失败,则获取错误信息返回前台

1
2
3
4
5
6
7
8
9
10
11
12
@RestController
@RequestMapping(value = "/user")
public class UserController {
@PostMapping(value = "/register")
public User login(@RequstBody @Valid User userInfo, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
System.out.print(bindingResult.getFieldError().getDefaultMessage());
return null;
}
return userInfo;
}
}

总结

上面给出了常用的处理方法,在实际开发过程中,通常为了返回数据格式的统一,可能会全局捕获异常,然后统一返回,这个时候上述 Controller 中的 BindResult 和 if 判断语句就可以省略了,然后在全局中捕获

参考

Java SpringBoot上的参数校验JSR 303 Validation

前言

最近一直在研究用 py2app 给自己写的 PyQt5 应用打包应用,在打包过程中遇到了一次问题,写在这里备忘一下。

问题

问题一 AttributeError: module ‘string’ has no attribute ‘maketrans’

这个问题从网上查找了一下发现好像是 PyQt 的问题,但是到现在也没有被修复。

解决方法:修复起来也很简单,由于出问题的地方在 ascii_upper.py 文件中,找到这个文件,将 string 改成 str 然后保存就可以了

问题二 打包后的应用一直出现 Segmentation fault: 11 错误

出现这个问题的可能性有很多种,我一开始怀疑是 PyQt5 和 py2app 的问题,后来我尝试写了一个 PyQt5 最小应用,然后成功打包完美运行,自然这个猜测就被排除再外了。最后通过引用的库进行排查,成功的定位到错误了,原因出在我用的 aiohttp 库,去github上找了一下发现 pyinstaller cannot import aiohttp 这个 issue,最后无奈之下只好把用到 aiohttp 的部分用 requests 重写了,然后打包成功.

参考

py2app : AttributeError: module ‘string’ has no attribute ‘maketrans’

给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

示例 1:

1
2
3
4
5
给定 nums = [3,2,2,3], val = 3,

函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。

你不需要考虑数组中超出新长度后面的元素。

示例 2:

1
2
3
4
5
6
7
给定 nums = [0,1,2,2,3,0,4,2], val = 2,

函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。

注意这五个元素可为任意顺序。

你不需要考虑数组中超出新长度后面的元素。

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

1
2
3
4
5
6
7
8
// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝
int len = removeElement(nums, val);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。
for (int i = 0; i < len; i++) {
    print(nums[i]);
}

思路

通过一个变量统计符合添加的值的个数,并替换

解法

Rust

1
2
3
4
5
6
7
8
9
10
11
12
13

impl Solution {
    pub fn remove_element(nums: &mut Vec<i32>, val: i32) -> i32 {
       let mut k : usize = 0;
       for i in 0..nums.len() {
           if nums[i] != val {
               nums[k] = nums[i];
               k += 1;
           }
       }
       return k as i32;
    }
}

前言

最近在使用 Spring Boot@PathVariable 碰见一个有趣的问题, @PathVariable 默认一般情况下匹配字符串都是十分正常的,一旦遇到带有 .后缀 的 字符串就会出现将 .后缀 丢失的问题。举个例子,当我们使用 @PathVariable 去匹配 a.b.c.d 的时候,匹配的结果为 a.b.c

1
2
3
4
5
6
@ApiOperation(value = "pathvariable 匹配测试", notes = "pathvariable 匹配测试")
@GetMapping("/pathvariable/test/{test}")
public ResponseSo getNetWorkElements(@PathVariable("test") String test) {
// 当 匹配为 a.b.c.d
// 匹配结果为 a.b.c
}

原因

为什么会出现这种问题呢?早期 Spring Boot 是能够做到完整匹配的,但是这种全匹配会导致一些使用文件拓展名的 Restful URLs 出现异常,具体内容可以参考 ReSTful URLs with content type extension do not work properly [SPR-5537]。然后在后续的更新中,会默认截断最后的所谓的文件拓展 .后缀。这个截断的代码我们可以在代码的修改 commits c178888

解决办法

  1. 修改匹配的表达式
1
@GetMapping("/pathvariable/test/{test:.+}")

注意:使用这个方法,在后续匹配类似 xx.txt 等问题,会出现 406 错误,建议使用第二种(未测试)或者第三种方法

  1. 修改默认配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Configuration
public class PolRepWebConfig extends WebMvcConfigurationSupport {

@Override
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
final RequestMappingHandlerMapping handlerMapping = super
.requestMappingHandlerMapping();
// disable the truncation after .
handlerMapping.setUseSuffixPatternMatch(false);
// disable the truncation after ;
handlerMapping.setRemoveSemicolonContent(false);
return handlerMapping;
}
}
  1. 修改 ContentNegotiationConfigurer 配置
1
2
3
4
5
6
7
8
9
10
11
12
13
@SpringBootApplication
public class Application extends WebMvcConfigurerAdapter {

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

@Override
public void configureContentNegotiation(
ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false);
}
}

参考链接

Spring MVC @PathVariable getting truncated

spring requestmapping http error 406 on file extension

前言

由于需求,最近需要使用 RestTemplate 去请求 https 的 url,在没有任何设置下会出现:

1
java.security.cert.CertificateEeception:No subject alternative names matching IP address xxx found

解决方案

从网上找了几种解决方法,最后使用下面一段代码解决了问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import javax.net.ssl.SSLContext;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;

public RestTemplate restTemplate() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
TrustStrategy acceptingTrustStrategy = (X509Certificate[] x509Certificates, String s) ->true;
SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier());
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(csf).build();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
RestTemplate restTemplate = new RestTemplate(requestFactory);
return restTemplate;
}