学吧,学无止境,太深了
- 其他知识点
- 导出文件
- 换页、换行、回车、TAB 制表符
- VO和DTO
- MySQL截取字符串函数
- SQL注入 (${ }和#{ } )
- 回滚
- 建表规避字段
- 注解释义
- 将List根据公共字段转成Map
- new 和 =
- 异步执行
- MYSQL count(*) 和 count(列名) 的区别
- 联合索引
- equals()方法的四大原则
- java1.8新特性removeIf & lambda表达式处理简化
- 注册拦截器InterceptorConfig
- 端口占用
- PG库创建序列实现主键自增
- PG库空间函数计算失效
- 又是一个小细节
其他知识点
双亲委派机制
https://blog.csdn.net/u013568373/article/details/93995246
“一言概之,双亲委派模型,其实就是一种类加载器的层次关系。”
JDK
JDK是个Java开发的工具包
JDK8或者JDK1.8是由于自从JDK1.5/JDK5命名方式改变后遗留的新旧命令方式问题。所以JDK8或者JDK1.8也是同一个东西。
JAVA就是指JDK开发工具,所以我们可以理解为JAVA等价于JDK。JAVA有3个版本:J2SE J2EE J2ME,而J2SE是标准版本,J2ME是手机方向的,J2EE是网站开发方向的。
判断数据类型
xx instanceof xx
导出文件
或
@PostMapping("/imp111ort")
@ApiOperation(value = "导入111", httpMethod = "POST", response = Result.class)
public void exportExl() {
HttpServletResponse response = RequestContextUtil.getResponse();
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
try {
response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode("fileName", "UTF-8") + ".xlsx");
换页、换行、回车、TAB 制表符
VO和DTO
VO传给前端的
DTO是从前端拿过来的
MySQL截取字符串函数
-
left(str,length) 从左边截取length
-
right(str,length)从右边截取length
-
substring(str,index)当index>0从左边开始截取直到结束 当index<0从右边开始截取直到结束 当index=0返回空
-
substring(str,index,len) 截取str,从index开始,截取len长度
-
substring_index(str,delim,count),str是要截取的字符串,delim是截取的字段 count是从哪里开始截取(为0则是左边第0个开始,1为左边开始第一个选取左边的,-1从右边第一个开始选取右边的
-
subdate(date,day)截取时间,时间减去后面的day
-
subtime(expr1,expr2) 时分秒expr1-expr2
SQL注入 (${ }和#{ } )
${ } 中因为用了变量,可能出现SQL注入
#{ } 会把有可能的注入变成字符串加一层引号
但是如果整体SQL语句都是变量那就不能用#{}防止SQL注入了,因为加了引号,要用一个正则方法判断一下是否有注入的危险。
回滚
@Transactional(rollbackFor = Exception.class)
如果数据库的操作(保存,更新,删除)要对多个表进行操作。(假如,一个医生表添加了一个人,医院表相应的人数也加一)加上这个事务让操作变成原子性(要么都成功,要么都失败)这个时候就要加回滚,保证失败的时候;另一个也要回到失败的状态。
建表规避字段
DESCRIBE、RANGE
注解释义
@Deprecated
使用@Deprecated
表示这个类或者方法没在使用了
@TableLogic
自动补值默认逻辑删除isDeleted(0-未删除,1-已删除)
@TableField(exist = false)
标识这个字段不是数据库表中的字段
@Accessors(chain = true)
生成setter方法返回this(也就是返回的是对象),代替了默认的返回void。
@RequestParam、@RequestBody和@ModelAttribute区别
当前台界面使用GET或POST方式提交数据时,数据编码格式由请求头的ContentType指定。分为以下几种情况:
\1. application/x-www-form-urlencoded,这种情况的数据@RequestParam、@ModelAttribute可以处理,@RequestBody也可以处理。
\2. multipart/form-data,@RequestBody不能处理这种格式的数据。(form表单里面有文件上传时,必须要指定enctype属性值为multipart/form-data,意思是以二进制流的形式传输文件。)
\3. application/json、application/xml等格式的数据,必须使用@RequestBody来处理。
将List根据公共字段转成Map
Map<String, List<HbbPublicVo>> collect = hbbPublicVos.stream().collect(Collectors.groupingBy(HbbPublicVo::getHbbType));
new 和 =
首先基本类型不会被回收
new的时候是先开辟一块空间,该空间地址和变量对应。如果后续对变量进行赋值,例如 = 就会有一个新的有值的空间地址和变量对应,之前的空间就没人指向他了。
例如:
Integer numb = 0;
numb = list.size();
//此时numb = 0 就没有意义了,因为后面赋值了。
异步执行
CompletableFuture.runAsync(() ->{});
MYSQL count(*) 和 count(列名) 的区别
count(*)会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行。
联合索引
联合索引 A,B,C三个字段 如果是唯一索引
那么A可以走索引但不是唯一,AB也可以走索引但是不唯一。
equals()方法的四大原则
对称性:
如果 x.equals(y)返回true,则y.equals(x)也必须返回true。
自反性:
x.equals(x)必须返回true。
传递性
如果 x.equals(y)返回true,而且y.equals(z)返回true,那么z.equals(x)也是返回true。
一致性
如果 x.equals(y)返回true,只要x和y内容一直不变,不管里重复多少次比较,都会返回true。
任何情况下x.equals(null),都会返回false。
java1.8新特性removeIf & lambda表达式处理简化
//简化前
for (int i = 0; i < geoms.size(); i++) {
if (geoms.get(i).startsWith("POLYGON")) {
//wkt转成polygon
Polygon polygon = (Polygon) reader.read(geoms.get(i));
geoms.remove(geoms.get(i));
Polygon[] polys = new Polygon[1];
polys[0] = polygon;
//polygon转成MultiPolygon
multiPolygons.add(gf.createMultiPolygon(polys));
i--;
}else{
multiPolygons.add((MultiPolygon) reader.read(geoms.get(i)));
}
}
//简化后
geoms.removeIf(next -> {
boolean b = next.startsWith("POLYGON");
try {
multiPolygons.add(b ? gf.createMultiPolygon(new Polygon[]{(Polygon) reader.read(next)}) : (MultiPolygon) reader.read(next));
} catch (ParseException e) {
e.printStackTrace();
}
return b;
});
注册拦截器InterceptorConfig
/**
* 注册拦截器,暂放于此
*
* @author yyh
* @since 2021-03-26
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
/**
* springboot 拦截器无法注入bean,故添加此配置
* 拦截器加载的时间点在springcontext之前,所以在拦截器中注入自然为null
* @return
*/
@Bean
public AuthInterceptor getMyInterceptor(){
return new AuthInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册权限校验拦截器
registry.addInterceptor(getMyInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/user/login/**","/user/logout", "/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**", "/doc.html/**");
}
}
/**
* <p>
* 权限校验拦截
* <p/>
*
* @author yyh
* @since 2021-05-17
*/
@Component
public class AuthInterceptor extends HandlerInterceptorAdapter {
@Resource
private RedisCacheUtil redisCacheUtil;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("token");
//测试使用
if ("123456".equals(token)) {
return true;
}
//判断token是否为空
if (token != null && !"".equals(token)) {
//判断token是否存在
if (redisCacheUtil.hasKey(token)) {
//存在,重新设置失效时间
redisCacheUtil.expire(token,120, TimeUnit.MINUTES);
return true;
} else {
throw new TokenInvalidException("token失效");
}
} else {
throw new TokenDefectException("未携带token");
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
}
}
端口占用
# 列出所有端口占用情况
netstat -ano
# 精确找到被占用的端口对应的PID
netstat -ano|findstr "port"
# 示例
netstat -ano|findstr "6644"
#查看是哪个进程或程序占用了端口
tasklist|findstr "PID"
# 示例
tasklist|findstr "4"
#在Dos窗口中通过命令结束进程
taskkill /f /t /im xx进程
# 示例
taskkill /f /t /im System
PG库创建序列实现主键自增
-- 先创建序列
CREATE SEQUENCE msg_connection_id_seq START 1;
-- 再把字段加上默认值
nextval('dbms_connection_msg_connection_id_seq'::regclass)
-- 序列重置到1000
alter sequence sequence_name restart with 1000
-- 验证
SELECT nextval('sequence_name');
PG库空间函数计算失效
-- 查询空间字段编码格式
SELECT
st_srid ( field_name )
FROM
table_name;
-- 更新空间数据编码格式
SELECT
UpdateGeometrySRID ( 'table_name', 'field_name', 4490 );
又是一个小细节
- SQL 如果查某些字段,查出来的都是null。此时若有记录但是该字段是空,则total显示对应条数,若没有记录,则total为 0。