关于Mac使用Caps Lock键切换输入法有延迟问题的解决办法

我已经记不清是什么版本中加入了短按大写键实现输入法切换的功能了

当时系统更新以后,大写就不好用了,然后发现了这个功能

但是在开始加入秃头大军(程序猿)以后,发现在频繁的切换中英文切换的过程中,Caps Lock键总是掉链子,态度犹豫不决

用了快10年的Mac,想让我适应别的方法!那是不可能的,所以就开始在网上查询关于问题的解决办法

经过网上的浏览,再根据自己的一些经验,总结一下我自己使用的方法

事先声明

首先声明,这个办法是旁门左道,会丧失长按大写的功能

灵感来源于各位的 Macbook Pro 16 寸有遇到中英文切换不灵敏的问题吗?

中第14楼的typetraits网友的回复

下载&安装 Karabiner

首先在官方网站下载软件的安装包

目前网站已经支持了BigSur

软件开源,并且免费

在软件中受益可以对其进行捐赠

如何使用请参考我的另一篇文章

完美方案(自认为)

超市库存管理系统第一周周报

Web项目第一周周报

本周项目的前端部分由我负责,项目经过了几次重建,所以进度没有太快

开始

最开始使用element vue进行编辑,但是element对选择器的指定由于不觉,调试麻烦

第一次重建

后改用了Vue单页面文件,在编写完登陆模块发现使用vue单文件进行单页面局部刷新的web太不友好,开始尝试Vue cli

第二次重建

经过简单的学习,使用了Vue-cli的基本配置进行了项目搭建,采用了route+严格文档(最开始让我吃尽了苦头)

虽然使用了Vue-cli,但是没有合理的使用路由,项目过于臃肿,所以开始学习vue路由

第三次重建

学习了Vue路由后对项目进行了拆分,学会使用component,route文件配置的使用

但是开始一味的使用路由进行转发缺乏了vue基础的运用使项目调试一场困难

我开始注重Vue基础的学习,开始学习组件的概念

父子组件,组件的创建、声明、使用

然后新建了项目,对项目进行了迁移,优化

第四次重建

一直到现在,依然是在使用这个版本,又学习了vuex的创建,引用,修改

将一些频繁使用的固定值定义在store文件夹中

现在完成的内容

head 头部

账户未登陆

head-未登陆

账户登陆后

head-登陆后

登陆注册框的显示

登陆注册框的显示

登陆与注册框使用了路由规则跳转

在进入网页首页时,会自动跳转到注册页面

菜单及菜单(未完成)

菜单及登陆

Vue - Newline required at end of file but not found

遇到的问题

今天在写 Vue框架 的时候遇到了报错

1
error  Newline required at end of file but not found	eol-last

意思就是:错误文件末尾需要换行符,但未找到

Vue:Newline required at end of file but not found-1

解决方法

Vue:Newline required at end of file but not found-2

有人说html , css 的后面都得加,但是我没加也没报错

得过且过吧 QAQ

在出错的文件末尾添加一个空行就ok了

问题出在 eslint 格式校验的身上,终于知道为啥老手都不愿意开校验的原因了

但是规范一下自己的代码还是不错的

超市库存管理系统的程序设计

超市库存管理系统的程序设计

项目分析

权限等级

graph LR
subgraph 管理模块
    subgraph 人员管理
        addUser(增加店员)
        deleteUser(删除店员)
        selectUser(查询店员信息)
        updateUser(修改店员信息)
        setManager(更换店长)
    end
    subgraph 商品管理
        infoCommodity(商品信息)
        addCommodity(增加商品)
        deleteCommodity(删除商品)
        updateCommodity(修改商品)
    end
    subgraph 库存管理
        upperCommodity(商品入库)
        lowerCommodity(商品出库)
        infoStock(库存记录)
    end
end
subgraph 人员信息
        sales(销售)
        Manager(店长)
        treasury(库管)
        Boss(总经理)
    end
sales -.-> selectUser
sales -.-> updateUser
sales --> infoCommodity
Manager -.-> addUser
Manager --> deleteUser
Manager --> selectUser
Manager --> updateUser
Manager --> infoStock
treasury --> infoCommodity
treasury --> addCommodity
treasury --> updateCommodity
treasury --> deleteCommodity
treasury --> upperCommodity
treasury --> lowerCommodity
Boss --> setManager
Boss --> infoStock

表结构

  • 商品信息表 commodity info

    字段名 字段类型 备注
    c_id bigint 商品编号
    c_name varchar 商品名称
    c_typeid varchar 类型编号
    c_life date 保质期
    c_unit varchar 销售单位
    origin info varchar 产地信息
    customer telephone varchar 客服电话
  • 库存

    字段名 字段类型 备注
    s_id 商品编号
    store_id 店铺编号
    s_num 库存数量
    birth_date 生产日期
    past_date 过期日期
  • 职员信息表

    字段名 字段类型 备注
    u_id 职工编号
    u_name 职工姓名
    u_birth 出生日期
    u_jobId 职位编号
    u_locationId 工作地点
  • 职员结构

    字段名 字段类型 备注
    jobId 职位编号
    jobName 职位名称
    locationId 店址编号
    locationName 店址名称
  • 库存记录表

    字段名 字段类型 备注
    u_id 商品编号
    余量
    入库编号
    入库时间
    出库编号
    出库时间

模块设计

登陆模块

graph LR
client --> userPwd
subgraph send
    userName
    userPwd
    autoLogin
end
userPwd  --- server
server --> userId
subgraph receive
    errorcode
    userId
    userRights
end
userId --- client1

注册验证模块

graph LR
client --> userName
subgraph send
    userName
end
userName --> server
subgraph recive
    errorcode
end
server --> errorcode
errorcode --> client1

注册模块

graph LR
client --> userPwd
subgraph send
    userName
    userPwd
    userBirth
end
userPwd --> server
server --> userId
subgraph recive
    errorcode
    userId
end
userId --> client1

添加商品

graph LR
client --> commmodityLife
subgraph send
    commmodityName
    commmodityTypeId
    commmodityLife
    commmodityUnit
    commmodityTel
end

修改商品

删除商品

查询商品

出入库管理

商品入库

商品出库

查询商品数量

库存统计

查询出入库信息

JSP:动态网页编程技术

JSP : Java Server Page

与HTML的对比

HTML只能为用户提供静态的数据,而JSP技术允许在页面中嵌套代码,为用户提供动态数据

与Servlet的对比

Servlet很难对数据进行排版,而JSP除了可以用Java代码生产动态数据的同时,也很容易对数据进行排版

应该什么时候使用

所以人们逐渐把servlet作为web应用中的控制器组件来使用,而JSP技术作为数据显示模版来使用

JSP的执行

其实JSP就是一个Servlet,当我们访问JSP时,JSP引擎会将这个JSP翻译成一个Servlet,这个文件存放在Tomcat中的work目录中

各种技术与服务/客户端的交互

准备工作

配置IDEA

更改默认字符集

进入IDEA设置界面

IDEA进入设置界面

找到 编辑器 - File Encodings更改3个位置的字符集设置

截屏2020-11-30 下午7.18.55

JSP使用

1
2
3
4
5
6
7
8
9
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>Hello JSP!</h2>
</body>
</html>

JSP的页面与HTML非常相似

下面我们来说一下为什么JSP就是一个Servlet

我们把上面的语句用tomcat运行,当我们打开网页浏览以后,tomcat就会进行编译,并把文件存放在(鸽~)

JSP注释 三种

1
2
3
// 单行注释 /*多行注释*/
<!-- HTML风格 -->
<%-- JSP风格注释 --%>

显式注释

1
2
3
<!-- 	继承HTML风格
不在页面显示
但是能够在查看源码时显示 -->

能够在客户端查看的注释

隐式注释

不能在客户端查看的注释

JSP 的注释

1
<%-- JSP自己的注释 --%>

Java 的注释

1
2
// 单行注释
/* 多行注释 */

继承Java风格的注释,只在Java代码段中生效

HTML语句中不生效

Scriptlet脚本小程序

JSP中一共有三种脚本小程序

Java 脚本段 <% %>

1
2
3
4
5
6
<%
//Java代码
String str = "Hello ";
System.out.println(str); // ==>Hello
out.print(str); // 与上一行代码显示内容一致
%>

在JSP中,Java代码是相关联的

1
2
3
4
5
6
7
8
9
10
<%
//Java代码
String str = "Hello ";
System.out.println(str1); // ==>Hello
out.print(str); // ==>Hello
%>
<%
String str1 = "JSP!!";
out.print(str+str2); // ==>Hello JSP!!
%>

Java 声明 <%! %>

1
2
3
4
5
6
7
8
<%
// 因为num是全局变量,所以我们可以在前面引用
out.print("全局变量num="+num); // ==>全局变量num=10
%>
<%!
// 声明全局变量
int num = 10;
%>

Java 输出表达式 <%= %>

1
2
3
4
<%
int sum = 10;
%>
<%= sum %> //==>10

JSP的指令标签

使用包含标签,可以将一些重复的代码包含进来使用,从正常的页面组成来看,有时可能分为一个区域

而其中的一些区域可能是一直不需要改变的,改变的只是某一部分区域

两种方法可以实现上述功能

  1. 在每个JSP页面 HTML 都包含所有信息
  2. 将需要改变与不需要改变的部分,分成几个区域,使用的时候直接导入

第二种方法在页面刷新或更改时,只需要将相应的区域进行刷新就好

在JSP中想要实现包含操作有两种做法静态包含动态包含

静态包含使用include指令即可,动态包含则需要使用include动作标签

include静态包含

1
<%@include file="要包含的页面地址"%>
  • 例子
1
2
3
4
5
6
main.jsp
<body>
<%@include file="header.jsp"%>
<h2>我是主体内容</h2>
<%@include file="footer.jsp"%>
</body>
1
2
3
4
header.jsp
<body>
<h2>我是头部内容</h2>
</body>
1
2
3
4
footer.jsp
<body>
<h2>我是尾部内容</h2>
</body>
  • 效果

我是头部内容

我是主体内容

我是尾部内容

特点

静态包含是将内容直接替换,只会生成一个源码文件,最终内容全部都在_jspService方法中(呈现在源码文件中)

所以不能出现同名变量

运行效率高一点,但是耦合性高,不够灵活

graph TD
     subgraph 错误合并
         subgraph header.jsp
             c1(int a)
             end
         subgraph footer.jsp
             c2(int a)
             end
         subgraph main.jsp
             c3(int a)
             end
         c1-->c3
         c2-->c3
         end
         subgraph Servlet
            c4(main.java)
            end
         c3-.编译错误.->c4
         subgraph 合并
        a1(header.jsp)-->a2(main.jsp)
        a3(footer.jsp)-->a2
        end
        subgraph Servlet
            b1(main.java)
            end
    a2-.编译.->b1

include动态包含

1
<jsp:include page="要包含的页面地址"></jsp:include>

动态包含在代码编译阶段,包含被包含部分是两个独立的部分,只有当运行时,才会动态包含进来,类似方法的调用

page可以是表达式,下边的上下两条语句的效果是相同的

1
2
<% String url = "要包含的页面地址" %>
<jsp:include page="<%=url%>"></jsp:include>
  • 例子
1
2
3
4
5
6
main.jsp
<body>
<jsp:include page="header.jsp"></jsp:include>
<h2>我是主体内容</h2>
<jsp:include page="footer.jsp"></jsp:include>
</body>
1
2
3
4
header.jsp
<body>
<h2>我是头部内容</h2>
</body>
1
2
3
4
footer.jsp
<body>
<h2>我是尾部内容</h2>
</body>
  • 效果

我是头部内容

我是主体内容

我是尾部内容

特点

  • 动态包含相当于方法的调用

  • 会产生多个源码文件

  • 可以定义同名变量

  • 效率高,耦合度低

graph TD
        a2(footer.jsp)-.编译.->b2
        a3(main.jsp)-.编译.->b3
        a1(header.jsp)-.编译.->b1
    subgraph Servlet
        b1(header.java)-->b3(main.java)
        b2(footer.java)-->b3
        end

是否传参

不需要传参

当动态包含中不需要任何参数时,include双标签之间不要有任何内容,包括换行和空格

需要传参

1
2
3
<jsp:include page="要包含的页面地址">
<jsp:param name="参数名" value="参数值"/>
</jsp:include>

name不可以是表达式,但是value可以是表达式

例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
main.jsp
<body>
<h2>这里是main的内容</h2>
<jsp:include page="connect.jsp"></jsp:include>
<% // 定义一个变量
String str = "你好,我的名字叫";
String name = "张三。";
String greetings = (str+name);
%>
<jsp:include page="connect.jsp">
<jsp:param name="uname" value="张三"/>
<jsp:param name="msg" value="<%=greetings%>"/>
</jsp:include>
</body>
1
2
3
4
5
6
7
8
9
connect.jsp
<body>
<h2>这里是connect的内容</h2>
<%
String uname = request.getParameter("uname");
String msg = request.getParameter("msg");
out.print("姓名:"+uname+",消息:"+msg);
%>
</body>
效果

这里是main的内容

这里是connect的内容

姓名:null,消息:null

这里是connect的内容

姓名:张三,消息:你好,我的名字叫张三。

JSP的四大域对象

四种属性的范围

在JSP中提供了四种属性的保存范围,所谓的属性保存范围,指的就是一个设置的对象,可以在多少个页面中保存并可以继续使用

page范围

pageContext : 只在一个页面中保存属性,跳转之后无效

request范围

request : 只在一次请求中保存,服务器跳转后依然有效

session范围

session : 只在一次会话范围中,无论何种跳转都可以使用

application范围

application : 在整个服务器上保存

验证属性范围的特点

page

本页面取得,服务端跳转 jsp:forward 后失效

requset

服务器跳转有效,客户端(浏览器)跳转无效

如果是客户端跳转,则相当于发出了两次请求,那么第一次的请求将不存在了,如果希望不管是在客户端还是服务端跳转,都能保存的话,就得进一步扩大范围

session

无论客户端还是服务端都可以取得,但是在重新开始一个新的浏览器,则无法取得之前设置的session了,因为每一个session只能保存在当前的浏览器当中,并在相关的页面取得

对于服务器而言,每一个连接到他的客户端都是一个session

如果想要让属性设置一次之后,不管是否是新的浏览器打开都能取得则可以使用application

application

所有的 application 属性直接保存在服务器上,所有的用户(每一个session)都可以直接访问取得

只要是通过 application 设置的属性,则所有的 session 都可以取得,表示公共的内容,但是如果此时服务器重启了,则无法继续取得了,因为服务器关闭后,所有属性都消失,需要重新设置

应该使用那个范围

在合理的范围内,尽可能的缩小范围

如何指定在哪个域执行方法

1
域对象.方法();
方法 类型 描述
public void setAttribute (String name, Object o) 普通 设置属性的名称及内容
public Object getAttribute (String name) 普通 根据属性名称取属性
public void removeAttribute(String name) 普通 删除指定的属性

例如

1
2
3
pageContext.getAttribute("");
request.setAttribute("","");
session.romoveAttribute("");

JSP的两种跳转方式

服务端跳转 JSP方式

1
<jsp:forward page="要跳转的页面地址"></jsp:forward>

客户端跳转 超链接跳转

1
<a href="要跳转的页面地址">跳转</a>

EL表达式的使用

EL表达式的语法

EL(Expression Language)是为了使JSP写起来更加简单。表达式语言的灵感来自于ECMAScript和Xpath表达式语言,它提供了在JSP中简化表达式的方法,让JSP的代码更加简化。

1
${expression}

EL表达式一般操作的都是域对象的数据,操作不了局部变量

EL默认的查找方式是从小到大查询,找到即可。当域对象未找到则返回空字符串””

取指定的域对象的值

1
${域Scope.域名}
域对象 指定域对象 作用范围
page pageScope 当前页面
request requestScope 一次请求
session sessionScope 一次会话
application applicationScope 整个程序

获取List

1
2
3
4
<%-- 获取List中指定下标的数据 --%>
${域变量名[下标]}
<%-- 获取集合的长度 --%>
${域变量名.size()}

仅限域变量名使用

获取Map

1
2
${域变量名["key"]}
${域变量名.key}

以上两种方法都可以

仅限域变量名使用

获取JavaBean对象(封装)

1
2
3
4
5
${JavaBean对象名} <%-- 直接获取JavaBean对象 --%>

<%-- 获取JavaBean对象中的属性 --%>
${JavaBean对象名.JavaBean中属性名}
${JavaBean对象名.get属性名( )}

判断空 empty

1
2
3
4
5
6
7
8
${empty 限域变量名}
判断对象是否为空
如果为空返回true
如果不为空返回false
${empty !限域变量名}
判断对象是否不为空
如果不为空返回true
如果为空返回false
  • 为空的条件
字符串 List Map JavaBean
不存在的字符串 不存在的List 不存在的Map null
空字符串 “” 空List 空Map
null null

JavaBean的空对象不为空

EL运算

等值判断 ==

1
2
3
${限域变量名1 == 限域变量名2}
${限域变量名1 eq 限域变量名2}
${限域变量名1 == 数值或字符串}

上面两条语句效果一致

相等返回 true 不等返回 false

算数运算 +-*/ div

1
2
${a + b}
${a / b}或 ${a div b}
运算 运算符
加法 +
减法 -
乘法 *
除法 / div

大小比较

1
2
${a > b}
${a >= b}
比较 比较符
大于 >
小于 <
大于等于 >=
小于等于 <=

逻辑运算

1
2
${a > b && b < c} 与
${a > b || b < c} 或

JSTL:JSP的响应标签库

标签的使用

过滤器和监听器

过滤器

Filter即为过滤,用在 Servlet 之外对 Requset 或者 Response 进行修改。它主要用于对用户请求进行预处理,也可以对 HttpServletResponse 进行处理。

使用 Filter 的完整流程:

Filter 对用户请求进行预处理,接着将请求交给 Servlet 进行处理并生成相应,最后 Filter 再对服务器响应进行处理。

在一个 web 应用中,可以开发编写多个 Filter ,这些Filter组合起来称之为一个 Filter 链。

image-20201203221648480

image-20201203221924352

URL:统一资源定位符

什么是URL

网络中的某个资源的绝对路径

http://www.baidu.com 就是一个url

通过ping 我们发现xon.ink的物理IP为 61.135.169.121

因为地域和时间的不同IP可能会有变动

ping www.baidu.com 的IP

我们再来访问

http://www.baidu.com/index.html

http://61.135.169.121

http://61.135.169.121:80/index.html

http://61.135.169.121:80/index.html

访问以上网站我们可以发现,所显示的页面都是一样的

对此,我们来解释一下URL的字段意思

1
协议 // 地址 : 端口号 /资源地址

协议(请求头):我们访问使用的协议,一般为HTTP或HTTPS。当然也有FTP,SSH等非网页的协议

地址:可以是IP地址(61.135.169.121),也可以是网址( www.baidu.com ),当然我们访问的网址最终也会被DNS服务器解释为真实的IP地址,只是网址更容易被人们记住,并且当真实IP地址改变以后,开发者只需要更改DNS服务对真实IP的解释就可以实现新的映射,而不需要变动网址

端口号:我们想要访问的服务会在他所在的服务器上开放、并占用一个端口号,当我们访问这个服务器的指定端口时,就会自动被这个服务响应。访问这台服务器的其他端口则不会获得对应的响应。80 443是默认的HTTP/HTTPS协议端口号,所以当我们用HTTP/HTTPS协议访问时,会默认访问80,443端口

资源地址:index.html就是一个资源地址,他在网站根目录下,文件名字叫做index.html,所以他不需要任何中间路径就可以被访问到。至于为什么我不加index.html也可以访问到百度的官网,这是因为网站服务器会有一个默认的地址,如果我的URL地址中什么资源地址都不写,服务器就会将我们引导到一个开发者设置好的资源地址

JDBC中 注册驱动 指令的原理详解

第一种方法

1
DriverManager.registerDriver(new com.mysql.jdbc.Driver());

官方文档解析

在1.6的中文官方文档中可以查看 java.sql包中,有一个管理驱动的类

DriverManger(驱动管理器)

其内部有一个用于注册驱动的方法

registerDriver(Driver driver)

属性为 static void

这就是DriverManager.registerDriver的含义

但是在文档中可以看到Driver drvier是一个接口

而接口对应的实现类应该是数据库对应厂商写的

我们来查看mysql的驱动文件

MySQL驱动文件解析

在mysql的驱动源代码中

src/com/mysql/jdbc中就有Driver.java的文件

同样在Jar包下对应的

com/mysql/jdbc目录下也有Driver.class的文件

内部内容为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.mysql.jdbc;

import java.sql.SQLException;

/**
* Backwards compatibility to support apps that call <code>Class.forName("com.mysql.jdbc.Driver");</code>.
*/
public class Driver extends com.mysql.cj.jdbc.Driver {
public Driver() throws SQLException {
super();
}

static {
System.err.println("Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. "
+ "The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.");
}
}

com.mysql.cj.jdbc.Driver.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.mysql.cj.jdbc;

import java.sql.SQLException;

public class Driver extends NonRegisteringDriver implements java.sql.Driver {

static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}

public Driver() throws SQLException {
// Required for Class.forName().newInstance()
}
}

父类引用

1
2
3
import java.sql.Driver;
Driver driver = new com.mysql.jdbc.Driver(); //多态,父类型引用指向子类型对象
DriverManger.registDriver(driver);

第二种方法(推荐)

通过查看com.mysql.cj.jdbc.Driver.java文件,发现方法为static方法

所以我们可以通过Class方法快速引用

1
Class.forName(com.mysql.jdbc.Driver);

异常抛出

根据官方文档,registerDriver会抛出方法SQLException

registerDriver官方方法

1
2
3
4
5
6
try{
Driver driver = new com.mysql.jdbc.Driver();
DriverManger.registDriver(driver);
}catch(SQLException e){
e.printSrackTrace();
}

需要导入的包

1
2
3
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;

记录一下阿里云企业邮箱的协议地址以及端口号

今天想把自己的企业邮箱登陆在Mac自带的邮箱APP中,遇到了很多莫名其妙的错误,哪些内容我另开一篇写

直接贴上阿里云企业邮箱的POP3SMTPIMAP地址

协议 服务器地址 服务器端口号 常规 服务器端口号 SSL
POP3 pop.qiye.aliyun.com 110 995
IMAP imap.qiye.aliyun.com 143 993
SMTP smtp.qiye.aliyun.com 25 465

当然原先老的地址也可以使用

协议 服务器地址 服务器端口号 常规 服务器端口号 SSL
POP3 pop3.mxhichina.com 110 995
IMAP imap.mxhichina.com 143 993
SMTP smtp.mxhichina.com 25 465

另外先提两点

  1. 使用第三方客户端POP登陆时,一定要关闭一定时间后删除服务器副本的选项,这样一段时间以后,你就没法在你服务器里找到原先的邮件了,可以说这些客户端为了绑架客户真是不择手段

    截屏2020-11-28 下午3.33.15

    当然你也可以直接在网页登陆邮箱,设置里面开启禁止第三方客户端删除

    截屏2020-11-28 下午3.31.26

  2. 尽量使用阿里云提供的服务器地址,我通过CNAME解析的地址总会出现无法验证用户名和密码的问题

请我喝杯咖啡吧~

支付宝
微信