你要悄悄努力,然后惊艳所有人(技术总结)

之前写了一个项目,可以后台生成自动插件,用户在前端付完款,提交到后台,会自动生成他的私有化插件,整个过程无人操控,全自动化,也为我赚到了人生第一桶金,但是,这第一桶金也太少了,哈哈哈。

今天再来,回顾一下写过的东西:

怎么有些东西,刚开始写都觉得自己逻辑写的可棒了,怎么再过半年一看,简直没法看了。。

哎,我好垃圾。什么时候才能写出有质量的代码?

一、时间相关

1.1 关于mysql 时间字段的设定。

类型大小 (字节)范围格式用途
DATE31000-01-01~9999-12-31YYYY-MM-DD日期值
TIME3-838:59:59 ~838:59:59HH:MM:SS时间值或持续时间
YEAR11901~2155YYYY年份值
DATETIME81000-01-01 00:00:00~9999-12-31 23:59:59YYYY-MM-DD HH:MM:SS混合日期和时间值
TIMESTAMP41970-01-01 00:00:00~2037 年某时YYYY-MM-DD HH:MM:SS混合日期和时间值,时间戳

TIMESTAMPDATETIME除了存储字节和支持的范围不同外,还有一个最大的区别是:

  • DATETIME在存储日期数据时,按实际输入的格式存储,即输入什么就存储什么,与时区无关;
  • TIMESTAMP值的存储是以 UTC(世界标准时间)格式保存的,存储时对当前时区进行转换,检索时再转换回当前时区。即查询时,根据当前时区的不同,显示的时间值是不同的。

我们可以使用 DATE_FORMAT(date,format) 来格式化时间:

%a缩写星期名
%b缩写月名
%c月,数值
%D带有英文前缀的月中的天
%d月的天,数值(00-31)
%e月的天,数值(0-31)
%f微秒
%H小时 (00-23)
%h小时 (01-12)
%I小时 (01-12)
%i分钟,数值(00-59)
%j年的天 (001-366)
%k小时 (0-23)
%l小时 (1-12)
%M月名
%m月,数值(00-12)
%pAM 或 PM
%r时间,12-小时(hh:mm:ss AM 或 PM)
%S秒(00-59)
%s秒(00-59)
%T时间, 24-小时 (hh:mm:ss)
%U周 (00-53) 星期日是一周的第一天
%u周 (00-53) 星期一是一周的第一天
%V周 (01-53) 星期日是一周的第一天,与 %X 使用
%v周 (01-53) 星期一是一周的第一天,与 %x 使用
%W星期名
%w周的天 (0=星期日, 6=星期六)
%X年,其中的星期日是周的第一天,4 位,与 %V 使用
%x年,其中的星期一是周的第一天,4 位,与 %v 使用
%Y年,4 位
%y年,2 位

若字段使用了 dateTime(3),即时间精确到1毫秒,也就是0.001秒。

1.2 java中时间操作

在java中,我们对时间的转换如下:

jdk1.8之前,我们习惯这样格式化时间:

SimpleDateFormat sm =new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
String format = sm.format(new Date());
System.out.println(format);
// 获取时间戳
Long time = new Date().getTime();
Date date = new Date();
date.setTime(time);
SimpleDateFormat sm2 =new SimpleDateFormat("yyyy年MM月dd日");
// 时间戳格式化输出
String format2 = sm2.format(date);
System.out.println(format2);
// 格式化时间转为时间戳
Date parse = null;
try {
   parse = sm2.parse("2020年05月20日");
} catch (ParseException e) {
   e.printStackTrace();
}
System.out.println(parse.getTime());

运行完上述代码,会得到如下结果:
在这里插入图片描述
而在jdk1.8版本以后,为我们提供了新的方式。
更为详细的教程:javaTime

1.2.1 LocalTime

System.out.println("当前时间(毫秒):"+Instant.now().toEpochMilli());;
System.out.println("当前时间戳(秒)"+Instant.now().getEpochSecond());;

System.out.println("最大时间:"+LocalTime.MAX);
// 1200*5秒 即5点:05:00
System.out.println("一天起始秒数转化为对应时间:"+LocalTime.ofSecondOfDay(60*60*5));
//20:32:12.930
System.out.println("现在时间:"+LocalTime.now());
// 精确到纳秒  05:20:52.520
System.out.println("设定时间:"+LocalTime.of(5,20,52,520000000));

LocalTime parse = LocalTime.parse("05:20");
// 05:20
System.out.println("字符串时间格式化:"+parse);
// 若该时间大于现在返回 1 若小于当前时间返回-1
System.out.println("比较大小:"+parse.compareTo(LocalTime.now()));

1.2.2 LocalDate

LocalDate localDate = LocalDate.now();

// 2020-10-30
System.out.println("现在日期:"+localDate);
//  日期拼接时间
LocalDateTime localDateTime = localDate.atTime(LocalTime.now());
// 2020-10-30T20:32:12.929
System.out.println("日期拼接时间:"+localDateTime.toString());
// 生成日期:2020-05-20
System.out.println("生成日期:"+ LocalDate.of(2020,5,20));
// 生成日期:2020-05-20
System.out.println("生成日期:"+LocalDate.of(2020, Month.MAY,20));
// 一年的第几天的日期:2020-01-02
System.out.println("一年的第几天的日期:"+LocalDate.ofYearDay(2020,2));;
// (以计算从1970-01-01以后开始的给定天数) 时间戳转化:1970-01-02
System.out.println("时间戳转化:"+LocalDate.ofEpochDay(1));

// 格式化字符串日期
LocalDate localDateFormat = LocalDate.parse("2020 05 20", DateTimeFormatter.ofPattern("yyyy MM dd"));
// 2020-05-20
System.out.println("转换为LocalDate对象:"+localDateFormat);

// 2020年05月20日
System.out.println("日期格式化为指定格式:"+localDateFormat.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
// WEDNESDAY
System.out.println("这天是一周的第几天"+localDateFormat.getDayOfWeek());
// 3
System.out.println("这天是一周的第几天"+localDateFormat.getDayOfWeek().getValue());
// 20
System.out.println("这天是一月的第几天"+localDateFormat.getDayOfMonth());
//141
System.out.println("一年的第几天:"+localDateFormat.get(ChronoField.DAY_OF_YEAR));
// 5
System.out.println("一年的第几个月:"+localDateFormat.get(ChronoField.MONTH_OF_YEAR));
// 2020-05-21
System.out.println("这一天的后一天:"+localDateFormat.plusDays(1));
// 2021-05-20
System.out.println("这一天的后一年:"+localDateFormat.plusYears(1));
// 2020-05-15
System.out.println("这一天的五天前的日期:"+localDateFormat.minusDays(5));
// 2020-06-14 ChronoUnit 实现了TemporalUnit
System.out.println("这一天的往后推25天:"+localDateFormat.plus(25, ChronoUnit.DAYS));
// false  当前时间是:2020.10.30 所以是false
System.out.println("这天是否在现在在之后:"+localDateFormat.isAfter(LocalDate.now()));
// 先比较月份 再比较日期  返回相差月份或者相差天数
System.out.println("这天和现在比较大小:"+localDateFormat.compareTo(LocalDate.now()));
下一个周日
System.out.println(""+localDateFormat.with(nextOrSame(DayOfWeek.SUNDAY)));
// 该月最后一天
System.out.println(""+localDateFormat.with(lastDayOfMonth()));

1.2.3 LocalDateTime

// 23:59:59.999999999
LocalDateTime time = LocalDateTime.now();
// 2020-10-30T20:32:12.930
System.out.println("直接获取日期时间:"+time.toString());

Calendar instance = Calendar.getInstance();
//Calendar calendar = new GregorianCalendar();
// 2020
System.out.println("年份:"+instance.get(Calendar.YEAR));

DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss:SSS");

String format = dtf2.format(time);
// 2020年10月30日 22:17:402
System.out.println("格式化输出"+format);

// 和SimpleDateFormat相比,DateTimeFormatter是线程安全的
// 格式化时间转为 LocalDateTime 进一步可调用 
//toInstant方法 转为时间戳
LocalDateTime parse1 = LocalDateTime.parse("2020年05月20日 05:20:00:000", DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss:SSS"));
System.out.println(parse1);
// LocalDateTime 转换为 时间戳
System.out.println("时间戳:"+LocalDateTime.now().toInstant(ZoneOffset.ofHours(8)).toEpochMilli());

// 时间戳转化为LocalDateTime 格式化
Instant instant = Instant.ofEpochMilli(System.currentTimeMillis());
ZoneId zone = ZoneId.systemDefault();
LocalDateTime timeStamp = LocalDateTime.ofInstant(instant, zone);
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss:SSS");

System.out.println("时间戳格式化:"+dateTimeFormatter.format(timeStamp));

1.2.4 Date与LocalDateTime转换(常用)

下面这段代码摘抄来自:点此进入,方便引用,我复制过来了。

/**
  * LocalDateTime转毫秒时间戳
  * @param localDateTime LocalDateTime
  * @return 时间戳
  */
public static Long localDateTimeToTimestamp(LocalDateTime localDateTime) {
    try {
        ZoneId zoneId = ZoneId.systemDefault();
        Instant instant = localDateTime.atZone(zoneId).toInstant();
        return instant.toEpochMilli();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

/**
 * 时间戳转LocalDateTime
 * @param timestamp 时间戳
 * @return LocalDateTime
 */
public static LocalDateTime timestampToLocalDateTime(long timestamp) {
    try {
        Instant instant = Instant.ofEpochMilli(timestamp);
        ZoneId zone = ZoneId.systemDefault();
        return LocalDateTime.ofInstant(instant, zone);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

/**
 * Date转LocalDateTime
 * @param date Date
 * @return LocalDateTime
 */
public static LocalDateTime dateToLocalDateTime(Date date) {
    try {
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        return instant.atZone(zoneId).toLocalDateTime();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

/**
 * LocalDateTime转Date
 * @param localDateTime LocalDateTime
 * @return Date
 */
public static Date localDateTimeToDate(LocalDateTime localDateTime) {
    try {
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt = localDateTime.atZone(zoneId);
        return Date.from(zdt.toInstant());
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

1.2.5 计算两个日期相差的年份、月份、日期差值

LocalDate localDate = LocalDate.of(2018,5,20);
// 当前时间为:2020/10/30
Period between = Period.between(LocalDateTime.now().toLocalDate(),
   localDate);
// 天数相差10天所以 -10
System.out.println(between.getDays());
// 月份相差5天所以 -5
System.out.println(between.getMonths()); 
//  年份相差2年所以 -2
System.out.println(between.getYears());



1.2.6 计算两个时间所差的天数

LocalDate from = LocalDate.of(2017, 9, 1);
long day = LocalDate.now().toEpochDay() - from.toEpochDay();
System.out.println("距离当前多少日:" + day);


LocalDate date1 = LocalDate.of(2019, 10, 27);
//会改变date1
LocalDate date2 = date1.withMonth(9);//2019-09-27
System.out.println("修改日期原日期受影响:");
System.out.println("修改前:"+date1);
System.out.println("修改后:"+date2);

LocalDate date3 = LocalDate.of(2019, 10, 27);
//不会改变date3
LocalDate date4 = date1.with(TemporalAdjusters.firstDayOfMonth());

System.out.println("修改日期原日期不受影响:");
System.out.println("修改前:"+date3);
System.out.println("修改后:"+date4);

输出:
在这里插入图片描述

二、 int(4),int(11)的区别

首先,这两个所占的字节都为4个字节,最大的不同就是,int(4)在数字不足4位的时候,会左端补齐0,直到4个为止,而int(11)是补齐0到11个长度为止。
我刚开始很郁闷,为什么我设置了mysql也没有补齐呢?
最后才发现:定义字段需要添加:UNSIGNED ZEROFILL,
这样就会补齐了。如:

create TABLE exam_pay  (
 `id` int(11)  UNSIGNED ZEROFILL NOT NULL  AUTO_INCREMENT,
 `create_time` datetime(6) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
  ) ENGINE = MyISAM ;

接下来看看查询出来的id果然补0了。
在这里插入图片描述

三、 POST提交数据的方式

方式形式springboot接收
application/x-www-form-urlencodedaa=123&bb=456参数名字匹配即可
multipart/form-data常用于上传文件,会随机生成boundary值分割数据
application/json{“app”:“曼拉精灵”,“version”:“1.0.0”}@RequestBody注解即可,参数类型为JSONObject
text/xml

在爬虫或者使用其他HTTP请求库的时候,一定得指定你post的类型。最常用的就是application/x-www-form-urlencodedapplication/json,而默认post类型则为:application/x-www-form-urlencoded

四、 springData Jpa 小坑

如下,在创建实体类的时候,一般我们不使用columnDefinition属性的时候就没必要指定属性映射字段类型,如果使用了columnDefinition使用comment指定了字段注释,那么需要添加字段类型,即下面的varchar(20),不然在程序启动的时候会报错!建表失败,可怜我还找了好久…还是基础不扎实。。

 @Column(nullable = false,columnDefinition = "varchar(20) comment '账户名' ")
 private String username;

 // 用户密码
 @JsonIgnore
 @Column(nullable = false,columnDefinition = "varchar(20)  comment '账户密码'")
 private String password;

五、关于参数的场景校验

场景一
在用户登录的时候,需要两个基础参数,用户名、密码。
场景二
在用户注册的时候,需要三个基础参数,用户名、密码、确认密码。
而在这两种场景下,我们不可能建立两个实体类吧!
所以这就出现了Hibernate为我们提供的参数场景校验,真的太强大了。
看下文:
首先,我们建立一个分组器,相当于,场景分离:
千万不要被我说的这个概念吓到…我就是随口一说,其实很简单。

package com.cri.miaosuyun.web.validator;

/**
 * @description:
 * @author: raven
 * @create: 2020-10-28 16:02
 **/
public class UserAccountValid {
   // 登陆需要
    public interface login{}
	// 注册需要
    public interface register {}
}

对,没错,场景分离器我们已经建立好了,上面的两个属性,很清楚了每个接口(相当于标记)的场景。

接下来 我们需要建立实体类,并在每个属性上面使用```groups ``属性标注场景接口:

package com.cri.miaosuyun.web.model.Vo;

import com.cri.miaosuyun.web.validator.UserAccountValid;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import javax.validation.constraints.NotNull;

/**
 * @description:
 * @author: raven
 * @create: 2020-10-28 20:14
 **/
@Data
public class ViewUser {
    // 用户名
    @NotNull(message = "账户名不能为空!",groups = {UserAccountValid.login.class,
            UserAccountValid.register.class,
            UserAccountValid.proxyAddLower.class})
    @ApiModelProperty(value = "用户账号",required = true)
    private String username;

    @NotNull(message = "密码不能为空!",groups = {UserAccountValid.login.class,
            UserAccountValid.register.class,
          } )
    @ApiModelProperty(value = "用户密码",required = true)
    private String password;

    @NotNull(message = "确认密码不能为空!",groups = 
            UserAccountValid.register.class,
            })
    @ApiModelProperty(hidden = true)
    private String password2;
}

可以看到:
username(用户名) 我使用了两个场景接口。

groups = {UserAccountValid.login.class,
            UserAccountValid.register.class,
           }

即就是,登陆和注册都需要这个参数。

password(用户名) 也使用了两个场景接口。

groups = {UserAccountValid.login.class,
            UserAccountValid.register.class,
          }

即就是,登陆和注册都需要这个参数。
而看看确认密码属性:
只使用了一个注册场景接口,即就是注册用户的时候,才检测这个属性是否满足条件

groups = { UserAccountValid.register.class}

接下来,看看API:

@PostMapping("/register")
private Result<Object> registerUserAccount(
@Validated({UserAccountValid.register.class})ViewUser viewUser){}
                                                               
@PostMapping("/login")
private Result<UserAccount> Login(@Validated({
UserAccountValid.login.class}) ViewUser viewUser){}

接下来,捕获异常,使用@ControllerAdvice解决全局异常即可!

传递实体类到前端时,不想传入某属性,请使用:@JsonIgnore
实体类属性不想映射到数据表字段时,请使用:@Transient

六、kotlin 中线程如何调用协程语句?

没学过kotlin,因为QQ机器人需要使用这个框架,可太难受了,搞了半天都不知道,主要是Kotlin资料太少了。最后在群里大佬的解答才知道。
使用runBlocking块,即把协程语句放入runBlocking。

runBlocking{
  qqSubject.sendMessage("您的线上考试已经完成,成绩100分")
}

kotlin 遍历数组:

// 相当于java的static
 companion object{
        val examList = JSONArray()
   }
for ((index,e) in examList.withIndex()){
	println("${index}---${e}")
}

七、 python使用requests下载图片

image_verity = self.session.get(url_config['imageUrl']).content
# 生成随机图片名字
img_name = ''.join(random.sample(string.ascii_letters + string.digits, 5)) 
img_path = ('../img/%s.png' % img_name)
with open(img_path, 'wb') as f:
	f.write(image_verity)
	f.flush()
	f.close()

不得不说的是,在爬虫 这方面java真的太不行了。太罗嗦了,还是python舒服。
使用BeautifulSoup4解析文本:

 post_login = BeautifulSoup(
                self.session.post(url=url_config['url'],
                 data=login_param, headers=self.headers).text,
                'html.parser')
self.user_info['name'] = post_login.find(attrs={"id": 'xhxm'}).text

八、selinium阻塞直到某结点出来继续执行

在使用自动化测试的时候,某些节点可能渲染的比较迟,代码继续进行要操作该节点,例如等待浏览器渲染好某个按钮,我们才去点击它。如下代码,阻塞,直到页面出现元素类型为input,类型为text,类为input-txt才往下执行。

  WebDriverWait(browser, 8, 0.5, ignored_exceptions=TimeoutException).until(
            lambda x: x.find_element_by_css_selector("input[type='text'].input-txt"))
  print('hello world!')
  # 寻找输入框
  usernameInput = browser.find_element_by_css_selector("input[type='text'].input-txt")
  # 输入值
  usernameInput.send_keys('hello')
  # 模拟点击按钮
  browser.find_element_by_css_selector("div.checkbox__mark").click()
  # 执行js返回给py
  browser.execute_script('return sessionStorage.getItem("sessionId");')

有时间决定去了解了解:Puppeteer,谷歌的亲儿子,也挺强的。

九、 实战微信小程序

建议开发微信小程序,先学习以下VUE,效果更佳。官方文档

app.json 里的pages,第一个默认即小程序启动默认页面。在这里直接可以创建新的页面或者组件。

"pages":[
    "pages/index/index",
    "pages/select/score/score",
    "pages/table/table",
    "pages/logs/logs",
    "pages/center/center",
    "pages/login/login"
  ]

注意各个阶段的生命周期:
created 组件实例化,但节点树还未导入,因此这时不能用setData
attached 节点树完成,可以用setData渲染节点,但无法操作节点

 attached: function (options) {
    console.log('进来')
    //success 使用 箭头函数或者that
    //var that = this;
    wx.getStorage({
      key: 'score',
      success: (res)=> {
        console.log('ok')
        //被坑惨了 that...
        this.setData({
          score:res.data
        })
      },
    })
  }

这里要注意,使用this特别容易犯的错误,刚开始一直赋值不了数据,甚至让我毫无办法,后面才知道疏忽了。要知道,箭头函数是没有this指针的,所有这里面要么用that记录this,或者使用箭头函数。

// 跳转页面
  wx.navigateTo({
            url: '/pages/table/table',
          })
 //设置本地缓存
  wx.setStorage({ 
      key: "score",
         data: res.data.data
  })
  //模态框
   wx.showModal({
      title: '温馨提示',
        content: '服务器异常,请稍后再试',
        showCancel: false
  })

十、常用正则提取文本

待完善

十一、 java 发起各种HTTP请求

11.1 http篇

11.1 https篇

待完善

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值