2022年工作积累
2022年1月
有的时候我们往往只是因为自己的一点小失误(粗心)而前功尽弃,没那么严重的情况下也可能会折腾而耽误不少时间
location /mxz {
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,PATCH,OPTIONS;
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
return 204;
}
proxy_pass http://49.233.205.96:8815;
rewrite ^.+mxz/?(.*)$ /$1 break;
add_header Access-Control-Allow-Origin $http_origin always;
add_header Access-Control-Allow-Methods *;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
这样一段配置,本身是从之前的配置中拷贝过来修改了一下转发规则,但是拷贝的时候因为终端显示的时候自动换行了,直接用鼠标覆盖的方式去复制,结果导致复制后的配置换行,重启nginx并不报错,但这样配置出来的路径竟然出现了跨域问题。在vim模式下编辑这个配置文件,完全感觉不到区别,一个是自动换行了,一个是拷贝后多了一个换行符。😂
location /mxz {
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,PATCH,OPTIONS;
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-
With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
return 204;
}
proxy_pass http://49.233.205.96:8815;
rewrite ^.+mxz/?(.*)$ /$1 break;
add_header Access-Control-Allow-Origin $http_origin always;
add_header Access-Control-Allow-Methods *;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,
If-Modified-Since,Cache-Control,Content-Type,Authorization';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
2022年3月
微服务调用的问题。
注册中心eureka,微服务为oder-server-800x
,使用feign访问,单服务oder-server-800x
时可以正常访问,再启动一台oder-server-800x
时,启动过程访问微服务,发生故障,可以复现,未解决
com.netflix.client.ClientException: Load balancer does not have available server for client: ODER-SERVER-800X
at com.netflix.loadbalancer.LoadBalancerContext.getServerFromLoadBalancer(LoadBalancerContext.java:483) ~[ribbon-loadbalancer-2.3.0.jar:2.3.0]
at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:184) ~[ribbon-loadbalancer-2.3.0.jar:2.3.0]
at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:180) ~[ribbon-loadbalancer-2.3.0.jar:2.3.0]
2022年4月
IDEA重置。Ultimate重置。因为过期了之后,无法打开点重置按钮没办法。还好别的大神的帮助。
- 原贴https://www.cnblogs.com/stcweb/articles/15601234.html,我用的 临时重置脚本
- 新版已经不能重置了,下载旧一点版本的,2021.2及之前 IDEA历史版本
- 重置插件插件地址
2022年5月
1、旧版本的navicate无法连接到Oracle,破解navicate 15教程: https://www.cnblogs.com/marchxd/p/15580739.html
2、切面输出请求信息
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@Aspect
@Component
@Slf4j
public class ApiAspect {
/**
*
* execution:改成自己要打印的控制器路径
* @param proceedingJoinPoint
* @return
* @throws Throwable
*/
@Around("execution(* cn..*.controller.*.*(..)) ")
public Object handleControllerMethod(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//原始的HTTP请求和响应的信息
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
log.debug("ApiAuthAspect::requestURI is::" + request.getRequestURI());
Signature signature = proceedingJoinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature)signature;
//获取当前执行的方法
Method targetMethod = methodSignature.getMethod();
//获取参数
Object[] args = proceedingJoinPoint.getArgs();
//获取返回对象
Object object = proceedingJoinPoint.proceed();
StringBuilder sb = new StringBuilder(1000);
sb.append("-------------------------------------------------------------\n");
sb.append("Controller: ").append(targetMethod.getDeclaringClass().getName()).append("\n");
sb.append("Method : ").append(targetMethod.getName()).append("\n");
if (ArrayUtils.isNotEmpty(args)) {
List<Object> logArgs = Arrays.stream(args).filter(arg -> (!(arg instanceof HttpServletRequest) && !(arg instanceof HttpServletResponse)))
.collect(Collectors.toList());
sb.append("Params : ").append(JSON.toJSONString(logArgs)).append("\n");
} else {
sb.append("Params : ").append("null").append("\n");
}
sb.append("URI : ").append(request.getRequestURI()).append("\n");
sb.append("URL : ").append(request.getRequestURL()).append("\n");
sb.append("Return : ").append(object).append("\n");
sb.append("-------------------------------------------------------------\n");
System.out.println(sb.toString());
return object;
}
}
注意这里直接返回object,开始有画蛇添足的 return proceedingJoinPoint.proceed()
这样会使得请求再执行一次,而再执行的时候,参数已经不存在,导致错误
3、oracle远程连接报错为:TNS无法监听
找到计算机安装oracle时,生成的app文件夹下,我的目录是D:\app\zhang\product\11.2.0\dbhome_1\NETWORK\ADMIN
按个人情况找到该文件夹,在该文件夹下找到listener.ora和tnsnames.ora两个文件
修改文件中的localhost为当前计算机的 名称,计算机名称可以 在计算机上右键 查看。然后在cmd命令行执行下面命令
lsnrctl stop 停止监听服务
lsnrctl start 开始监听服务
lsnrctl reload 重启监听服务
4、前后端分离的项目,跨域的情况 JSESSIONID 会变化,导致Session过期,目前接手的项目启用了Session域,没办法全部改掉,遇到这个问题倒腾了一两天。参考链接:https://blog.csdn.net/wxj_ios/article/details/86083458。
- 后端配置
- 将Access-Control-Allow-Origin设置为
request.getHeader("Origin")
- 将Access-Control-Allow-Credentials 设置为true
- 将Access-Control-Allow-Origin设置为
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 跨域
* @author zm
* @version 1.0.0
* @since 2022年05月20日
*/
@Component
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request= (HttpServletRequest)req;
response.setHeader("Access-Control-Allow-Origin",request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Methods", "POST,PUT,GET,OPTIONS,DELETE");
response.setHeader("Access-Control-Allow-Headers", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
chain.doFilter(req, res);
}
@Override
public void init(FilterConfig filterConfig) {}
@Override
public void destroy() {}
}
- 前端
- axios.defaults.withCredentials = true
- 前端配置跨域解决
你以为我遇到的问题就这么简单如上面的帖子吗,并不是,我本地因为要参考以前那个前后端不分离的项目,所以把另外一个项目启动了,当我再访问旧项目时使用 http://localhost:8082时,这个项目会把新项目http://localhost:8089的服务的的JSESSIONID串改了,串改后因为新项目后端不认识这个新的JSESSIONID,就又会重新发一个Set-Cookie让浏览器更新JSESSIONID,这样就登陆失效了。最后http://localhost:8082 改成 http://127.0.0.1:8082,终于欧克了
2022年6月
mybatis binding
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
通常都是 映射的xml没找到
- springboot+mybatis
mybatis:
mapper-locations: classpath*:mapper/*.xml
- springboot+mybatis-plus
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
此时和 springboot+mybatis相同配置就不起作用了,使用如下配置
mybatis-plus:
mapper-locations: classpath:mappers/*.xml
普通的mybatis中注意多级目录是目录,而不是点号:https://www.bilibili.com/video/BV1VP4y1c7j7?p=18&vd_source=5df7a6561564422724543d96bd6a674f
2022年8月
树形菜单加搜索,费劲
- 关于树形结构的搜索功能,首先数据库里存的树形结构用一个 pid来关联的,做某一个字段的搜索功能
oracle 统计每个班级的学生数,学生id有重复,使用rownumber去重
oracle 中的merge into用法
运维相关知识比较薄弱,装个openvpn整一天,还是没整出来
看了半天视频,博客文章,硬是没整出来。后来公司里别的同事折腾了一两个小时,弄好了
经验告诉你。安装这种东西,尽量找官网。因为软件版本更新了,系统也更新了,东拉西扯的资料看完,各种坑
数据库连接池困扰一周的问题
给某政府单位做的项目,用一段时间就卡死,mybatis查询卡主,不报错。不知道问题所在就尝试以下操作
- 更换mybatis版本 ,从mybatis-plus高版本换到 mybatis-spring-boot-starter低版本 【失败】
- 更换数据库连接池,从Druid换到dbcp2 【失败】
- 查找事务是否结束,未查询到
- 查询连接数是否打满,未打满 oracle默认最大连接数是150,使用了三四十个吧
- 查询未结束的sql,找到了,为啥一直update未结束,看起来不是个慢查询
- 查看dbcp2的连接池的实际连接数,用完了,默认为8个,上面8个未执行完的,卡死。
pool.setMaxTotal(50); //使用对象注入的,可以通过springboot的配置注入,反正就是maxTotal属性
2022年11月
一个切面配了半天,最后发现符号写错了
要写两个方法的Pointcut 用成了&&。这里要用||,用成&&就完。但当如果是包的范围更广,然后要排除范围更小的方法或者类,就需要用
&& !execution
@Pointcut("execution(* tech.dclass.dclasspay.controller.FreeController.projectDetail(..))|| execution(* tech.dclass.dclasspay.controller.WxNewBindController.loginGetState(..))" )
以下两种代码,结果不同,需要非常理解这个引用
private void wxBind(String bindToken,UserExt user){
if(!StringUtils.isBlank(bindToken)){
if(省略){
userMapper.update(
省略了更新user的具体细节
);
BeanUtils.copyProperties(userMapper.selectExtByKey(user.getUserid()),user);
}
}
}
private void wxBind(String bindToken,UserExt user){
if(!StringUtils.isBlank(bindToken)){
if(省略){
userMapper.update(
省略了更新user的具体细节
);
user=userMapper.selectExtByKey(user.getUserid());
}
}
}
第二种写法就无效,第二种写法的意思是,user引用去指向另外一个对象。而这里的引用是个局部变量,跟你调用的变量的引用是两个变量。所以如果
user=userMapper.selectExtByKey(user.getUserid())
在方法外使用,就会正常,因为整个返回的这个引用指向了新的user,正好我们要返回这个引用的对象。但第一个copyProperties就不一样,因为copy现在所指的对象,现在所指的对象是传进来的真实对象