已找到解决方案:
修改nginx配置即可
fastcgi_param SCRIPT_FILENAME /www$fastcgi_script_name;
没有足够的数据
soft_xiang 赞了回答 · 2020-11-26
已找到解决方案:
修改nginx配置即可
fastcgi_param SCRIPT_FILENAME /www$fastcgi_script_name;
已找到解决方案:修改nginx配置即可fastcgi_param SCRIPT_FILENAME /www$fastcgi_script_name;
关注 4 回答 4
soft_xiang 发布了文章 · 2020-09-03
var reg = /(?<=prompt:.*)([\u4e00-\u9fa5]+)(?=.*,)/g //断言用法
"prompt: '请选择商品编码' ,searcher:function(){xxx[商品编码]}".match(reg); //匹配到 请选择商品编码
var patt = /(?<=\[).+?(?=\])|(?<=\().+?(?=\))/g;
"操作失败,单号[0001]中(0002)不存在".replace(patt,'8888');
// 结果 操作失败,单号[8888]中(8888)不存在
查看原文主要记录一些正则表达式匹配指定格式中的中文 {代码...} 匹配特殊[] {代码...}
赞 0 收藏 0 评论 0
soft_xiang 发布了文章 · 2020-07-21
做一个jasperreport6 导出excel的功能时,出现一个问题,在测试环境(centos7)正常,发到客户环境(centos7)后异常,最开始为:
Handler processing failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class net.sf.jasperreports.engine.util.JRStyledTextParser
查看tomcat9中项目中的lib下有重复版本jar包,处理以后重启,报
org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11GraphicsEnvironment
java.lang.InternalError: Cant connect to X11 window server using 'localhost:10.0' as the value of the DISPLAY variable.
at sun.awt.X11GraphicsEnvironment.initDisplay(Native Method)
最终解决办法为:
在tomcat启动脚本 start.sh 中加入:export CATALINA\_OPTS="-Djava.awt.headless=true"
参见:
https://blog.csdn.net/xgjians...查看原文
做一个jasperreport6 导出excel的功能时,出现一个问题,在测试环境(centos7)正常,发到客户环境(centos7)后异常,最开始为:
赞 0 收藏 0 评论 0
soft_xiang 发布了文章 · 2020-07-09
ireport5.6.0安装不多说
安装完成后启动可能闪退,主要是ireport5.6.0需要jdk1.7才能运行,1.8就会闪退。
修改 C:\Program Files (x86)\Jaspersoft\iReport-5.6.0\etc\ireport.conf
(默认路径) 下
#jdkhome="/path/to/jdk"
jdkhome="C:\programs\Java\jdk1.7.0_71"
① 对应代码中paramMap中的变量
② 对应代码中datas中的数据的名称
③ 计算数,需要注意计算类型
public static void main(String[] args) {
String exportType = "xlsx";
String defaultTemplatePath = "D:\\report1.jasper";
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("usid", "test@test.cn");
paramMap.put("usna", "张三");
paramMap.put("curDate", DateUtil.date2String(new Date()));
List<Map<String, ?>> datas = new ArrayList<>();
for (int i = 0; i < 3; i++) {
Map<String, Object> temp = new HashMap<>();
temp.put("key1", "key----" + i);
temp.put("val1", "val====" + i);
temp.put("cnt", 1);
datas.add(temp);
}
JRDataSource dataSource = new JRMapCollectionDataSource(datas);
try {
JasperPrint jasperPrint = JasperFillManager.fillReport(defaultTemplatePath, paramMap, dataSource);
String targetFileName = "D:\\test_" + DateUtil.date2String(new Date(), DateUtil.yyyyMMddHHmmss) + "." + exportType;
if ("pdf".equalsIgnoreCase(exportType)) {
JasperExportManager.exportReportToPdfFile(jasperPrint, targetFileName);
} else if ("xlsx".equalsIgnoreCase(exportType)) {
JRXlsxExporter exporter = new JRXlsxExporter();
SimpleXlsxReportConfiguration configuration = new SimpleXlsxReportConfiguration();
configuration.setWhitePageBackground(true);
configuration.setRemoveEmptySpaceBetweenRows(true);// 空行
configuration.setRemoveEmptySpaceBetweenColumns(true);// 空列
exporter.setConfiguration(configuration);
// 设置输入项
ExporterInput exporterInput = new SimpleExporterInput(jasperPrint);
exporter.setExporterInput(exporterInput);
// 设置输出项
OutputStreamExporterOutput exporterOutput = new SimpleOutputStreamExporterOutput(targetFileName);
exporter.setExporterOutput(exporterOutput);
exporter.exportReport();
}
System.out.println("导出成功:" + targetFileName);
} catch (Exception e) {
e.printStackTrace();
}
}
修改 C:\Program Files (x86)\Jaspersoft\iReport-5.6.0\etc\ireport.conf (默认路径) 下
赞 0 收藏 0 评论 0
soft_xiang 发布了文章 · 2020-06-03
springboot项目默认打成一个jar包,在多环境时不友好,需要将依赖的第三方jar及resources目录下的配置文件打包到与jar包同级目录下,方便环境变更,具体操作如下:
pom.xml需修改
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
<outputDirectory>${project.build.directory}/gwall/</outputDirectory>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 打包成jar文件,并指定lib文件夹以及resources资源文件夹 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.xxl.job.admin.XxlJobAdminApplication</mainClass>
<!--依赖前缀 -->
<classpathPrefix>lib/</classpathPrefix>
<addClasspath>true</addClasspath>
</manifest>
<manifestEntries>
<Class-Path>resources/</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
添加配置文件
assembly.xml文件内容如下:
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>distribution</id>
<!--输出格式 zip 最终结果生成zip -->
<formats>
<format>tar.gz</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<!--设置需要输出文件 -->
<fileSets>
<fileSet>
<directory>src/main/bin</directory>
<outputDirectory>/</outputDirectory>
<fileMode>0755</fileMode>
</fileSet>
<fileSet>
<directory>src/main/resources/</directory>
<outputDirectory>/resources</outputDirectory>
<fileMode>0644</fileMode>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<!--依赖包的输出目录 -->
<outputDirectory>/lib</outputDirectory>
<scope>runtime</scope>
<excludes>
<exclude>${project.groupId}:${project.artifactId}</exclude>
</excludes>
</dependencySet>
<dependencySet>
<!--jar包的输出目录 -->
<outputDirectory>/</outputDirectory>
<includes>
<include>${project.groupId}:${project.artifactId}</include>
</includes>
</dependencySet>
</dependencySets></assembly>
start.sh文件内容如下:
#!/bin/bash
curpath=`pwd`
app=xxl-job-admin-2.1.0.jar
echo 'curpath:$curpath app:$app'
ps -aux|grep $curpath/$app|grep -v grep|awk '{print $2}'|xargs -r kill -9
nohup java -jar $curpath/$app > $curpath/nohup.out 2>&1 &
start.bat文件内容如下:
@echo off & setlocal enabledelayedexpansion
java -jar xxl-job-admin-2.1.0.jar
pause
最终结果如下:
主要是使用logback-spring.xml
另外需要在application.yml中配置
logging:
config: config/logback-spring.xml
springboot项目默认打成一个jar包,在多环境时不友好,需要将依赖的第三方jar及resources目录下的配置文件打包到与jar包同级目录下,方便环境变更,具体操作如下:
赞 0 收藏 0 评论 0
soft_xiang 发布了文章 · 2020-05-26
mycat在使用过程中觉得非常好,很实用,但使用过程中也碰到了不少问题,踩了不少坑,现做一些记录,历史的一些坑已经忘记了,从现在开始吧
这个问题比较常见,而且比较初级。
现象为:连mycat的查询的时候多次执行SQL,返回的结果数量不一致或者数据不一致。
一般原因为:查询的表中有全局表,且在全局表中的数据不一致造成
重现现象为:项目中使用了mybatisplus(推荐,封装了mybatis的工具),在使用mybatisplus的saveOrUpdateBatch方法时,数据量超过一定的数据量时报 Unknown command
,详细异常信息如下:
发生异常,
org.apache.ibatis.exceptions.PersistenceException:
### Error flushing statements. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Unknown command
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Unknown command
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSession.flushStatements(DefaultSqlSession.java:254)
at com.baomidou.mybatisplus.extension.service.impl.ServiceImpl.saveOrUpdateBatch(ServiceImpl.java:179)
at com.baomidou.mybatisplus.extension.service.IService.saveOrUpdateBatch(IService.java:76)
at com.gwall.core.service.impl.DstaskServiceImpl.saveOrUpdateCids(DstaskServiceImpl.java:148)
at com.gwall.core.service.impl.DstaskServiceImpl$$FastClassBySpringCGLIB$$bf68f571.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:100)
at com.gwall.core.common.aspects.GwallRequestIdAspect.requestIdHandle(GwallRequestIdAspect.java:46)
at sun.reflect.GeneratedMethodAccessor83.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:295)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
at com.gwall.core.service.impl.DstaskServiceImpl$$EnhancerBySpringCGLIB$$e5a8ece4.saveOrUpdateCids(<generated>)
at com.gwall.core.service.impl.base.AbstractServiceImpl.batchSaveCids(AbstractServiceImpl.java:727)
at com.gwall.core.service.impl.base.AbstractServiceImpl$$FastClassBySpringCGLIB$$3afa95e6.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:100)
at com.gwall.core.common.aspects.GwallRequestIdAspect.requestIdHandle(GwallRequestIdAspect.java:46)
at sun.reflect.GeneratedMethodAccessor83.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:295)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
at com.gwall.base.service.impl.SuinServiceImpl$$EnhancerBySpringCGLIB$$946e8cf5.batchSaveCids(<generated>)
at com.gwall.core.controller.AbstractController.batchSaveCids(AbstractController.java:500)
at com.gwall.core.controller.AbstractController$$FastClassBySpringCGLIB$$9007052b.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:100)
at com.gwall.core.common.aspects.GwallRequestIdAspect.requestIdHandle(GwallRequestIdAspect.java:46)
at sun.reflect.GeneratedMethodAccessor83.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
at com.gwall.base.controller.SuinController$$EnhancerBySpringCGLIB$$3fb28a8b.batchSaveCids(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at com.dianping.cat.servlet.CatFilter.logTransaction(CatFilter.java:255)
at com.dianping.cat.servlet.CatFilter.doFilter(CatFilter.java:93)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:151)
at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:85)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:853)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
将数据库连接改为mysql 3306端口时,则正常,定位为mycat问题,咨询大佬后给出的方案是将 数据库连接字符串?后的部分去掉。具体如
原数据库连接字符串:jdbc:mysql://host:8066/db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&useAffectedRows=true&autoReconnect=true&failOverReadOnly=false
修改后:jdbc:mysql://host:8066/db
问题修复,暂时只做问题记录,未研究具体原因
重现现象为:
当在一个存在事务的方法中,存在sql异常(字段不存在,语法错误等)且被try catch包裹时,链接被标记为需要rollback,方法执行完成后归还到连接池中。如果后面从数据库连接池中拿到了这个链接,再执行其他sql的时候,即使sql没有错误,在提交事务的时候也会抛出
Caused by: java.sql.SQLException: Transaction error, need to rollback.Distributed transaction is disabled!
之前一直没查出来什么问题,以为是应用druid或者spring的问题,被坑了很久。
发现这个问题之后找到了下面这个文章,写的比较详细
https://www.cnblogs.com/jonra...
查看原文这个问题比较常见,而且比较初级。现象为:连mycat的查询的时候多次执行SQL,返回的结果数量不一致或者数据不一致。一般原因为:查询的表中有全局表,且在全局表中的数据不一致造成
赞 2 收藏 0 评论 0
soft_xiang 发布了文章 · 2020-03-26
本篇文章主要是springboot2 中 redis cache中的一些内容,主要包含2个功能点:
废话不多说,上代码
@Configuration
@EnableCaching
public class CacheConfig extends CachingConfigurerSupport {
private static final String SYSTEMCACHE_REDIS_KEY_PREFIX = "system:cache";
private static final String SYSTEMCACHE_TTL_OFDAY = "system.cache.ttlOfDay";
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Bean
@Override
public CacheManager cacheManager() {
// 设置系统缓存过期时间为默认30天以及添加自定义前缀
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(
Duration.ofDays(30))
.computePrefixWith(cacheKeyPrefix()); // 设置缓存有效期一小时
return RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
.cacheDefaults(redisCacheConfiguration).build();
}
@Bean
public CacheKeyPrefix cacheKeyPrefix() {
return new CacheKeyPrefix() {
@Override
public String compute(String cacheName) {
String cid = getCid();//此方法需要自己实现,获取租户编码
StringBuilder sBuilder = new StringBuilder(100);
sBuilder.append(SYSTEMCACHE_REDIS_KEY_PREFIX).append(":");
if (StringUtil.isNotBlank(cid)) {
sBuilder.append(cid).append(":");
}
sBuilder.append(cacheName).append(":");
return sBuilder.toString();
}
};
}
}
用法:
@Cacheable(value = {"MenuTreeByRoles"})
public List<Map<String, Object>> selectMenuTreeByRoles(String roleIds) {...}
则最终以生成system:cache:cid:MenuTreeByRoles为key的缓存;
查看原文本篇文章主要是springboot2 中 redis cache中的一些内容,主要包含2个功能点: 自定义缓存过期时间(全局自定义,每个key不能单独指定) 自定义缓存key前缀 废话不多说,上代码 {代码...} 用法: {代码...} 则最终以生成system:cache:cid:MenuTreeByRoles为key的缓存;
赞 1 收藏 0 评论 0
soft_xiang 发布了文章 · 2020-01-08
系统需要用到一个导入excel文件的功能,使用poi组件常规方式读取excel时,内存耗尽,OutOfMemoryError,或者读取非常慢
所以写了一个工具类,使用poi sax方式读取excel,速度快很多,内存消耗可以接受。
测试结果如下:
.xlsx文件,35M大小,总4个sheel,
只读取第一个,37434行,54列
总行数:37434
读取耗时:39秒
打印耗时:17秒
主要代码如下:
ExcelUtils.class 主入口
package com.xxx.bi.utils.excel;
import java.util.List;
import java.util.Objects;
import org.apache.commons.lang3.StringUtils;
import com.google.common.collect.Lists;
public class ExcelUtils {
/** logger日志. */
// public static final Logger LOGGER = Logger.getLogger(ExcelUtils.class);
public ExcelUtils() {
}
/**
* 获取excel的表头
*
* @param filePath
* 文件路径
* @param headerNum
* 表头所在行数
* @return
*/
public static List<String> getHeader(String filePath, int headerNum) {
if (StringUtils.isBlank(filePath)) {
throw new IllegalArgumentException("传入文件路径不能为空");
}
if (Objects.isNull(headerNum) || headerNum < 1) {
headerNum = 1;
}
try {
return LargeExcelFileReadUtil.getRowFromSheetOne(filePath, headerNum);
} catch (Exception e) {
// LOGGER.info("获取excel[" + filePath + "]表头失败,原因:", e);
e.printStackTrace();
}
return Lists.newArrayList();
}
/**
* 获取excel的所有数据<br/>
* 所有数据类型都是String<br/>
* 会以第一行数据的列数为总列数,所以第一行的数据必须都不为空,否则可能出java.lang.IndexOutOfBoundsException
*
* @param filePath
* 文件路径
* @param headerNum
* 表头所在行数
* @return
*/
public static List<List<String>> getAllData(String filePath) {
if (StringUtils.isBlank(filePath)) {
throw new IllegalArgumentException("传入文件路径不能为空");
}
try {
return LargeExcelFileReadUtil.getRowsFromSheetOne(filePath);
} catch (Exception e) {
// LOGGER.info("获取excel[" + filePath + "]表头失败,原因:", e);
e.printStackTrace();
}
return Lists.newArrayList();
}
public static void main(String[] args) {
long start = System.currentTimeMillis();
String filepath = "C:/Users/Administrator/Desktop/05-作业调配表 -快递.xlsx";
// List<String> result = ExcelUtils.getHeader(filepath, 1);
// for (String col : result) {
// System.out.println(col);
// }
List<List<String>> result = ExcelUtils.getAllData(filepath);
long end = System.currentTimeMillis();
for (List<String> list : result) {
System.out.println(list.toString());
}
long end1 = System.currentTimeMillis();
try {
Thread.sleep(1000l);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.err.println("总行数:" + result.size());
System.err.println(("读取耗时:" + (end - start) / 1000) + "秒");
System.err.println(("打印耗时:" + (end1 - end) / 1000) + "秒");
}
}
LargeExcelFileReadUtil.class 真正的工具类
package com.xxx.bi.utils.excel;
import java.io.InputStream;
import java.util.List;
import java.util.Objects;
import org.apache.log4j.Logger;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
public class LargeExcelFileReadUtil {
/** logger日志. */
public static final Logger LOGGER = Logger.getLogger(LargeExcelFileReadUtil.class);
// 处理一个sheet
public static List<String> getRowFromSheetOne(String filename, Integer rowNum) throws Exception {
InputStream inputStream = null;
OPCPackage pkg = null;
SingleRowHandler singleRowHandler = null;
try {
pkg = OPCPackage.open(filename);
XSSFReader r = new XSSFReader(pkg);
SharedStringsTable sst = r.getSharedStringsTable();
singleRowHandler = new SingleRowHandler(sst, rowNum);
XMLReader parser = XMLReaderFactory.createXMLReader("com.sun.org.apache.xerces.internal.parsers.SAXParser");
parser.setContentHandler(singleRowHandler);
inputStream = r.getSheet("rId1");
InputSource sheetSource = new InputSource(inputStream);
parser.parse(sheetSource);
return singleRowHandler.getRow();
} catch (Exception e) {
String message = e.getMessage();
if (Objects.nonNull(rowNum) && Objects.nonNull(singleRowHandler)
&& SingleRowHandler.FINISH_ROW_MESSAGE.equalsIgnoreCase(message)) {
// 获取某一行数据完成 ,暂时不知道怎么能终止excel解析,直接抛出了异常,实际是成功的
return singleRowHandler.getRow();
}
throw e;
} finally {
if (Objects.nonNull(pkg)) {
pkg.close();
}
if (Objects.nonNull(inputStream)) {
inputStream.close();
}
}
}
// 处理一个sheet
public static List<List<String>> getRowsFromSheetOne(String filename) throws Exception {
InputStream inputStream = null;
OPCPackage pkg = null;
MultiRowHandler multiRowHandler = null;
try {
pkg = OPCPackage.open(filename);
XSSFReader r = new XSSFReader(pkg);
SharedStringsTable sst = r.getSharedStringsTable();
multiRowHandler = new MultiRowHandler(sst);
XMLReader parser = XMLReaderFactory.createXMLReader("com.sun.org.apache.xerces.internal.parsers.SAXParser");
parser.setContentHandler(multiRowHandler);
inputStream = r.getSheet("rId1");
InputSource sheetSource = new InputSource(inputStream);
parser.parse(sheetSource);
return multiRowHandler.getRows();
} catch (Exception e) {
throw e;
} finally {
if (Objects.nonNull(pkg)) {
pkg.close();
}
if (Objects.nonNull(inputStream)) {
inputStream.close();
}
}
}
}
SingleRowHandler.class 当行处理类,可以只获取表头或表格中的某一行数据
package com.xxx.bi.utils.excel;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class SingleRowHandler extends DefaultHandler {
public final static String FINISH_ROW_MESSAGE = "row data process finish";
private Integer rowNum = null;// rowNum不为空时则标示只需要获取这一行的数据
private int curRowNum = 1;
private String cellType = "";
private SharedStringsTable sst;
private String lastContents;
private boolean nextIsString;
private String cellPosition;
private List<String> row = new ArrayList<>();
public List<String> getRow() {
return row;
}
public SingleRowHandler(SharedStringsTable sst, Integer rowNum) {
this.sst = sst;
this.rowNum = rowNum;
}
public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
if (name.equals("c")) {
cellPosition = attributes.getValue("r");
// 这是一个新行
if (Pattern.compile("^A[0-9]+$").matcher(cellPosition).find()) {
curRowNum = Integer.valueOf(cellPosition.substring(1));
}
cellType = "";
cellType = attributes.getValue("t");
if ("s".equals(cellType)) {
nextIsString = true;
} else {
nextIsString = false;
}
}
// 清楚缓存内容
lastContents = "";
if (Objects.nonNull(rowNum) && curRowNum > rowNum) {
// 获取某一行数据完成 ,暂时不知道怎么能终止excel解析,直接抛出了异常,实际是成功的
throw new SAXException(FINISH_ROW_MESSAGE);
}
}
public void endElement(String uri, String localName, String name) throws SAXException {
if (nextIsString) {
int idx = Integer.parseInt(lastContents);
lastContents = new XSSFRichTextString(sst.getEntryAt(idx)).toString();
nextIsString = false;
}
if (name.equals("v")) {
if (Objects.isNull(rowNum) || rowNum == curRowNum) {
row.add(lastContents);
}
}
}
public void characters(char[] ch, int start, int length) throws SAXException {
lastContents += new String(ch, start, length);
}
}
MultiRowHandler.class 获取excel所有行的数据
package com.xxx.bi.utils.excel;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* 获取完整excel数据的handler<br/>
*
* @author Administrator
*
*/
public class MultiRowHandler extends DefaultHandler {
private int curRowNum = 0;// 行号,从1开始
private int curColIndex = -1;// 列索引,从0开始
private int colCnt = 0;// 列数,取第一行列数做为列总数
private String cellType = "";
private SharedStringsTable sst;
private String lastContents;
private boolean nextIsString;
private String cellPosition;
private List<String> head = null;
private List<String> curRowData = null;
private boolean curRowIsBlank = true;// 当前是个空行
private List<List<String>> rows = new ArrayList<>();
public List<List<String>> getRows() {
return rows;
}
public MultiRowHandler(SharedStringsTable sst) {
this.sst = sst;
}
@Override
public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
if (name.equals("c")) {
cellPosition = attributes.getValue("r");
curColIndex = getColIndex(cellPosition);
// 这是一个新行
if (isNewRow(cellPosition)) {
curRowNum = getRowNum(cellPosition);
if (2 == curRowNum && Objects.nonNull(curRowData)) {
head = curRowData;
colCnt = head.size();
}
curRowData = getBlankRow(colCnt);
}
cellType = "";
cellType = attributes.getValue("t");
if ("s".equals(cellType)) {
nextIsString = true;
} else {
nextIsString = false;
}
}
// 清楚缓存内容
lastContents = "";
}
private boolean isNewRow(String cellPosition) {
// 坐标以A开头,后面跟数字 或者坐标行和当前行不一致的
boolean newRow = Pattern.compile("^A[0-9]+$").matcher(cellPosition).find();
if (!newRow) {
int cellRowNum = getRowNum(cellPosition);
newRow = (cellRowNum != curRowNum);
}
return newRow;
}
/**
* 根据列坐标获取行号,从1开始,返回0时标示出错
*
* @param cellPosition
* 列坐标,为A1,B23等
* @return 行号,从1开始,返回0是为失败
*/
private static int getRowNum(String cellPosition) {
String strVal = Pattern.compile("[^0-9]").matcher(cellPosition).replaceAll("").trim();// 获取坐标中的数字
if (StringUtils.isNotBlank(strVal)) {
return Integer.valueOf(strVal);
}
return 0;
}
/**
* 根据列坐标返回当前列索引,从0开始,返回-1时标示出错<br/>
* A1->0; B1->1...AA1->26
*
* @param cellPosition
* 列坐标,为A1,B23等
* @return 列索引,从0开始,返回-1是为失败,A1->0; B1->1...AA1->26
*/
private static int getColIndex(String cellPosition) {
int index = -1;
int num = 65;// A的Unicode码
int length = cellPosition.length();
for (int i = 0; i < length; i++) {
char c = cellPosition.charAt(i);
if (Character.isDigit(c)) {
break;// 确定指定的char值是否为数字
}
index = (index + 1) * 26 + (int) c - num;
}
return index;
}
/**
* 返回一个全部为空字符串的空行
*
* @param cnt
* @return
*/
private List<String> getBlankRow(int cnt) {
List<String> result = new ArrayList<>(cnt);
for (int i = 0; i < cnt; i++) {
result.add(i, "");
}
curRowIsBlank = true;
return result;
}
@Override
public void endElement(String uri, String localName, String name) throws SAXException {
if (nextIsString) {
int idx = Integer.parseInt(lastContents);
lastContents = new XSSFRichTextString(sst.getEntryAt(idx)).toString();
nextIsString = false;
}
if (name.equals("v")) {
// System.out.println(MessageFormat.format("当前列定位:{0},当前行:{1},当前列:{2},当前值:{3}",
// cellPosition, curRowNum,
// curColIndex, lastContents));
if (Objects.isNull(head)) {
curRowData.add(lastContents);
} else {
curRowData.set(curColIndex, lastContents);
}
curRowIsBlank = false;
// 这是一个新行
if (isNewRow(cellPosition)) {
if (Objects.nonNull(curRowData)) {
if (curRowIsBlank) {
curRowData.clear();// 如果当前行是空行,则清空当前行数据
}
rows.add(curRowData);
}
}
}
}
@Override
public void endDocument() throws SAXException {
if (Objects.nonNull(curRowData) && !curRowIsBlank) {
rows.add(curRowData);// 最后一行在上面不好加入,最后一行全是空行的不加入
}
super.endDocument();
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
lastContents += new String(ch, start, length);
}
@Override
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
lastContents += "";
}
public static void main(String[] args) {
System.out.println(getColIndex("BC2"));
}
}
查看原文系统需要用到一个导入excel文件的功能,使用poi组件常规方式读取excel时,内存耗尽,OutOfMemoryError,或者读取非常慢所以写了一个工具类,使用poi sax方式读取excel,速度快很多,内存消耗可以接受。
赞 0 收藏 0 评论 0
soft_xiang 发布了文章 · 2019-12-13
说明
之所以写这篇文章,是因为在项目中处理全局异常是发现自定义Intercepter中的异常没发通过 @ControllerAdvice
捕获。
项目中使用 @ControllerAdvice
处理了controller中的异常,但发现在自定义拦截器( extends HandlerInterceptorAdapter )中抛出的异常没有被拦截,跳转到了/error下,所以想要重写/error请求,过程比较曲折,现将测试通过的代码进行记录。
最终结果如下:
package com.xxx.core.controller;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ErrorProperties.IncludeStacktrace;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.servlet.error.AbstractErrorController;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import lombok.extern.slf4j.Slf4j;
@Controller
@RequestMapping("${server.error.path:${error.path:/error}}")
@Slf4j
public class CustomerExceptionController extends AbstractErrorController {
private final ErrorProperties errorProperties;
@Autowired
public CustomerExceptionController(ErrorAttributes errorAttributes, ServerProperties serverProperties) {
super(errorAttributes);
this.errorProperties = serverProperties.getError();
}
@Override
public String getErrorPath() {
return errorProperties.getPath();
}
@RequestMapping(produces = "text/html")
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
ModelAndView modelAndView = new ModelAndView("error");
Map<String, Object> errorMap = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));
if (errorMap != null) {
/* timestamp status error message path */
modelAndView.addObject("msg", errorMap.get("error"));
modelAndView.addObject("statusCode", errorMap.get("status"));
logHandler(errorMap);
}
return modelAndView;
}
@RequestMapping
@ResponseBody
public ResponseEntity<JsonResult<Map<String, Object>>> error(HttpServletRequest request) {
Map<String, Object> errorMap = getErrorAttributes(request,
isIncludeStackTrace(request, MediaType.APPLICATION_JSON));
logHandler(errorMap);
Map<String, Object> data = new HashMap<>();
data.putAll(errorMap);
data.remove("trace");
// HttpStatus status = getStatus(request);
return new ResponseEntity<>(JsonResult.failure("", data), HttpStatus.OK);
}
private void logHandler(Map<String, Object> errorMap) {
log.error("url:{},status{},time:{},errorMsg:{}", errorMap.get("path"), errorMap.get("status"),
errorMap.get("timestamp"), errorMap.get("message"));
}
protected boolean isIncludeStackTrace(HttpServletRequest request, MediaType produces) {
IncludeStacktrace include = getErrorProperties().getIncludeStacktrace();
if (include == IncludeStacktrace.ALWAYS) {
return true;
}
if (include == IncludeStacktrace.ON_TRACE_PARAM) {
return getTraceParameter(request);
}
return false;
}
private ErrorProperties getErrorProperties() {
return this.errorProperties;
}
}
本来想直接继承 BasicErrorController,重写error方法 完事,结果发现继承后启动报错,提示没有ErrorProperties。
后来找到一篇文章,构造方法中注入的是ServerProperties serverProperties(和本例类似),通过serverProperties获取ErrorProperties,修改后提示没有无参的构造方法。
心好累,不想努力了,就直接继承了AbstractErrorController,抄了一些BasicErrorController的内容成了上面的代码。完美解决了纠结的问题。
注意事项
拦截器中要排除 /error路径
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authorizeIntercepter).addPathPatterns("/**").excludePathPatterns("/login", "/login/**",
"/static/**", "/webjars/**", "/swagger-ui.html/**", "/swagger-resources/**","/v2/**","/error");
}
查看原文说明 之所以写这篇文章,是因为在项目中处理全局异常是发现自定义Intercepter中的异常没发通过 @ControllerAdvice 捕获。 项目中使用 @ControllerAdvice 处理了controller中的异常,但发现在自定义拦截器( extends HandlerInterceptorAdapter )中抛出的异常没有被...
赞 0 收藏 0 评论 2
soft_xiang 发布了文章 · 2019-11-15
https不了解,对https双向认证更是一脸懵
客户方要求系统提供https的服务,一年前申请某网站的免费证书,下载后包含了各种web容器的证书,应用程序的web容器为tomcat8,最后选用了tomcat下的证书,为jks格式。
一年后免费服务到期,需要更换证书,客户申请了阿里云的证书,下载下来的格式为pfx,客户说只有这种格式的。坑已挖好。
百度搜索结果说可以将pfx转换成jks
命令如下:
keytool -importkeystore -srckeystore xxx.pfx -destkeystore xxx.jks -srcstoretype PKCS12 -deststoretype JKS -srcstorepass xxx -deststorepass xxx -srcalias alias -destalias destalias
因为原来tomcat中配置了jks相关的信息,想着直接将新的jks的文件名和密码保持一致,直接替换原文件就可以了。结果被坑。
按原来的文件名、密码生成新证书后,启动tomcat,事实证明想的还是太简单。
报错信息如下:
15-Nov-2019 12:20:20.221 SEVERE [main] org.apache.coyote.AbstractProtocol.init Failed to initialize end point associated with ProtocolHandler ["http-nio-443"]
java.security.UnrecoverableKeyException: Cannot recover key
at sun.security.provider.KeyProtector.recover(Unknown Source)
at sun.security.provider.JavaKeyStore.engineGetKey(Unknown Source)
at sun.security.provider.JavaKeyStore$JKS.engineGetKey(Unknown Source)
at java.security.KeyStore.getKey(Unknown Source)
at sun.security.ssl.SunX509KeyManagerImpl.<init>(Unknown Source)
at sun.security.ssl.KeyManagerFactoryImpl$SunX509.engineInit(Unknown Source)
at javax.net.ssl.KeyManagerFactory.init(Unknown Source)
at org.apache.tomcat.util.net.jsse.JSSESocketFactory.getKeyManagers(JSSESocketFactory.java:617)
at org.apache.tomcat.util.net.jsse.JSSESocketFactory.getKeyManagers(JSSESocketFactory.java:546)
.
.
.
Caused by: org.apache.catalina.LifecycleException: Protocol handler initialization failed
at org.apache.catalina.connector.Connector.initInternal(Connector.java:962)
at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
... 12 more
Caused by: java.security.UnrecoverableKeyException: Cannot recover key
at sun.security.provider.KeyProtector.recover(Unknown Source)
at sun.security.provider.JavaKeyStore.engineGetKey(Unknown Source)
处理办法:
将新的jks的密码和pfx的密码保持一致,修改tomcat配置文件中的密码。
其实tomcat可以直接配置pfx格式证书,需要指定 keystoreType="PKCS12"
keystoreFile="/证书路径/名称.pfx" keystoreType="PKCS12" keystorePass="证书密码"
但这次的客户有做https双向认证,之前的代码已经写死支持jks证书库,所以需要生成jks
15-Nov-2019 11:59:55.017 SEVERE [main] org.apache.coyote.AbstractProtocol.init Failed to initialize end point associated with ProtocolHandler ["http-nio-443"]
java.io.IOException: Keystore was tampered with, or password was incorrect
at sun.security.provider.JavaKeyStore.engineLoad(Unknown Source)
at sun.security.provider.JavaKeyStore$JKS.engineLoad(Unknown Source)
.
.
.
Caused by: java.security.UnrecoverableKeyException: Password verification failed
... 25 more
异常信息如下:
15-Nov-2019 12:20:20.221 SEVERE [main] org.apache.coyote.AbstractProtocol.init Failed to initialize end point associated with ProtocolHandler ["http-nio-443"]
java.security.UnrecoverableKeyException: Cannot recover key
import javax.net.ssl.*;
import java.io.*;
import java.net.URL;
import java.nio.charset.Charset;
import java.security.KeyStore;
/**
* #2
* HTTPS 双向认证 - use truststore
* 原生方式
*
* @Author soft_xiang
* @Date 7/11/2017
*/
public class HttpsTruststoreNativeDemo {
// 客户端证书路径,用了本地绝对路径,需要修改 调用方证书
private final static String CLIENT_CERT_FILE = "D:\\xxx\\https\\xxx-ip.p12";
// 客户端证书密码
private final static String CLIENT_PWD = "pwd";
// 信任库路径 (被调用方证书合集)
private final static String TRUST_STRORE_FILE = "D:\\xxx\\https\\xxx.jks";
// 信任库密码
private final static String TRUST_STORE_PWD = "xxx";
private static String readResponseBody(InputStream inputStream) throws IOException {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
StringBuffer sb = new StringBuffer();
String buff = null;
while ((buff = br.readLine()) != null) {
sb.append(buff + "\n");
}
return sb.toString();
} finally {
inputStream.close();
}
}
public static void httpsCall() throws Exception {
// 初始化密钥库
KeyManagerFactory keyManagerFactory = KeyManagerFactory
.getInstance("SunX509");
KeyStore keyStore = getKeyStore(CLIENT_CERT_FILE, CLIENT_PWD, "PKCS12");
keyManagerFactory.init(keyStore, CLIENT_PWD.toCharArray());
// 初始化信任库
TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance("SunX509");
KeyStore trustkeyStore = getKeyStore(TRUST_STRORE_FILE, TRUST_STORE_PWD, "JKS");
trustManagerFactory.init(trustkeyStore);
// 初始化SSL上下文
SSLContext ctx = SSLContext.getInstance("SSL");
ctx.init(keyManagerFactory.getKeyManagers(), trustManagerFactory
.getTrustManagers(), null);
SSLSocketFactory sf = ctx.getSocketFactory();
HttpsURLConnection.setDefaultSSLSocketFactory(sf);
String url = "post url";
URL urlObj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) urlObj.openConnection();
con.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36");
con.setRequestProperty("Accept-Language", "zh-CN;en-US,en;q=0.5");
con.setRequestProperty("Content-Type", "text/xml");
con.setRequestMethod("POST");
con.setRequestProperty("Content-Length", "0");
con.setDoInput(true);
con.setDoOutput(true);
DataOutputStream os = new DataOutputStream(con.getOutputStream());
os.write("".getBytes("UTF-8"), 0, 0);
os.flush();
os.close();
con.connect();
InputStream is = con.getInputStream();
Integer code = con.getResponseCode();
final String contentType = con.getContentType();
System.out.println(code + ":" + contentType);
String response = readResponseBody(is);
System.out.println(response);
}
/**
* 获得KeyStore
*
* @param keyStorePath
* @param password
* @return
* @throws Exception
*/
private static KeyStore getKeyStore(String keyStorePath, String password, String type)
throws Exception {
FileInputStream is = new FileInputStream(keyStorePath);
KeyStore ks = KeyStore.getInstance(type);
ks.load(is, password.toCharArray());
is.close();
return ks;
}
public static void main(String[] args) throws Exception {
httpsCall();
}
}
在允许调用的服务器,直接浏览器打开需要访问的地址,调用出现401,sap问题,协调sap解决
证书库密码错误
证书错误,确认sap加入信任库的证书和代码中调用的证书库中的证书是同一个
keytool -import -alias xxx -file "xxx.der" -keystore xxx.jks -storepass pass
将证书导入信任库
keytool -export -alias xxx -keystore abc.jks -storepass pass -file xxx.cer
将证书库abc.jks中别名为xxx的证书导出为xxx.cer,cer客户端证书
keytool -import -alias xxx -file xxx.cer -keystore "%JAVA_HOME%/jre/lib/security/cacerts" -storepass changeit -trustcacerts
将客户端证书导入jdk的默认信任库(cacerts为jdk默认信任库,导入之前记得备份)
客户方要求系统提供https的服务,一年前申请某网站的免费证书,下载后包含了各种web容器的证书,应用程序的web容器为tomcat8,最后选用了tomcat下的证书,为jks格式。
赞 0 收藏 0 评论 0
查看全部 个人动态 →
(゚∀゚ )
暂时没有
(゚∀゚ )
暂时没有
注册于 2018-03-16
个人主页被 1.3k 人浏览
推荐关注