有关软件开发编程知识及学习心得
3月20
redis读取数据失败,打印异常信息如下:
Could not read JSON: Invalid UTF-32 character 0x22636364 (above 0x0010ffff) at char #15, byte #63); nested exception is java.io.CharConversionException: Invalid UTF-32 character 0x22636364 (above 0x0010ffff) at char #15, byte #63)

问题的原因是我在添加数据时设置了存活时间但是忘记指定单位了;
正确的应该是再指定TimeUnit.SECONDS参数。
时间单位:
天:TimeUnit.DAYS
小时:TimeUnit.HOURS
分钟:TimeUnit.MINUTES
秒:TimeUnit.SECONDS
毫秒:TimeUnit.MILLISECONDS
3月17
下面列举下EasyPoi支持的指令以及作用,最主要的就是各种fe的用法文字
三元运算 {{test ? obj:obj2}}
n: 表示 这个cell是数值类型 {{n:}}
le: 代表长度{{le:()}} 在if/else 运用{{le:() > 8 ? obj1 : obj2}}
fd: 格式化时间 {{fd:(obj;yyyy-MM-dd)}}
fn: 格式化数字 {{fn:(obj;###.00)}}
fe: 遍历数据,创建row
!fe: 遍历数据不创建row
$fe: 下移插入,把当前行,下面的行全部下移.size()行,然后插入
#fe: 横向遍历
v_fe: 横向遍历值
!if: 删除当前列 {{!if:(test)}}
单引号表示常量值 ‘’ 比如’1’ 那么输出的就是 1
&NULL& 空格
&INDEX& 表示循环中的序号,自动添加,看到这里应该就明白怎么在表格中增加一列序号了。
]] 换行符 多行遍历导出
sum: 统计数据
3月8
1、前端封装JSON值,后台需要List<实体类>接收

Map map = jsonObject.getInnerMap();
List<RecommendDTO> recommendDTOlist = (List<RecommendDTO>) map.get("xxx");

2、进行forearch循环的时候报错

recommendDTOlist .forEach((item)->{})

3、从redis中获取数据后进行遍历
List<RecommendDTO> recommendDTOlist = redisUtil.get(defaultCacheKey);
for (RecommendDTO recommendDTO : defaultRecommendList) {

}

报错信息:

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.heckjj.apps.modules.smartpush.dto.RecommendDTO

4、打断点调试查看发现里面封装的是两个Map 而不是实体类而是个LinkedHashMap

5、解决方法

ObjectMapper mapper = new ObjectMapper();
List<RecommendDTO> recommendDTOlist = (List<RecommendDTO>) map.get("xxx");
List<RecommendDTO> recommendDTOlist = mapper.convertValue(list1, new TypeReference<List<RecommendDTO>>() { });

记住引入包路径是下面这两个

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
1月10
系统中对密码复杂度的校验是比较常见的工作,往往我们可以通过正则来实现,或者基于规则而实现特定的算法来满足需求。

下面我来介绍两个开源的解决方案。

1.使用vt-password来实现密码复杂度的检查
VT 密码是一个 Java 库,用于验证密码是否符合定义的规则集。
该库包括以下规则实现:

AllowedCharacterRule - 密码是否只包含特定的字符列表
AlphabeticalSequenceRule - 密码是否包含字母顺序
CharacterCharacteristicRule - 密码是否包含所需的字符类型组合
DictionaryRule - 密码是否与字典中的单词匹配
DictionarySubstringRule - 密码是否包含字典中的单词
DigitCharacterRule - 密码是否包含数字
HistoryRule - 密码是否与以前的密码匹配,支持散列
IllegalCharacterRule - 密码是否包含非法字符
LengthRule - 是一定长度的密码
LowercaseCharacterRule - 密码是否包含小写字符
NonAlphanumericCharacterRule - 密码是否包含非字母数字字符
NumericalSequenceRule - 密码是否包含数字序列
RegexRule - 密码是否与正则表达式匹配
RepeatCharacterRegexRule - 密码是否包含重复字符
SequenceRule - 密码是否包含键盘序列
SourceRule - 密码是否与来自另一个系统或来源的密码匹配
QwertySequenceRule - 密码是否包含 QWERTY 键盘序列
UppercaseCharacterRule - 密码是否包含大写字符
UsernameRule - 密码是否包含用户名
WhitespaceRule - 密码是否包含空格
如果你想在你的Maven构建中使用这个项目,请在你的pom.xml 中包含以下内容:

<dependency>
  <groupId>edu.vt.middleware</groupId>
  <artifactId>vt-password</artifactId>
  <version>3.1.2</version>
</dependency>
12月9
公司有个项目不能解析内网所以需要对本地hosts文件进行修改,添加一条本地域名解析记录,如果让客户去操作,很容易破坏掉原先的hosts文件,用户只需要以管理员权限运行即可,如果记录存在则替换掉。
由于办公电脑都使用信创麒麟的系统,所以最好做一个deb的安装包,通过程序写修改的,在信创麒麟的系统电脑下载安装即可执行。
下面是实现逻辑,要将java打包成deb安装包就需要使用jdeb的maven插件来打包。
我使用的是1.8的版本,具体配置就不贴上来了,需要的联系我。
               <artifactId>jdeb</artifactId>
                <groupId>org.vafer</groupId>
                <version>1.8</version>


package com.nine.rivers.jdeb;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.util.StrUtil;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
* @Description 不破坏原有hosts文件,支持新host绑定或修改支持host解绑
* @Date 2022/12/9 16:42
* @Author heck
**/
public class HostUtil {

    public static final String LINUX = "linux";
    public static final String LINUX_HOSTS_PATH = "/etc/hosts";
    public static final String WINDIR = "windir";
    public static final String WIN_HOSTS_PATH = "\\system32\\drivers\\etc\\hosts";
    public static final String OS_NAME = "os.name";

    /**
     * 获取host文件路径
     *
     * @return
     */
    public static String getHostFile() {
        String fileName = null;
        // 判断系统
        if (LINUX.equalsIgnoreCase(System.getProperty(OS_NAME))) {
            fileName = LINUX_HOSTS_PATH;
        } else {
            fileName = System.getenv(WINDIR) + WIN_HOSTS_PATH;
        }
        return fileName;
    }
11月30
原因:SpringBoot内嵌web容器,其特点是只有一个jar文件,在容器启动后不会解压缩。

解决方式:

1. 必须使用相对路径读取文件;

假设你的模板文件放在了 resources —> templates —> test.xlsx

2. 只能使用流去读取,不能用file;

  // jar里面文件读取方式:
  ClassPathResource classPathResource = new ClassPathResource("templates/test.xlsx");
  // 获取文件流
  classPathResource .getInputStream();

如果要将流存储到数组中如下:

  /**
     * 输出流转字节数组
     * @param input 输出流
     * @return 字节数组
     */
    public static byte[] toByteArray(InputStream input) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024 * 4];
        int size = 0;
        while (-1 != (size = input.read(buffer))) {
            output.write(buffer, 0, size);
        }
        return output.toByteArray();
    }
11月27
Archetype是用于创建项目的骨架(或者模板),通过Archetype我们可以创建类似的Maven工程,同时Archetype能够极大的简化我们创建一个工程的步骤和流程。这里我将介绍自定义Maven的工程模板Archetype的方法和流程,这里采用的方法是从现有工程创建工程模板。

关于Archetype介绍参考:Introduction to Archetypes

一、Archetype自定义流程:
1、创建模板工程:找到一个现有的项目,进行编辑,将项目中的包结构、各类文件放置到合适的位置;



2、从模板工程创建Archetype:打开cmd窗口,切换当前目录到上面的工程目录下,执行maven命令:

mvn archetype:create-from-project
执行完成后,target/generated-sourced/archetype目录下就是我们需要的项目模板。

3、安装Archetype到本地仓库:cd进入target/generated-sourced/archetype中,执行命令:

mvn -Dmaven.test.skip=true clean install
将自定义Archetype安装到本地仓库即可:此时,自定义archetype就被安装到settings.xml中<localRepository>指定的本地仓库中,我的机器本地目录是D:/q/repos-maven;另外,archetype安装到本地仓库后,会在.m2/archetype-catalog.xml中加入对应的archetype节点,结构如下:

<archetype>

      <groupId>com.heckjj.blog</groupId>

      <artifactId>crm-archetype-archetype</artifactId>

      <version>1.0.0</version>

      <description>The parent pom of crm</description>

    </archetype>



4、使用自定义Archetype创建工程:

这样我们就创建成功了自定义的Archetype,可以通过命令从本地模板创建工程:

mvn archetype:generate -DarchetypeCatalog=local
以上就是创建自定义Archetype的简单流程。
11月24

PF4J的了解和使用

22:09编程杂谈  From: 本站原创
在平时编码过程中我们都知道要抽象,要封装变化,要实现开闭原则,比如对于很多相似的功能,我们可以将通用的功能抽象出来,然后把变化的不同的地方提取出去,比如模版模式、策略模式等都是实现类似的效果

比如对于策略模式,我们通常是定义一个接口,然后有不同的实现,这种是可以的,但是如果通用流程中要扩展的点较多的话,这些不同的实现也需要管理,可以把他们合并到一个单独的包中,再进一步,我们甚至可以将包单独提取出来,支持运行时加载包实现新增功能的支持

JDK对此功能的支持就是 SPI,但是它的限制较多,也不够灵活,比如dubbo就是自己定义了一套SPI的实现,这次我们来看另一个实现,pf4j 提供一套在基本框架中定义扩展点接口,然后通过不同的插件来实现扩展点的功能,来支持对新增开放对修改关闭

下面我们就来学习一下它的使用

使用
比如我们有一套通用的流程,假设是下单流程,不同的业务线等对于下单都有一些特殊点,但是它们的基本流程是相似的,这时候我们就可以先定义好通用的流程,不同的地方预留出扩展点接口,使用 pf4j 的流程如下

先定义好扩展点接口(需要定义单独的包,因为基本应用和各个扩展点的包都依赖它)
定义单独的插件包,其中实现扩展点接口的功能
在应用中编写基本流程和扩展点的发现使用功能
这次我们就参考 pf4j 提供的例子来看一下

1. 定义扩展点接口
pom.xml首先声明依赖

<dependency>
    <groupId>org.pf4j</groupId>
    <artifactId>pf4j</artifactId>
    <version>3.6.0</version>
    <!-- 一般应用中会依赖这个包,所以这里设置为provided即可 -->
    <scope>provided</scope>
</dependency>
之后即可声明各个扩展点接口

/**
* 假设我们需要一个通知用户的功能
* 需要注意的是,我们一定要继承 ExtensionPoint 接口,表示这是一个扩展点
*/
public interface Notice extends ExtensionPoint {
    boolean notice(List<Long> userIds);
}
11月24
PF4J是一个Java轻量级的插件框架,可以实现动态加载,执行,卸载外部插件(支持jar以及zip),具体可以看官网:https://pf4j.org/。

本文例子基于Github地址:https://github.com/pf4j/pf4j

<dependency>
  <groupId>org.pf4j</groupId>
  <artifactId>pf4j</artifactId>
  <version>3.6.0</version>
</dependency>
插件项目会涉及到3个工程:工程结构
plugin-api:定义可扩展接口
plugins:插件项目,可以包含多个插件,需要实现plugin-api中定义的接口
plugin-app:主程序,需要依赖plugin-api,加载并执行plugins
定义可扩展接口(plugin-api)
简单定义一个接口,需继承ExtensionPoint:

package plugin.api;

import org.pf4j.ExtensionPoint;

public interface Greeting extends ExtensionPoint {

    String getGreeting();
}
实现插件(plugins)
插件需要实现plugin-api定义的接口,并且使用@Extension标记:
package plugins;

import org.pf4j.Extension;
import plugin.api.Greeting;

@Extension
public class WelcomeGreeting implements Greeting {

    public String getGreeting() {
        return "Welcome";
    }
}

插件打包(plugins)
插件打包时,需要往MANIFEST.MF写入插件信息,此处使用maven插件(打包命令为package):
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  <version>2.3.1</version>
  <configuration>
    <archive>
      <manifestEntries>
        <Plugin-Id>welcome-plugin</Plugin-Id>
        <Plugin-Version>0.0.1</Plugin-Version>
      </manifestEntries>
    </archive>
  </configuration>
</plugin>
11月22
运行SpringBoot的时候报如下错Consider defining a bean of type ‘com.google.code.kaptcha.Producer’ in your configuration.

报错原因为配置中找不到一个指定自动注入类型的bean。
那么我们要从collecter层开始查找,点击service层,看service实现类是否加上@Service或者@Component,检查service实现类是否有implements service。如果这些都没有问题:

我们来看@SpringBootApplication,点过去。可以看到有个@ComponentScan,ComponentScan做的事情就是告诉Spring从哪里找到bean

那可以直接在@SpringBootApplication加上

还有一种问题,你的spring启动类不在同一个父包路径下,比如你的其它类在com.heckjj.blog,而你的启动类在heckjj下,也会报错扫不到其它的类,比如说service找不到。
分页: 1/19 第一页 1 2 3 4 5 6 7 8 9 10 下页 最后页 [ 显示模式: 摘要 | 列表 ]