java基础进阶-工作日常使用

文章目录

  • 工作日常方法总结
  • 一、数据库多数据源使用配置
    • 1.注解
    • 2.实现
    • 3.使用
  • 二、list对象多属性去重
    • Image转换base64
    • base64转换file文件
    • httpClient

工作日常方法总结

一、数据库多数据源使用配置

运用了Aop的概念—Aop加强的使用

1.注解

//范围
@Target(ElementType.METHOD)
//生存周期
@Retention(RetentionPolicy.RUNTIME)
//类继承关系中,子类会继承父类使用的注解中被@Inherited修饰的注解-允许子类继承父类中的注解
@Inherited
//指明修饰的注解,可以被例如javadoc此类的工具文档化,只负责标记,没有成员取值
@Documented
public @interface MultiDataSourceTransactional {

    /**
     * 事务管理器数组
     * @return
     */
    String[] transactionManagers();
}

2.实现

@Component
@Aspect
public class MultiDataSourceTransactionAspect {
    /**
     * 线程本地变量->栈->为了达到后进先出的效果
     */
    private static final ThreadLocal<Stack<Map<DataSourceTransactionManager, TransactionStatus>>> THREAD_LOCAL = new ThreadLocal<>();

    /**
     * 事务管理器
     */
    @Autowired
    private ApplicationContext applicationContext;

    private DefaultTransactionDefinition definition =new DefaultTransactionDefinition();
    {
        //非只读模式
        definition.setReadOnly(false);
        //事务隔离:数据库的
        definition.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);
        //传播行为
        definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
    }

    /**
     * 切面
     */
    @Pointcut("@annotation(com.learnta.dms.service.annotation.MultiDataSourceTransactional)")
    public void pointcut(){ }

    /**
     * 声明事务
     */
    @Before("pointcut() && @annotation(transactional)")
    public void before(MultiDataSourceTransactional transactional){
        // 根据设置的事务名称按顺序声明,并放到ThreadLocal里
        String[] transactionManagerNames = transactional.transactionManagers();
        Stack<Map<DataSourceTransactionManager, TransactionStatus>> pairStack = new Stack<>();
        for (String transactionManagerName : transactionManagerNames) {
            DataSourceTransactionManager transactionManager = applicationContext.getBean(transactionManagerName, DataSourceTransactionManager.class);
            TransactionStatus transactionStatus = transactionManager.getTransaction(definition);
            Map<DataSourceTransactionManager, TransactionStatus> transactionMap = new HashMap<>();
            transactionMap.put(transactionManager, transactionStatus);
            pairStack.push(transactionMap);
        }
        THREAD_LOCAL.set(pairStack);
    }

    /**
     * 提交事务
     */
    @AfterReturning("pointcut()")
    public void afterReturning(){
        //栈顶弹出(后进先出)
        Stack<Map<DataSourceTransactionManager, TransactionStatus>> pairStack = THREAD_LOCAL.get();
        while (CollectionUtils.isNotEmpty(pairStack)) {
            Map<DataSourceTransactionManager, TransactionStatus> pair = pairStack.pop();
            pair.forEach((key,value)->key.commit(value));
        }
        THREAD_LOCAL.remove();
    }

    /**
     * 回滚事务
     */
    @AfterThrowing(value = "pointcut()")
    public void afterThrowing(){
        // ※栈顶弹出(后进先出)
        Stack<Map<DataSourceTransactionManager, TransactionStatus>> pairStack = THREAD_LOCAL.get();
            while (CollectionUtils.isNotEmpty(pairStack)) {
                Map<DataSourceTransactionManager, TransactionStatus> pair = pairStack.pop();
                pair.forEach((key, value) -> key.rollback(value));
        }
        THREAD_LOCAL.remove();
    }
}

3.使用

@MultiDataSourceTransactional(transactionManagers = {"defaultTransactionManager", "dmsTransactionManager"})

二、list对象多属性去重

1.方法
/**
 * 用于对象去重
 * @param keyExtractor 需要去重的属性
 * @param 
 * @return
 */
public static <T> Predicate<T> distinctByKeyExtractor(Function<? super T, ?> keyExtractor) {
    //记录已有对象或者属性
    ConcurrentSkipListMap<Object,Boolean> skipListMap = new ConcurrentSkipListMap<>();
    //获取对象的属性值,且使用putIfAbsent判断存在则不添加到map而且返回数值不存在则添加返回null,value恒定为true
    //JSONObject.toJSONString(keyExtractor.apply(t)) 是为了解决null参数和对象比较的问题
    //在Stream distinct()中使用了支持null为key的hashSet来进行处理 java/util/stream/DistinctOps.java:90  但是没有解决对象比较的问题
    //所以虽然序列化消耗性能但是也没有更好的办法
    Predicate<T> predicate = t -> skipListMap.putIfAbsent(JSONObject.toJSONString(keyExtractor.apply(t)), Boolean.TRUE) == null;
    return predicate;
}

2.用法
grades.stream().filter(CommonUtil.distinctByKeyExtractor(grade->Stream.of(grade.getGrade(),grade.getGradeName()).toArray())).collect(Collectors.toList())

Image转换base64

/**
* 图片转换base64
* @param imageUrl 图片路径-可以自己拼接,也可以直接使用网络图片
* @return
*/
 public static String encodeImageToBase64(String imageUrl) {
        Long startImage = System.currentTimeMillis();
        if (StringUtils.isBlank(imageUrl)) return null;
        ByteArrayOutputStream outputStream = null;
        try {
            URL url = new URL(imageUrl);
            BufferedImage bufferedImage = ImageIO.read(url);
            outputStream = new ByteArrayOutputStream();
            //png 是支持我自己服务器的格式 可以自己修改,其他格式我服务器会IO异常
            ImageIO.write(bufferedImage,"png",outputStream);
        } catch (Exception e) {
            logger.error("picture transformation error exception={}", e);
            //异常捕捉,是否需要返回看业务
            //throw new ServerRuntimeException(ErrorStatus.IMAGE_ERROR);
        }

        BASE64Encoder encoder = new BASE64Encoder();
        String imageBase64= encoder.encode(outputStream.toByteArray());
        //去除转换过程中产生的换行
        imageBase64= imageBase64.replaceAll("\r|\n", "");
        Long endImage = System.currentTimeMillis();
        logger.info("image time check={}",endImage-startImage);
        return imageBase64;
    }

base64转换file文件

 /**
     * base64转换file 七牛入参-我自己本身是为了继续调用七牛方便,本功能用于OCR识别中的图片转换给七牛存储起来
     * @param base64
     * @return
     */
    public static File base64ToFile(String base64) {
        if(base64==null||"".equals(base64)) {
            return null;
        }
        Long fileStart = System.currentTimeMillis();

        File file=null;
        FileOutputStream out = null;
        try {
            byte[] buff=new BASE64Decoder().decodeBuffer(base64);
            file = File.createTempFile("tmp", null);
            out=new FileOutputStream(file);
            out.write(buff);
        } catch (IOException e) {
            throw new ServerRuntimeException(ErrorStatus.FILE_ERROR);
        }finally {
            if(out!=null) {
                try {
                    out.close();
                } catch (IOException e) {
                    throw new ServerRuntimeException(ErrorStatus.FILE_ERROR);
                }
            }
        }
        Long fileEnd = System.currentTimeMillis();
        logger.info("file time check={}",fileEnd-fileStart);
        return file;
    }

httpClient

比较特殊的一种方式处理-适用于postman的form-data形式
httpclient的post请求
EntityUtils.toString()解析httpClient形式的entity

public static String getHash(File file,String token)throws Exception{
        Long uploadStart = System.currentTimeMillis();

        HttpClient httpclient = new DefaultHttpClient();
        //QINIUURL 是我本地调取七牛云的地址url 配置在了yml里面
        HttpPost httpPost = new HttpPost(QINIUURL);
		
		//入参构建
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        builder.addBinaryBody("file",file);
        builder.addTextBody("token",token);

        HttpEntity entity = builder.build();
        httpPost.setEntity(entity);
        HttpResponse httpResponse = httpclient.execute(httpPost);
        String hash = EntityUtils.toString(httpResponse.getEntity());
        //我自己是解析截取-也可以用json toArray方式
        hash = hash.substring(hash.indexOf("key")+6,hash.indexOf("}")-1);
        Long uploadEnd = System.currentTimeMillis();
        logger.info("qi niu hash={}",hash);
        logger.info("upload time check={}",uploadEnd-uploadStart);
        return hash;
    

后续持续更新–

你可能感兴趣的:(新手,java)