最近使用到的技术与坑20190630-1

1.java反射   bean2Map

本开打算使用jedis hset(final String key, final Map<String, String> hash)把对象缓存到redis,结果遇到了下面 ERR wrong number of arguments for 'hset' command的错误,导致有点无奈,既然写了,纪念一下

package util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import exception.CustomException;
import lombok.extern.slf4j.Slf4j;
import model.RunTimeStatus;
import org.springframework.beans.BeanUtils;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @program: netty_study
 * @description:
 * @author: dyingstraw
 * @create: 2019-06-29 15:57
 **/
@Slf4j
public class CommonUtil {

    /**
     * bean2map
     * @param o
     * @return
     */
    public static Map<String, String> beanToMap(Object o) {
        Field[] fields = o.getClass().getDeclaredFields();
        Map<String, String> map = new HashMap<>();
        Arrays.asList(fields).stream().forEach(e -> {
            try {
                e.setAccessible(true);
                map.put(e.getName(), (e.get(o)).toString());
            } catch (IllegalAccessException ex) {
                ex.printStackTrace();
            }
        });
        return map;
    }

    /**
     * mapTobean 仅支持基础类型转换
     * @param map
     * @param clazz
     * @return
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     * @throws CustomException
     */
    public static RunTimeStatus mapToBean(Map<String,String> map,Class<?extends RunTimeStatus> clazz) throws NoSuchFieldException, IllegalAccessException, CustomException {
        RunTimeStatus status = new RunTimeStatus();
        Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
        while (it.hasNext()){
            Map.Entry<String, String> temp = it.next();
            String k = temp.getKey();
            String v = temp.getValue();

            Field field = clazz.getDeclaredField(k);
            field.setAccessible(true);
            if (Long.class.equals(field.getType())|| long.class.equals(field.getType())){
                field.set(status,Long.valueOf(v));
            }else if (String.class.equals(field.getType())) {
                field.set(status,v);
            }else if (Double.class.equals(field.getType())||double.class.equals(field.getType())){
                field.set(status,Double.valueOf(v));
            }else if (Integer.class.equals(field.getType())||int.class.equals(field.getType())){
                field.set(status,Integer.valueOf(v));
            }else {
                throw new CustomException("不支持的数据类型:"+ field.getType());
            }
        }
        return status;
    }

    public static void main(String[] args) throws IllegalAccessException, CustomException, NoSuchFieldException {
        RunTimeStatus status = RuntimeUtil.getRunTimeStatus();
        Map<String, String> map = beanToMap(status);
        log.info(map.toString());


        RunTimeStatus s = mapToBean(map, RunTimeStatus.class);
        log.info(s.toString());

    }
}

2.cglib动态代理,jdk动态代理

例子:每次使用完成jedis关闭释放资源(线程池方式)

 public static Jedis getJedis(){
        final Jedis jedis = getResource();
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(jedis.getClass());
        enhancer.setCallback(new InvocationHandler() {
            @Override
            public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                Object result = method.invoke(jedis, objects);
                log.info("active:{}",jedisPool.getNumActive());
                jedis.close();
                return result;
            }
        });
        return (Jedis) enhancer.create();
    }

3.jedis报错

Map<String,String>map = new HashMap<>();
map.put("name","map");
map.put("count","sss");
r.hset("test",map);
Caused by: redis.clients.jedis.exceptions.JedisDataException: ERR wrong number of arguments for 'hset' command
	at redis.clients.jedis.Protocol.processError(Protocol.java:131)
	at redis.clients.jedis.Protocol.process(Protocol.java:165)
	at redis.clients.jedis.Protocol.read(Protocol.java:219)
	at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:309)
	at redis.clients.jedis.Connection.getIntegerReply(Connection.java:260)
	at redis.clients.jedis.Jedis.hset(Jedis.java:738)
	... 7 more

分析:看了一下hset的源码public void hset(final String key, final Map<String, String> hash)通过把命令组装成hset key field1 value1 fileld2 value2的格式向redis服务器发送命令。而不凑巧的是,服务器上的redis版本是3.0.6的不支持这样做,更新版本应该就可以了。

 public void hset(final byte[] key, final Map<byte[], byte[]> hash) {
    final byte[][] params = new byte[1 + hash.size() * 2][];

    int index = 0;
    params[index++] = key;
    for (final Entry<byte[], byte[]> entry : hash.entrySet()) {
      params[index++] = entry.getKey();
      params[index++] = entry.getValue();
    }
// 通过把命令组装成hset key field1 value1 fileld2 value2的格式向redis服务器发送命令
    sendCommand(HSET, params);
  }

服务器redis命令行错误重现:

在redis的网站上测试成功,注意这个version不准确,应该是5.0.0:

 最后重新写一个工具,专门处理map:

public static long writeMap2Redis(String key,Map<String,String> map){
        Long count=0L;
        Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
        while (it.hasNext()){
            Map.Entry<String, String> temp = it.next();
            count +=getJedis().hset(key,temp.getKey(),temp.getValue());
        }
        return count;
    }

测试:

public static void main(String[] args) {

        RunTimeStatus status = RuntimeUtil.getRunTimeStatus();

        Map<String,String>map = new HashMap<>();
        long r =RedisUtil.writeMap2Redis("test",CommonUtil.beanToMap(status));
        System.out.println(r);
    }

posted @ 2019-06-30 17:11  dyigstraw  阅读(93)  评论(0编辑  收藏  举报
foot