
暂无个人介绍
官方文档请先阅读:dcloud官方扫码文档很蛋疼的是我好像并没有看到默认不支持CODE128。scan = new plus.barcode.Barcode('code',filters,styles); 以上是创建扫描对象,filters 是可以增加支持的条形码类型的。增加方法是:将这一句代码放在scan对象创建之前// 创建支持(根据文档常量的介绍自定义添加支持扫码的类型)var filters = [plus.barcode.QR, plus.barcode.CODE128, plus.barcode.EAN13, plus.barcode.EAN8]; 这样即可扫出CODE128的条形码。
公司需要,搞了一下钉钉的接口。首先说明我是帮使用钉钉软件的客户通过钉钉的接口获取数据,所以说我是有权限的。如果你是ISV,去看官方文档吧。我暂时还不知道ISV开发人员是什么需求,但是至少对于钉钉来说我觉得挺麻烦的。点击打开链接这是钉钉的官方文档地址:点击打开链接我搞了半天才分清一点ISV和非ISV是什么,反正大抵意思是一个授权和一个非授权的访问接口的方式。非ISV开发人员需要获取access_token(好像是默认两小时生命周期,超过时间若在持续获取数据就会自动延续,否则过期需要重新获取。),这个获取接口是https://oapi.dingtalk.com/gettoken?corpid=corpid&corpsecret=corpsecret,其中的corpid和corpsecret这样获取:点击打开链接。java get方式获取示例代码:public static String get(String url) { String result = ""; BufferedReader in = null; try { URL getUrl = new URL(url); URLConnection connection = getUrl.openConnection();// 建立http连接 connection.setRequestProperty("Charset", "UTF-8"); connection.setRequestProperty("accept", "*/*");// 设置通用的请求属性 connection.connect();// 开始连接请求 in = new BufferedReader(new InputStreamReader(connection.getInputStream(),"UTF-8"));//这里如果不加编码方式,解析请求回来的json可能中文乱码报错 String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("发送GET请求出现异常!" + e); e.printStackTrace(); } finally { try { if (in != null) { in.close(); } } catch (Exception e2) { e2.printStackTrace(); } } return result; }下面说POST方式获取数据,看一下接口文档就知道了,严格的参数要求,初次搞反正很蛋疼。@SuppressWarnings("unchecked") public void post() throws Exception { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Calendar cal = Calendar.getInstance(); String access_tokenJson = "https://oapi.dingtalk.com/gettoken?corpid=corpid&corpsecret=corpsecret"; JSONObject accessJson = JSONObject.fromObject(get(access_tokenJson)); DD_access_token token= (DD_access_token)JSONObject.toBean(accessJson,DD_access_token.class); /* 钉钉取打卡记录的接口传参列表: { "userId": "员工在企业内的UserID,企业用来唯一标识用户的字段",//非必填 "workDateFrom": "yyyy-MM-dd hh:mm:ss", "workDateTo": "yyyy-MM-dd hh:mm:ss" } */ JSONObject jsonObj = new JSONObject(); Date curTime = new Date(); //jsonObj.put("userId", "userId");//userid查询条件 jsonObj.put("workDateFrom", sdf.format(curTime)+" 00:00:00"); jsonObj.put("workDateTo", sdf.format(curTime)); String strURL = "https://oapi.dingtalk.com/attendance/list?access_token="+token.getAccess_token()+""; try { URL url = new URL(strURL);// 创建url资源 HttpURLConnection conn = (HttpURLConnection) url.openConnection();// 建立http连接 conn.setDoOutput(true);// 设置允许输出 conn.setDoInput(true);// 设置允许输入 conn.setUseCaches(false);// 设置不用缓存 conn.setRequestMethod("POST");// 设置传参方式 conn.setRequestProperty("Charset", "UTF-8"); conn.setRequestProperty("Content-Type", "application/json"); conn.connect();// 开始连接请求 OutputStream out = conn.getOutputStream(); out.write((jsonObj.toString()).getBytes());// 写入请求的字符串 out.flush(); out.close(); if (conn.getResponseCode() == 200) {// 请求返回的状态 // 请求返回的数据 InputStream in = conn.getInputStream(); try { BufferedReader rd = new BufferedReader(new InputStreamReader(in,"UTF-8"));//这里可以用这个也可以直接用流,buffer的话就是多了个缓存功能 int c = 0; StringBuffer temp = new StringBuffer();//请求接口获取json拼接字符串的话,比较长的返回结果String接收是不够的 while((c = rd.read())!= -1){//这里可以用read也可用readLine,不清楚的话可以查一下两者区别 temp.append((char)c); } JSONObject jsonobject = JSONObject.fromObject(temp.toString()); JSONArray dkobject = JSONArray.fromObject(jsonobject.get("recordresult"));//这里就是将json转成对象或者集合 List<Object> list = (List<Object>) JSONArray.toCollection(dkobject,Object.class); } catch (Exception e1) { e1.printStackTrace(); } } else { System.out.println(String.valueOf(conn.getResponseCode()));; } } catch (Exception e) { e.printStackTrace(); System.out.println("发送POST请求出现异常!" + e); } } 文中用到的JSONObject和JSONArray的包是import net.sf.json.JSONArray; import net.sf.json.JSONObject;可以自行下载导入,maven的话直接贴地址到pom.xml就好
不管三七二十一,粗略的理解,过滤器是在spring之前执行的这个时候想在过滤器中使用spring管理的对象就得用代理过滤器来管理过滤器(DelegatingFilterProxy)<!-- <filter> <filter-name>MyFilter</filter-name> <filter-class>com.package.MyFilter</filter-class> </filter> --> <filter> <filter-name>MyFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>MyFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>修改后的在web.xml中的代码如上,注释中的是原有写法。在spring的配置文件中添加一行:<!-- 启动项目时Spring创建一个过滤器对象交由代理过滤器管理(DelegatingFilterProxy) --> <bean id="MyFilter" class="com.package.MyFilter" />这个时候在过滤器中就能注入spring管理的对象了。
代理有静态代理、动态代理和cglib代理静态代理:1.目标类必须实现一个接口,比如dao层的先写一个接口,再写一个接口的dao实现类,静态代理就是对这个实现类进行代理 2. 必须实现和目标对象(需要代理的类的对象)一样的接口,就是这个目标对象实现了什么接口,静态代理类就必须实现什么接口弊端:如果目标类方法太多岂不是所有的方法都要写一下?太麻烦静态代理public class UserDaoProxy implements IUserDao{ // 接收保存目标对象 private IUserDao target; public UserDaoProxy(IUserDao target) { this.target = target; } @Override public void save() { System.out.println("开始事务..."); target.save(); // 执行目标对象的方法 System.out.println("提交事务..."); }}动态代理:1.和静态代理一样也是目标类必须实现接口 2.代理类不用必须实现和目标类一样的接口,是一个方法,给里面有三个参数,有一个参数是要指定目标类实现接口的类型,(注意指明的是实现接口的类型)动态代理public class ProxyFactory { // 维护一个目标对象 private Object target; public ProxyFactory(Object target){ this.target = target; } // 给目标对象,生成代理对象 public Object getProxyInstance() { return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("开启事务"); // 执行目标对象方法 Object returnValue = method.invoke(target, args); System.out.println("提交事务"); return returnValue; } }); }}cglib代理:1.目标类没有实现的接口,是以子类的形式代理! 2.如果你又不想像静态代理那样实现相同的接口重写所有的方法,也不想像动态代理那种指明接口类型或者说目标对象根本没有实现接口 3.用cglib的方法可以实现,两个方法,看下面代码。 4.使用cglib代理的话是需要导包的,cglib.jar,但是spring-core.jar包中里面有引入这个cglib.jar的包,也就是导了spring的包就可以用了。cglib代理public class ProxyFactory implements MethodInterceptor{ // 维护目标对象 private Object target; public ProxyFactory(Object target){ this.target = target; } // 给目标对象创建代理对象 public Object getProxyInstance(){ //1. 工具类 Enhancer en = new Enhancer(); //2. 设置父类 en.setSuperclass(target.getClass()); //3. 设置回调函数 en.setCallback(this); //4. 创建子类(代理对象) return en.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("开始事务....."); // 执行目标对象的方法 Object returnValue = method.invoke(target, args); System.out.println("提交事务....."); return returnValue; }}spring中的代理模式:根据目标对象是否有实现接口动态的选择代理的模式。 1.如果目标类有实现的接口就使用动态代理 2.如果目标类没有实现的接口就使用cglib代理 为什么上层向下层提供的是接口支持,而不是具体的实现类? 这里面涉及到spring中的事务管理,是aop方式,aop又涉及到代理,代理分为三种,静态、动态、cglib代理。 具体三种代理的区别和实现上面展示了 这里值得一说的是如果你用动态代理需要告诉spring一个被代理类的父类对象,动态代理是以目标类子类的形式代理; 如果使用cglib代理被代理类是要继承接口的。 换个角度看,如果你的dao或者service层写了接口定义方法,实体类是实现这个接口,那么spring就给你采用cglib代理, 如果你的dao或者service层是直接写实现类,那么spring就给你采用jdk动态代理 所以写代码时要细心点,比如说如果你写具体实现类是实现接口,spring给你采用cglib代理, 你糊涂的在下层调用和注入的时候是直接用实现类, 那么是会报错的,因为你告诉spring用cglib代理,而你在下层用的时候用jdk动态代理,肯定冲突啊。
找到本地maven配置中对应的settings.xml文件目录,修改该文件: alimaven aliyun maven http://maven.aliyun.com/nexus/content/groups/public/ central eclipse示例:如果没有这个文件,可以搜索一下教程,如果安装了本地maven库的应该都有这个文件的。
我大体了解到三种解决办法第一种是从在web.xml中配置errorcode的404配置(一般的做法是配置一个跳转页面,如果是网站的话,就搞一个404界面友好的提示,如果是接口的话可以在页面上请求一个404的controller返回提示数据,但是有个弊端是浏览器的地址栏会变成这个404的controller地址,而不是用户原访问地址)第二种是从springmvc源码出发,追溯springmvc在找不到请求url的时候是怎么分发请求的,重写分发器,改写404的方法即可但是以上两种我个人感觉在对springmvc开发rest接口时并不实用,或者说太复杂。第三种就是根据springmvc的特点:精确匹配,也就是当用户访问/project/test/a时不会进入到/project/test/*这个controller,就从这里下手。写一个controller如下:@Controllerpublic class ErroerController extends PublicMethod{@RequestMapping(value={"/","/*"})public @ResponseBody Map<String,Object> error(HttpServletRequest request)throws Exception{Map<String,Object> rmap = new HashMap<String,Object>();rmap.put("status", false);rmap.put("message", "请求的URI地址不存在");return rmap;}}"/"的话只能匹配一个单个的"/",而"/*"可以满足所有的不存在的url地址进入到这个请求
web开发中的POST请求很常见,最近遇到的一个问题是写接口,我看别人牛逼的接口都是又能浏览器访问,又能JS访问,又能URL getUrl = new URL(url);URLConnection connection = getUrl.openConnection();访问,而我在用springmvc的时候利用他请求参数自动封装的用法,怎么样都不能兼容JS和后台请求接口两种用法,也是百度谷歌半天无果,最后我看我java发起的post请求,写法如下:OutputStream out = conn.getOutputStream();out.write((jsonObj.toString()).getBytes("UTF-8"));这就是输出流,对于服务端来说就是要接收这个输出流啊,springmvc的什么表单或者json参数自动封装成对象,或者各种接收参数的注解,其实都是封装HttpServletRequest中的流。既然这样,那就不用springmvc的自动封装了,自己封装。BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream) request.getInputStream(), "utf-8"));StringBuffer sb = new StringBuffer("");String temp;while ((temp = br.readLine()) != null) {sb.append(temp);}br.close();这样就能获取到HttpServletRequest中的post数据了,sb.toString(),一般是json格式,至于json格式想得到对应类型的数据就很随意了。这里要注意的是:在正常开发中,HttpServletRequest这个参数需要经过多个过滤器,而无法保证在哪个过滤器的操作中被读取了一次流的操作,只能读取一次,读取了一次后面从过滤器到达controller的时候再获取是null的。那么解决这个问题的办法也有多个,这里说一个算是比较简单的做法1、创建类:ThreadCachepublic class ThreadCache {// ThreadLocal里只存储了简单的String对象,也可以自己定义对象,存储更加复杂的参数private static ThreadLocal threadLocal = new ThreadLocal();public static String getPostRequestParams() {return threadLocal.get();}public static void setPostRequestParams(String postRequestParams) {threadLocal.set(postRequestParams);}public static void removePostRequestParams() {threadLocal.remove();}}2、在过滤器中将以上读取流的代码进行改造一下if ("POST".equals(req.getMethod().toUpperCase())) {BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream) request.getInputStream(), "utf-8"));StringBuffer sb = new StringBuffer("");String temp;while ((temp = br.readLine()) != null) {sb.append(temp);}br.close();//将流放在线程里面,在controller中需要重复利用,如果不这样controller中request带的post数据将会丢失ThreadCache.setPostRequestParams(sb.toString());}3、到请求最终需要参数的地方获取参数,比如springmvc中的controller里面String requestStr = ThreadCache.getPostRequestParams();requestStr 就是请求的json参数。
例如:Object obj = dao.get(Object_2.classs,id);obj.setName("张三");这种情况下Hibernate下次提交事务的时候会把这个数据库中对应数据更新成set后的。产生原因涉及到Hibernate设计原理,(以下这段话复制地址:http://blog.csdn.net/yang_lover/article/details/45057181)1.瞬态: 一个实体通过new操作符创建后,没有和Hibernate的Session建立关系,也没有手动赋值过该实体的持久化标识(持久化标识可以认为是映射表的主键)。 此时该实体中任何属性的更新都不会反映到数据库表中。2.持久化: 当一个实体和Hibernate的Session创建了关系,并获取了持久化标识,而且在Hibernate的Session生命周期内存在。 此时针对该实体任何属性的更改都会直接影响到数据库表中一条记录对应字段的更新,即与数据库表同步。3.脱管: 当一个实体和Hibernate的Session创建了关系,并获取了持久化标识,而此时Hibernate的Session生命周期结束,实体的持久化标识没有被改动过。 针对该实体任何属性的修改都不会及时反映到数据库表中。 关闭session可以使实体从持久化状态转为托管状态。解决办法:把上述代码例子中的对象"obj",调用方法:sessionFactory.getCurrentSession().evict(obj);这样即可避免自动更新。
地址:highlight.js进去下载common就够用了,下载完了解压如下图:新建html,如下引用:上面引入的CSS名称就是截图中styles中的css,具体样式示例可以参考:https://highlightjs.org/static/demo/然后把代码放在代码段落示例:END.
第一步:获取mysql YUM源进mysql官网获取RPM包下载地址MySQL :: Download MySQL Yum Repository进去后往下翻点击 Download右击 复制链接地址 https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm得到这个 这个就是Yum仓库的rpm包 其实就是一个下载地址第二步:下载和安装mysql源先下载 mysql源安装包[root@localhost ~]# wget https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm-bash: wget: 未找到命令我们先安装下wget yum -y install wget然后执行:(这个wget后面的地址就是刚刚复制的那个地址)wget https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm执行上面的语句后,会下载一个rpm文件,可以ll命令查看:安装mysql源:后面的安装名称就是刚刚下载的,ll命令查看到的rpm文件yum -y localinstall mysql57-community-release-el7-11.noarch.rpm 第三步:在线安装Mysqlyum -y install mysql-community-server这个下载有点耗费时间,本地一般有点慢,毕竟服务器在国外,我在服务器上安装还挺快的漫长的等待,安装完成后就可以启动mysql了第四步:启动Mysql服务systemctl start mysqld第五步:设置开机启动systemctl enable mysqldsystemctl daemon-reload第六步:修改root本地登录密码mysql安装完成之后,在/var/log/mysqld.log文件中给root生成了一个临时的默认密码。[root@localhost ~]# vi /var/log/mysqld.log进入后按一下“/”输入root@localhost,会跳转到临时密码所在地,右键复制,后面登录会用到输入登录命令:mysql -u root -pEnter password: (这里粘贴上刚刚复制的临时密码)输入临时密码 进入mysql命令行;mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'Test123456@';Query OK, 0 rows affected (0.00 sec)修改密码为 Test123456@ (备注 mysql5.7默认密码策略要求密码必须是大小写字母数字特殊字母的组合,至少8位,这个可以把策略更改,不用这么复杂,感兴趣可以自行百度解决)第七步:设置允许远程登录Mysql默认不允许远程登录,我们需要设置下,并且防火墙开放3306端口;mysql> GRANT ALL PRIVILEGES ON . TO 'root'@'%' IDENTIFIED BY 'Test123456@ ' WITH GRANT OPTION;Query OK, 0 rows affected, 1 warning (0.01 sec)mysql> exit;Bye退出下;如果你的centos没有开启防火墙,这个可以忽略[root@localhost ~]# firewall-cmd --zone=public --add-port=3306/tcp --permanentsuccess[root@localhost ~]# firewall-cmd --reloadsuccess[root@localhost ~]# 开放3306端口第八步:配置默认编码为utf8修改/etc/my.cnf配置文件,在[mysqld]下添加编码配置,如下所示:[mysqld]character_set_server=utf8init_connect='SET NAMES utf8'lower_case_table_names=1(lower_case_table_names=1 加这个的原因是,可以解决让mysql数据库对表名,字段名不区分大小写,根据个人需求自行决定加或不加)[root@localhost ~]# vi /etc/my.cnf编辑保存完 重启mysql服务;systemctl restart mysqld登录mysql,查看下编码:第九步:远程连接测试我用本机的navicat远程连接下虚拟机里的mysqlEND.
执行activeMQ启动命令后,打印无异常,访问http://ipaddress:8161/admin无法访问查看activeMQ日志如下:java.lang.IllegalStateException: LifecycleProcessor not initialized - call 'refresh' before invoking lifecycle methods via the context: org.apache.activemq.xbean.XBeanBrokerFactory$1@f6c48ac: startup date [Thu May 03 08:36:38 CST 2018]; root of context hierarchy at org.springframework.context.support.AbstractApplicationContext.getLifecycleProcessor(AbstractApplicationContext.java:360)[spring-context-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1059)[spring-context-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:1012)[spring-context-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.apache.activemq.hooks.SpringContextHook.run(SpringContextHook.java:30)[activemq-spring-5.12.0.jar:5.12.0] at org.apache.activemq.broker.BrokerService.stop(BrokerService.java:840)[activemq-broker-5.12.0.jar:5.12.0] at org.apache.activemq.xbean.XBeanBrokerService.stop(XBeanBrokerService.java:122)[activemq-spring-5.12.0.jar:5.12.0] at org.apache.activemq.broker.BrokerService.start(BrokerService.java:611)[activemq-broker-5.12.0.jar:5.12.0] at org.apache.activemq.xbean.XBeanBrokerService.afterPropertiesSet(XBeanBrokerService.java:73)[activemq-spring-5.12.0.jar:5.12.0] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)[:1.8.0_131] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)[:1.8.0_131] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)[:1.8.0_131] at java.lang.reflect.Method.invoke(Method.java:498)[:1.8.0_131] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeCustomInitMethod(AbstractAutowireCapableBeanFactory.java:1640)[spring-beans-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1581)[spring-beans-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1511)[spring-beans-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521)[spring-beans-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)[spring-beans-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293)[spring-beans-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)[spring-beans-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)[spring-beans-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:191)[spring-beans-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:636)[spring-beans-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:934)[spring-context-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)[spring-context-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.apache.xbean.spring.context.ResourceXmlApplicationContext.<init>(ResourceXmlApplicationContext.java:64)[xbean-spring-3.18.jar:3.18] at org.apache.xbean.spring.context.ResourceXmlApplicationContext.<init>(ResourceXmlApplicationContext.java:52)[xbean-spring-3.18.jar:3.18] at org.apache.activemq.xbean.XBeanBrokerFactory$1.<init>(XBeanBrokerFactory.java:104)[activemq-spring-5.12.0.jar:5.12.0] at org.apache.activemq.xbean.XBeanBrokerFactory.createApplicationContext(XBeanBrokerFactory.java:104)[activemq-spring-5.12.0.jar:5.12.0] at org.apache.activemq.xbean.XBeanBrokerFactory.createBroker(XBeanBrokerFactory.java:67)[activemq-spring-5.12.0.jar:5.12.0] at org.apache.activemq.broker.BrokerFactory.createBroker(BrokerFactory.java:71)[activemq-broker-5.12.0.jar:5.12.0] at org.apache.activemq.broker.BrokerFactory.createBroker(BrokerFactory.java:54)[activemq-broker-5.12.0.jar:5.12.0] at org.apache.activemq.console.command.StartCommand.runTask(StartCommand.java:87)[activemq-console-5.12.0.jar:5.12.0] at org.apache.activemq.console.command.AbstractCommand.execute(AbstractCommand.java:62)[activemq-console-5.12.0.jar:5.12.0] at org.apache.activemq.console.command.ShellCommand.runTask(ShellCommand.java:154)[activemq-console-5.12.0.jar:5.12.0] at org.apache.activemq.console.command.AbstractCommand.execute(AbstractCommand.java:62)[activemq-console-5.12.0.jar:5.12.0] at org.apache.activemq.console.command.ShellCommand.main(ShellCommand.java:104)[activemq-console-5.12.0.jar:5.12.0] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)[:1.8.0_131] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)[:1.8.0_131] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)[:1.8.0_131] at java.lang.reflect.Method.invoke(Method.java:498)[:1.8.0_131] at org.apache.activemq.console.Main.runTaskClass(Main.java:262)[activemq.jar:5.12.0] at org.apache.activemq.console.Main.main(Main.java:115)[activemq.jar:5.12.0] 2018-05-03 08:36:41,881 | WARN | Exception encountered during context initialization - cancelling refresh attempt | org.apache.activemq.xbean.XBeanBrokerFactory$1 | main org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.apache.activemq.xbean.XBeanBrokerService#0' defined in class path resource [activemq.xml]: Invocation of init method failed; nested exception is java.net.URISyntaxException: Illegal character in hostname at index 7: ws://VM_72_106_centos:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1514)[spring-beans-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521)[spring-beans-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)[spring-beans-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293)[spring-beans-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)[spring-beans-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)[spring-beans-3.2.11.RELEASE.jar:3.2.11.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:191)[spring-beans-3.2.11.RELEASE.jar:3.2.11.RELEASE]可以看到打印的不是ERROR错误,而是WARN警告,但是就是访问不了,网上找到原因是因为linux系统下主机名带了下划线,修改主机名,再次重启就可以正常访问了。执行hostname yourhostname可以临时修改主机名,要想永久生效,需要如下操作:vim /etc/sysconfig/network # 编辑network文件修改hostname行(重启生效),修改如下,wq保存NETWORKING=yes HOSTNAME=newhostname``` 然后修改host文件把新加的主机名映射到127.0.0.1vim /etc/hosts # 在127.0.0.1后面加上你刚新加的主机名,wq
解决方法:其实navicat自带sqlncli_x64.msi,就在安装目录下,安装后问题解决!
MQ消息队列MQ面试目标什么是MQ、为什么用MQ结合实际项目讲自己用过的案例rabbitmq/rocketmq/activemq/kafka什么区别,分别适用什么场景,怎么结合自己的业务去技术选型MQ学习笔记ActiveMQ在成熟度比较优秀,但是它的性能方面比较欠缺,所以在吞吐量不太高的中小型企业比较受欢欢迎;Kafka追求高吞吐量,一般应用在大数据,一开始目的用于日志收集和传输,它不支持事务、不追求消息传递的可靠性,所以根据业务需求自行判断是否合适;RocketMQ纯java开发,起源kafka,并不是复制kafka,基于kafka的缺点方面做了优化,比如可靠性方面,阿里对它的开源版本不支持事务,只有付费云产品才支持事务,它在阿里众多业务场景下经过不断的优化得到了逐步的完善;RabbitMQ是Erlang语言开发的开源消息队列,基于AMQP协议实现,AMQP协议的特点的可靠性、安全性比较好,基于它的性能和可靠性以及开源社区活跃的结合考量,得到了众多企业的青睐。AMQP和JMS的本质差别:JMS是基于API层面的限定,而AMQP是定义网络交换的数据格式虚拟主机的作用:类似数据库中的库概念,同一个rabbitmq服务端下可以创建多个虚拟主机,便于供不同场景或不同项目共用同一服务端提供rabbitmq的连接信息中包括了连接的用户账号和密码,而在服务端可以通过命令方式或者web管理界面中对用户的权限和虚拟主机进行管理,这样就便于程序知道连接至rabbitmq后从哪个虚拟主机中生产和消费消息据了解可以省略交换机的模式,直接将消息放置于队列queue中创建消费者demo代码示例(添加AMQP客户端依赖、服务端的虚拟主机/用户的创建/用户权限的设置、代码连接服务端、发布消息):https://www.bilibili.com/video/BV1dE411K7MG?p=5&spm_id_from=pageDriver官方示例的几种消费模型https://www.rabbitmq.com/getstarted.htmlwork queues:没有交换机订阅模式:fanout,有交换机,所有消费者无条件/无过滤的接受广播routing:direct,有交换机,队列绑定路由key,在交换机中根据路由key获取指定消息topic:基于direct的功能,可以使用通配符,简化过滤规则集群主从复制集群:不可靠,从节点只能在队列看到队列信息,无法正常使用队列信息,如果主节点宕机,整个系统不可用镜像集群:实际上就是rabbitmq提供的策略模式,基于主从设置策略后达到自动/手动同步,实现高可用学习MQ疑问怎么改端口?(默认服务端口5672/默认web管理界面端口15672/集群的端口25672)
Day 11. JDK版本之间的差异相关问题2. 怎么通过maven设置构建项目的jdk版本:profiles3. spring boot应用如何打包成一个可运行的jar包要创建一个可执行jar,我们需要将spring-boot-maven-plugin添加到我们的pom.xml中。要做到这一点,请在dependencies部分下面插入以下几行:<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>4. spring boot starter是什么,它有哪些类型的starterhttps://docs.spring.io/spring-boot/docs/2.4.0-SNAPSHOT/reference/html/using-spring-boot.html#using-boot5. spring boot为什么能从application.properties或者yaml文件中取配置应该是从在启动类底层代码中固定的配置文件名称6. 怎么通过spring boot获取配置文件中的值、yaml支持的数据类型要加@Compent将类标记为容器中的一个组件注解 org.springframework.boot.context.properties.ConfigurationProperties,需要匹配配置文件中的前缀prefix用法示例:@ConfigurationProperties(prefix = "person")@ConfigurationProperties(prefix = "person") @Compent public Class Person { private String key1; private String key2; // set get ... }在yaml文件中就以:person: key1: value1 key2: value2使用@Value7. @Autowire和@Resource区别1.@Autowire是Spring开发的,而@Resource是jdk开发的2.@Autowire是按照type来注解的,而@Resource是按照名称来的,如果名称找不到,那么就按照type截至https://www.bilibili.com/video/BV1gW411W76m?p=13从14开始看Day 21. @PropertySource默认是从根目录的application.properties或application.yaml获取,可以通过@PropertySource指定配置文件目录和名称2. @ImportResource@ImportResource(locations = {"classpath:bean.xml"})可以支持Spring时期使用的xml配置方式3. @Configuration+@Bean的便捷方式往IOC容器中配置组件4. 配置文件占位符支持随机数,包括整数、字符串uuid等5. Profile激活方式spring.profiles.active=dev对应application-dev.properties/ymlyml文件可使用---来分隔文档块,每一块都可以理解为一个profile的配置块,指定active后对应文档块的配置生效也可以使用启动的参数配置, java -jar x.jar--spring.profiles.active=dev6. 配置文件的优先级,以下四个目录都会加载,由高到低,高覆盖低,可以利用优先级实现互补配置spring.config.location可以用作命令行参数7. 自动配置截至:https://www.bilibili.com/video/BV1gW411W76m?p=19Day 31. @Conditional当满足某个条件时,才往容器中注入该Bean2. 什么是SpEL表达式SpEL(Spring Expression Language),即Spring表达式语言。它是一种类似JSP的EL表达式、但又比后者更为强大有用的表达式语言。为什么要用SpEL:因为它可以在spring容器内实时查询和操作数据,尤其是操作List列表型、Array数组型数据。所以使用SpEL可以有效缩减代码量,优化代码结构,笔者认为很有用3. 配置debug启动启动项目,控制台打印自动配置报告,方便得知哪些自动配置类生效Positive matches:启用的、匹配上的自动配置类Negative matches:没有启动、没有匹配上的自动配置类4. 日志介绍SLF4J是一种抽象,它对应的实现有Log4J/Logback,抽象和两种实现都出自同一人之手Logback是继Log4J出现性能问题后的另实现的一套框架SLF4J理解为一种抽象、公认的规范,你系统要记录日志,我这个规范能满足你、也能约束你实现的更好,而实现这一规范就按需进行了,世面上有些已有的,开发人员也可根据自己需要自己按规范实现,slf4j-api.jar就是规范的引入,再往下一层引入该规范的实现,实现比如null、logbak、log4j、java.util .logging等等每个框架都有自己的日志用法,可能每种框架都用各自不同的日志框架,而Spring Boot这样的框架是一个集结多种框架于一体的开发解决方案,比如它有Spring/MyBatis/Hibernate/MQ...,各自用各自的日志就太过于混乱,slf4j提供了一套日志统一解决方案,大致原理如下:已知市面上流行的所有日志框架将它们与SLF4J进行一个转换,比如ALogging框架中的XX类,在其对应转换的Jar包中有同样的接口名称,但是其对应的实现类就用SLF4J的实现类这样的替换包流行的有以下几种:jcl-over-slf4j jul-to-slf4j log4j-over-slf4j5. spring boot 日志场景、启动器spring boot日志相关的底层依赖关系spring boot 底层使用slf4j+logback方式进行日志记录将其他框架中的日志依赖转换为slf4j排除掉每个框架默认的日志,排除示例如下<dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-console</artifactId> <version>${activemq.version}</version> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency>在正常开发中,日志对应的级别,spring boot默认设置为info,可以指定报名改变日志打印级别,级别分高低,如图# 指定报名设置日志打印级别,以下是设置了com.nobt包下的类打印都以trace级别打印 logging.level.com.nobt=trace # 指定日志文件目录 logging.path=/spring/log # 不指定路径在当前项目下生成springboot.log日志 # 可以指定完整的路径 logging.file=G:/springboot.log官方文档中有这么一句:If you want to write log files in addition to the console output youneed to set a logging.file or logging.path property也就是说,它们不会同时生效,只配置其中一个就好了。例如我配置的时候只指定pathlogging.path = ./logs那么记录日志的时候默认的文件名是:spring.log截至https://www.bilibili.com/video/BV1gW411W76m?p=26Day 4自己搭建的hello world maven 工程Junit一直不正常,故拉取 ityouknow 的教程合集,看了几个快速简单的,跟一两年前一样,上手写业务代码都是照葫芦画瓢,但是细节上的配置还需要熟悉,比如 maven 对应的好些配置,是不了解、不知道怎么配置的。<project> <modelVersion>4.0.0</modelVersion> <!--maven2.0必须是这样写,现在是maven2唯一支持的版本--> <!-- 基础设置 --> <groupId>...</groupId> <artifactId>...</artifactId> <version>...</version> <packaging>...</packaging> <name>...</name> <url>...</url> <dependencies>...</dependencies> <parent>...</parent> <dependencyManagement>...</dependencyManagement> <modules>...</modules> <properties>...</properties> <!--构建设置 --> <build>...</build> <reporting>...</reporting> <!-- 更多项目信息 --> <name>...</name> <description>...</description> <url>...</url> <inceptionYear>...</inceptionYear> <licenses>...</licenses> <organization>...</organization> <developers>...</developers> <contributors>...</contributors> <!-- 环境设置--> <issueManagement>...</issueManagement> <ciManagement>...</ciManagement> <mailingLists>...</mailingLists> <scm>...</scm> <prerequisites>...</prerequisites> <repositories>...</repositories> <pluginRepositories>...</pluginRepositories> <distributionManagement>...</distributionManagement> <profiles>...</profiles> </project>fork ityouknow 的spring boot教程并拉取本地环境搭建https://gitee.com/nobt/spring-boot-examplesDay 5spring boot admin 和 spring boot actuator这两者的关系描述:Spring Boot Admin就是将Spring Boot Actuator中提供的endpoint信息可视化表示,在BookPub应用(被监控)的这一端,只需要进行一点配置即可。也就是说Admin 依赖 Actuator,从pom 依赖关系中找到体现:<!-- spring-boot-admin-server.pom --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> <version>2.1.0.RELEASE</version> <scope>compile</scope> </dependency>Admin 可以做以下功能:监控你的 Spring Boot 程序,支持异常邮件通知大体上有个了解,细节上的API、用法需要时再查阅spring 断言用法示例spring的底层也较多的用到了该用法,其实就是个方法抽离的用法org.springframework.util.Assert 的注释如下:断言实用工具类,帮助验证参数。有助于在运行时早期和清晰地识别程序员错误。例如,如果一个公共方法的契约声明它不存在,允许{@code null}参数,{@code Assert}可以用来验证。这样做就清楚地表明违反了约定发生并保护类的不变量。通常用于验证方法参数,而不是配置属性。带着疑问阅读源码BeanA中注入BeanB,或者依赖注解@DependsOn 他们在容器注册Bean时怎么确认这个先后顺序getBean、doGetBean、createBean、doCreateBeanbanner在哪个环节加载的、加载目录、文件名称启动的第一步就是去找banner// 1. 启动类的构造方法中 // org.springframework.boot.SpringApplication.run(String...) public ConfigurableApplicationContext run(String... args) { ... Banner printedBanner = printBanner(environment); ... } return context; } // 2. org.springframework.boot.SpringApplication.printBanner(ConfigurableEnvironment) // 3. org.springframework.boot.SpringApplicationBannerPrinter.print(Environment, Class<?>, PrintStream) // 4. org.springframework.boot.SpringBootBanner.printBanner(Environment, Class<?>, PrintStream) // 会有获取的操作,获取不到就打印默认的: // 此方法中会循环打印静态变量:org.springframework.boot.SpringBootBanner.BANNER,默认就是spring的banner样式 class SpringBootBanner implements Banner { private static final String[] BANNER = { "", " . ____ _ __ _ _", " /\\\\ / ___'_ __ _ _(_)_ __ __ _ \\ \\ \\ \\", "( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\", " \\\\/ ___)| |_)| | | | | || (_| | ) ) ) )", " ' |____| .__|_| |_|_| |_\\__, | / / / /", " =========|_|==============|___/=/_/_/_/" }; private static final String SPRING_BOOT = " :: Spring Boot :: "; private static final int STRAP_LINE_SIZE = 42; @Override public void printBanner(Environment environment, Class<?> sourceClass, PrintStream printStream) { for (String line : BANNER) { printStream.println(line); } String version = SpringBootVersion.getVersion(); version = (version == null ? "" : " (v" + version + ")"); String padding = ""; while (padding.length() < STRAP_LINE_SIZE - (version.length() + SPRING_BOOT.length())) { padding += " "; } printStream.println(AnsiOutput.toString(AnsiColor.GREEN, SPRING_BOOT, AnsiColor.DEFAULT, padding, AnsiStyle.FAINT, version)); printStream.println(); } }配置文件从哪读取的、配置文件所在位置优先级定义、配置文件名称定义、properties/yml的解析逻辑CSDN说明环境变量配置文件实现类properties和xml对应一个实现类:org.springframework.boot.env.PropertiesPropertySourceLoaderyml和yaml对应一个实现类:org.springframework.boot.env.YamlPropertySourceLoader国际化如何使用、配置、解析// Initialize message source for this context.initMessageSource();能否理清refresh 方法逻辑走向、子父类关系org.springframework.context.support.AbstractApplicationContext.refresh()spring boot默认的server.port为什么是8080server.port指定web服务的端口号,只要是application或者是yml文件中支持配置的,都会有对应的属性类进行获取配置的这些值,获取到后进行相应设置,所有的配置都有默认值,这从哪体现呢,从spring-boot-hello-world 的程序中不添加application配置文件或文件中为空,程序仍然正常启动而server.port 对应的属性类文件是:org.springframework.boot.autoconfigure.web.ServerProperties.class@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)加上 @ConfigurationProperties 代表该类是一个属性文件类,prefix 指定该类从配置文件中解析相关配置的前缀,也就是诸如 server.xxx 样的配置,将都会被它一一对应,比如 server.port 那在该类中就有个 port 字段,如果在配置文件中配了一个该 server.yyy,这个yyy在该类中没有对应的字段绑定,可能会导致报错,所以,加上了注解属性:ignoreUnknownFields = true 意为忽略未知字段而当你不配置server.port时,它默认使用8080,是为什么,来按这个顺序看看在spring boot启动时创建Tomcat的逻辑:1. org.springframework.context.support.AbstractApplicationContext.onRefresh() 2. org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh() 3. org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer() 4. org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getWebServerFactory() 5. 再走到这 // 它根据ConditionalOnClass和ConditionalOnMissingBean来控制是否向容器中注入该Bean,这就是在创建一个Tomcat的 @Configuration @ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class }) @ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT) public static class EmbeddedTomcat { @Bean public TomcatServletWebServerFactory tomcatServletWebServerFactory() { return new TomcatServletWebServerFactory(); } } 6. 再后置处理器将applicaiton或yml文件中有关tomcat的配置给Tomcat设置上 org.springframework.boot.autoconfigure.web.embedded.TomcatWebServerFactoryCustomizer.customize(ConfigurableTomcatWebServerFactory factory) 7. 在此过程中它默认使用的是Tomcat,将会创建一个Tomcat对象,而Tomcat对象中,port字段默认值就是8080为什么默认8080,总结为一句话:因为Tomcat端口默认值就是8080所以一开始的猜测,它是在哪默认配置的,比如通过server.port,不是的还全局搜索搜索到了 /META-INF/spring-configuration-metadata.json 里面有server.port 描述为8080,其实不是,这是在properties或yml配置文件中添加配置时的提示来源,看看官方的介绍:元数据官方解释该提示功能需要在pom.xml中引入依赖:<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>精美的类设计org.springframework.boot.autoconfigure.web.ResourceProperties它的功能就是从配置文件中映射spring.resources前缀的配置,到这些属性里面去,这样嵌套的静态内部类如果让我写,我现在也只知道按类名区分开来写,但是写完后,spring.resources就套不了娃了,他这样可以套娃,用一个类可以支持resources这一类的所有配置,还清晰分层设计模式一直以来,设计模式都是面试的高频词汇,可能简单的总是就说单例、工厂等,但是如果想读懂spring里面各个功能,比如较为复杂的后置处理器,需要学习设计模式后加上手写Spring等教程
Git 忽略规则优先级在 .gitingore 文件中,每一行指定一个忽略规则,Git 检查忽略规则的时候有多个来源,它的优先级如下(由高到低):从命令行中读取可用的忽略规则当前目录定义的规则父级目录定义的规则,依次递推$GIT_DIR/info/exclude 文件中定义的规则core.excludesfile中定义的全局规则Git 忽略规则匹配语法在 .gitignore 文件中,每一行的忽略规则的语法如下:空格不匹配任意文件,可作为分隔符,可用反斜杠转义开头的文件标识注释,可以使用反斜杠进行转义! 开头的模式标识否定,该文件将会再次被包含,如果排除了该文件的父级目录,则使用 ! 也不会再次被包含。可以使用反斜杠进行转义/ 结束的模式只匹配文件夹以及在该文件夹路径下的内容,但是不匹配该文件/ 开始的模式匹配项目跟目录如果一个模式不包含斜杠,则它匹配相对于当前 .gitignore 文件路径的内容,如果该模式不在 .gitignore 文件中,则相对于项目根目录** 匹配多级目录,可在开始,中间,结束? 通用匹配单个字符[] 通用匹配单个字符列表常用匹配示例:bin/: 忽略当前路径下的bin文件夹,该文件夹下的所有内容都会被忽略,不忽略 bin 文件/bin: 忽略根目录下的bin文件/*.c: 忽略 cat.c,不忽略 build/cat.cdebug/*.obj: 忽略 debug/io.obj,不忽略 debug/common/io.obj 和 tools/debug/io.obj**/foo: 忽略/foo, a/foo, a/b/foo等a/**/b: 忽略a/b, a/x/b, a/x/y/b等!/bin/run.sh: 不忽略 bin 目录下的 run.sh 文件*.log: 忽略所有 .log 文件config.php: 忽略当前路径的 config.php 文件.gitignore规则不生效.gitignore只能忽略那些原来没有被track的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。解决方法就是先把本地缓存删除(改变成未track状态),然后再提交:git rm -r --cached .git add .git commit -m 'update .gitignore'你想添加一个文件到Git,但发现添加不了,原因是这个文件被.gitignore忽略了:$ git add App.classThe following paths are ignored by one of your .gitignore files:App.classUse -f if you really want to add them.如果你确实想添加该文件,可以用-f强制添加到Git:$ git add -f App.class或者你发现,可能是.gitignore写得有问题,需要找出来到底哪个规则写错了,可以用git check-ignore命令检查:$ git check-ignore -v App.class.gitignore:3:*.class App.classGit会告诉我们,.gitignore的第3行规则忽略了该文件,于是我们就可以知道应该修订哪个规则。
如下命令:git rm -r --cached [具体文件名,可包含文件夹路径]示例:git rm -r --cached folderName/fileNamegit commit -m "remark"git push
说明使用JXLS根据模板填充数据时,若模板上绑定的标签中含中文将会报错详细字段绑定一个详细字段,若在模板绑定成:${test.姓名},将会报错如下:2021-01-28T11:13:58.284+08:00 [main] [org.jxls.transform.poi.PoiTransformer] [ERROR] - Failed to write a cell with CellData{Sheet2!C3, cellType=STRING, cellValue=${test.姓名}} and context keys [img, test2, test.name, student, nowdate, test.姓名, employees1, employees2, employees, test1] org.jxls.expression.EvaluationException: An error occurred when evaluating expression test.姓名 at org.jxls.expression.JexlExpressionEvaluator.evaluate(JexlExpressionEvaluator.java:70) ~[jxls-2.9.0.jar:?] at org.jxls.common.CellData.evaluate(CellData.java:292) ~[jxls-2.9.0.jar:?] at org.jxls.common.CellData.evaluate(CellData.java:262) ~[jxls-2.9.0.jar:?] at org.jxls.transform.poi.PoiCellData.writeToCell(PoiCellData.java:129) ~[jxls-poi-1.0.15.jar:?] at org.jxls.transform.poi.PoiTransformer.transform(PoiTransformer.java:152) ~[jxls-poi-1.0.15.jar:?] at org.jxls.area.XlsArea.transformStaticCell(XlsArea.java:427) ~[jxls-2.9.0.jar:?] at org.jxls.area.XlsArea.transformTopStaticArea(XlsArea.java:400) ~[jxls-2.9.0.jar:?] at org.jxls.area.XlsArea.applyAt(XlsArea.java:165) ~[jxls-2.9.0.jar:?] at org.jxls.util.JxlsHelper.processTemplate(JxlsHelper.java:222) ~[jxls-2.9.0.jar:?] at com.sunwayworld.jxls.JxlsUtils.exportExcel(JxlsUtils.java:37) ~[classes/:?] at com.sunwayworld.jxls.ObjectCollectionDemo.main(ObjectCollectionDemo.java:72) ~[classes/:?] Caused by: org.apache.commons.jexl3.JexlException$Tokenization: org.jxls.expression.JexlExpressionEvaluator.evaluate@1:6 tokenization error in '' at org.apache.commons.jexl3.JexlEngine.createExpression(JexlEngine.java:304) ~[commons-jexl3-3.1.jar:3.1] at org.jxls.expression.JexlExpressionEvaluator.evaluate(JexlExpressionEvaluator.java:65) ~[jxls-2.9.0.jar:?] ... 10 more解决办法,改为:${test."姓名"}表格绑定若是表格的模板绑定如下:解决办法也就是涉及标签中包含中文的,就将标签中文部分用双引号包裹即可为什么出现中文在出现问题后,网上查找到的几乎算是没找到解决办法,可能大家都不涉及到标签含中文的情况吧,都是将模板所需数据来源定义为对象或List为什么会有中文标签的用法,比如表格的数据源支持List<Bean类型>的集合,也支持List<Map<String, Object>>这样的集合类型,自定义SQL,将SQL查询结果集作为JXLS模板表格的数据来源,若SQL中列为中文别名则会出现需要绑定标签含中文的情况JXLS标签中含中文报错的原因这个原因经过排查,暂时没找到,但是经过自己尝试后发现标签中用英文双引号包裹中文部分可以支持,大致的原因应该如下:// java语法不支持这样的定义 String name = 姓名; // 支持这样的定义
2021年09月