Language/JAVA

[JAVA] HttpUtil

yjkim_97 2021. 12. 19. 19:22

[2021.12.15]

이 포스트는 아래 게시글에서 파생된다. Spring RestTemplate 통신할때 사용되는 유틸리티이다.

2021.12.19 - [IT story/Spring] - [Spring] RestTemplate - Java에서 HTTP 통신

 

[Spring] RestTemplate - Java에서 HTTP 통신

[2021.12.15] 데이터베이스에 저장된 데이터를 기반으로 자동으로 http 통신을하는 기능을 구현하였다. 아직 프로젝트 기획 전이라서 해당 기능에 대항 정확한 서비스가 명시되지 않았지만 기본 플

yjkim97.tistory.com


특수한 도메인에서 path param, query param, request body 파라미터를 생성하는 유틸리티이다.

구현 로직중에서 Exception은 소스를 올리기 위해 수정한 것이다. 실제로는 커스텀한 exception을 내렸다.

 

HttpUtil.java

@Slf4j
public class HttpUtil 
{
	public static final Pattern PATH_PARAM_PATTERN = Pattern.compile("\\{[a-zA-Z0-9_:.-]+\\}");
	
	public static Map<String, String> listHttpParamToMap(List<TbHttpParam> params)
	{
		if(ObjectUtils.isEmpty(params))
		{
			return null;
		}
		
		Map<String,String> keyvalueMap = params.stream()
				.collect(Collectors.toMap(TbHttpParam::getKey, TbHttpParam::getVal));
		return keyvalueMap;
	}

	public static Map<String, String> listHttpParamToMap(List<TbHttpParam> params, PARAM_TYPE paramType)
	{
		if(ObjectUtils.isEmpty(params) || paramType == null)
		{
			return null;
		}
		
		Map<String,String> keyvalueMap = params.stream()
				.filter(m -> m.getParamTypeCd() == paramType)
				.collect(Collectors.toMap(TbHttpParam::getKey, TbHttpParam::getVal));
		return keyvalueMap;
	}
	
	/**
	 * convert {@link TbHttpParam} to path param 
	 * 
	 * @param uri
	 * @param params
	 * @return
	 */
	public static String convertPathParams(String uri, List<TbHttpParam> params)
	{
		if(StringUtils.isEmpty(uri))
		{
			return "";
		}
		if(ObjectUtils.isEmpty(params))
		{
			return uri;
		}
		return HttpUtil.convertPathParams(uri, HttpUtil.listHttpParamToMap(params, PARAM_TYPE.PathParam));
	}

	private static String convertPathParams(String uri, Map<String,String> params)
	{
		if(ObjectUtils.isEmpty(params))
		{
			return uri;
		}
		
		Matcher matcher = PATH_PARAM_PATTERN.matcher(uri);
		
		StringBuffer sb = new StringBuffer();
		
		while (matcher.find()) 
		{
			String group = matcher.group();
			int len = group.length();
			
			String key = group.substring(1,len-1);
			if(params.containsKey(key))
			{
				matcher.appendReplacement(sb, params.get(key));
			}
		}
		matcher.appendTail(sb);
		return sb.toString();
	}
	
	
	/**
	 * convert {@link TbHttpParam} to query param
	 * 
	 * @param uri
	 * @param params
	 * @return
	 */
	public static String convertQueryParams(String uri, List<TbHttpParam> params)
	{
		if(StringUtils.isEmpty(uri)) 
		{
			return "";
		}
		if(ObjectUtils.isEmpty(params))
		{
			return uri;
		}
		
		Map<String, String> keyvalueMap = HttpUtil.listHttpParamToMap(params, PARAM_TYPE.QueryParam);
		String queryString = HttpUtil.paramToQueryString(keyvalueMap);
		
		StringBuffer sb = new StringBuffer();
		sb.append(uri.replace("?", ""));
		
		if(StringUtils.isNotBlank(queryString))
		{
			sb.append("?");
			sb.append(queryString);	
		}
		
		return sb.toString();
	}
	
	public static String paramToQueryString(Map<String, String> paramMap){
		if(ObjectUtils.isEmpty(paramMap))
		{
			return null;
		}
		
		List<NameValuePair> params = Lists.newArrayList();
		if(paramMap != null){
			for(Entry<String, String> paramEntry : paramMap.entrySet()){
				String value = paramEntry.getValue();
				if(value != null){
					params.add(new BasicNameValuePair(paramEntry.getKey(), value.toString()));
				}
			}
		}
		return URLEncodedUtils.format(params, "UTF-8");
	}
	
	/**
	 * convert {@link TbHttpParam} to request body
	 * 
	 * @param listParams
	 * @return
	 */
	public static Map<String, Object> convertBodyParams(List<TbHttpParam> listParams)
	{
		if(ObjectUtils.isEmpty(listParams))
		{
			return null;
		}
		
		List<TbHttpParam> listBodyParams = listParams.stream()
				.filter(item -> item.getParamTypeCd() == PARAM_TYPE.ReqBody)
				.collect(Collectors.toList());
		
		if(ObjectUtils.isEmpty(listBodyParams))
		{
			return null;
		}
		
		List<TbHttpParam> listRootParam = listBodyParams.stream()
				.filter(item -> ObjectUtils.isEmpty(item.getParamPsid()))
				.collect(Collectors.toList());
		
		if(ObjectUtils.isEmpty(listRootParam))
		{
			throw new Exception("httpParam에서 루트 파라미터가 존재하지 않습니다.");
		}
		
		
		Map<String, Object> mapRoot = new HashMap<>();
		List<Long> listCompleteSid = new ArrayList<>();
		
		try 
		{
			for(TbHttpParam param : listRootParam)
			{
				listCompleteSid.add(param.getParamSid());
				
				DATA_TYPE myDataType = param.getDataTypeCd();
				Object myValue = param.getVal();
				
				// 내 자식이 존재
				if(myDataType == DATA_TYPE.Json || myDataType == DATA_TYPE.List)
				{
					myValue = (myDataType == DATA_TYPE.Json) ? new HashMap<>() : new ArrayList<>(); 
					HttpUtil.convertBodyChlidParams(myValue, param, listBodyParams, listCompleteSid);
				}
				
				HttpUtil.putValueByDataType(mapRoot, param.getKey(),myValue,param.getDataTypeCd());
			}
		}
		catch (NumberFormatException | ClassCastException ex)
		{
			log.error(ex.getMessage(), ex);
			throw new Exception("데이터 변환 도중 오류가 발생했습니다. " + ex.getMessage());
		}
		catch (Exception ex)
		{
			log.error(ex.getMessage(), ex);
			throw new Exception("작업도중 오류가 발생했습니다. " + ex.getMessage());
		}
		
		return mapRoot;
	}
	
	private static void convertBodyChlidParams(Object objParent, TbHttpParam parentParam, List<TbHttpParam> listBodyParam, List<Long> listCompleteSid)
			throws NumberFormatException, ClassCastException
	{
		List<TbHttpParam> listTargetParam = listBodyParam.stream()
				.filter(item -> item.getParamPsid() != null && item.getParamPsid().equals(parentParam.getParamSid()))
				.collect(Collectors.toList());
		
		if(ObjectUtils.isEmpty(listTargetParam))
		{
			return;
		}
		
		DATA_TYPE parentDataType = parentParam.getDataTypeCd();
		
		for(TbHttpParam param : listTargetParam)
		{
			if(listCompleteSid.contains(param.getParamSid()))
			{
				continue;
			}
			listCompleteSid.add(param.getParamSid());
			
			DATA_TYPE myDataType = param.getDataTypeCd();
			Object myValue = param.getVal();
			
			// 내 자식이 존재
			if(myDataType == DATA_TYPE.Json || myDataType == DATA_TYPE.List)
			{
				myValue = (myDataType == DATA_TYPE.Json) ? new HashMap<>() : new ArrayList<>(); 
				HttpUtil.convertBodyChlidParams(myValue, param, listBodyParam, listCompleteSid);
			}
			
			// 부모에게 내 데이터 세팅
			if(parentDataType == DATA_TYPE.Json)
			{
				HttpUtil.putValueByDataType((Map) objParent, param.getKey(), myValue, myDataType);
			}
			else if(parentDataType == DATA_TYPE.List)
			{
				HttpUtil.addValueByDataType((List) objParent, myValue, myDataType);
			}
		}
	}
	
	private static void putValueByDataType(Map<String, Object> map, String key, Object value, DATA_TYPE dataType)
		throws NumberFormatException
	{
		if(StringUtils.isBlank(key))
		{
			return;
		}
		if(value == null)
		{
			map.put(key, null);
			return;
		}
		
		if(!map.containsKey(key))
		{
			if(dataType == DATA_TYPE.String)
			{
				map.put(key, String.valueOf(value));
			}
			else if(dataType == DATA_TYPE.Integer)
			{
				map.put(key, Integer.parseInt(String.valueOf(value)));
			}
			else if(dataType == DATA_TYPE.Long)
			{
				map.put(key, Long.parseLong(String.valueOf(value)));
			}
			else if(dataType == DATA_TYPE.Float)
			{
				map.put(key, Float.parseFloat(String.valueOf(value)));
			}
			else if(dataType == DATA_TYPE.Decimal)
			{
				map.put(key, BigDecimal.valueOf(Long.parseLong(String.valueOf(value))));
			}
			else if(dataType == DATA_TYPE.Boolean)
			{
				map.put(key, Boolean.parseBoolean(String.valueOf(value)));
			}
			else if(dataType == DATA_TYPE.Json)
			{
				map.put(key, value);
			}
			else if(dataType == DATA_TYPE.List)
			{
				map.put(key, value);
			}
		}
	}
	
	private static void addValueByDataType(List<Object> map, Object value, DATA_TYPE dataType)
	{
		if(value == null)
		{
			map.add(null);
			return;
		}
		
		if(dataType == DATA_TYPE.String)
		{
			map.add(String.valueOf(value));
		}
		else if(dataType == DATA_TYPE.Integer)
		{
			map.add(Integer.parseInt(String.valueOf(value)));
		}
		else if(dataType == DATA_TYPE.Long)
		{
			map.add(Long.parseLong(String.valueOf(value)));
		}
		else if(dataType == DATA_TYPE.Float)
		{
			map.add(Float.parseFloat(String.valueOf(value)));
		}
		else if(dataType == DATA_TYPE.Decimal)
		{
			map.add(BigDecimal.valueOf(Long.parseLong(String.valueOf(value))));
		}
		else if(dataType == DATA_TYPE.Boolean)
		{
			map.add(Boolean.parseBoolean(String.valueOf(value)));
		}
		else if(dataType == DATA_TYPE.Json)
		{
			map.add(value);
		}
		else if(dataType == DATA_TYPE.List)
		{
			map.add(value);
		}
	}
}