아직 Jsp를 쓰는 프로젝트에서 Maven multi module 프로젝트를 셋팅했는데, JSP를 못 찾는 문제가 발생했습니다.

IntelliJ Working directory에 $MODULE_WORKING_DIR$ 를 셋팅해주면 문제가 해결됩니다.
- 참고 링크

샘플

import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.Period;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.util.Locale;

/**
 * 월 달력 생성기
 *
 * @author
 */
public class Test {

	public static void main(String[] args) {

		final int addMonth = 2; //2개월 후 데이터 생성

		DateTimeFormatter fmtMonth = DateTimeFormat.forPattern("yyyyMM");
		DateTimeFormatter fmtDay = DateTimeFormat.forPattern("yyyyMMdd");

		//대상 월
		DateTime now = DateTime.now();
		String strTargetMonth = now.plus(Period.months(addMonth)).toString(fmtMonth);

		DateTime dt = DateTime.parse(strTargetMonth, fmtMonth);

		int startDay = dt.dayOfMonth().getMinimumValue();
		int endDay = dt.dayOfMonth().getMaximumValue();

		String strDay;
		String dayOfWeek;
		//boolean isHoliDay = false;
		for (int i = startDay; i <= endDay; i++) {
			strDay = strTargetMonth + StringUtils.leftPad(Integer.toString(i), 2, "0");
			dayOfWeek = DateTime.parse(strDay, fmtDay).dayOfWeek().getAsShortText(Locale.KOREA);

			System.out.println(String.format("%s | %s", strDay, dayOfWeek));

		}

	}
}

Spring에서 예외 핸들링 중 특정 예외에서 어떤 경우에는 json으로 응답하고 어떤 경우에는 유저에게 에러 페이지를 보여줘야하는 경우가 존재합니다.

이런 경우 간단히 처리하는 예제 소스입니다.(더 좋은 방법이 있을 수 있지만 고민이 필요)

 

 

/**
	 * 최상위 예외(Exception) 처리
	 * - 에러로그를 남겨서 담당자에게 이메일 발송(logback에 설정 됨)하여 알 수 있도록 하기 위함
	 * - 유저에게 에러 페이지를 보여주기 위해서 ModelAndViewDefiningException를 사용(DispatcherServlet에서 view 처리됨)
	 *
	 * @param ex
	 * @return
	 */
	@ExceptionHandler(Exception.class)
	public ResponseEntity<Object> RootException(Exception ex) throws ModelAndViewDefiningException {

		errorLog("RootException", ex);
		log.debug("exception class ===> {}", ex.getClass().getSimpleName());

		if (CommonUtil.isAjaxReq(HttpRequestUtil.getCurrentRequest())) { //ajax라면 json으로 응답
			RtnVO rtnVO = new RtnVO();
			rtnVO.setErrorCd(ErrorCd.SYSTEM_ERROR.name());
			rtnVO.setMsg("서버 에러가 발생했습니다. 담당자에게 문의하세요");
			return new ResponseEntity<>(rtnVO, ErrorCd.SYSTEM_ERROR.getStatus());
		}

		ModelAndView mav = new ModelAndView();
		mav.setViewName("forward:/error/serverError"); //ajax 요청이 아니라면 유저에게 에러메시지 페이지를 보여줌(/error/serverError는 에러 페이지 랜더링용 공용 URL) 
		throw new ModelAndViewDefiningException(mav);
	}

참고로 DispatcherServlet.java에서 ModelAndViewDefiningException 처리가 되어있다.

 

Java의 java.time.LocalDateTime관련 자주 사용하는 몇 가지를 메모 목적으로 정리합니다.

  • 예전 java 1.7까지는 joda를 많이 사용했고, Java기본 패키지에 포함된 이후에도 바쁘면 joda를 사용했습니다.
  • 가능하면 java 기본 패키지를 사용하는게 좋습니다.
  • 계속해서 내용은 추가할 예정입니다.

 

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Date;

/**
 * Java의 java.time.LocalDateTime 관련 몇가지 사용 예 - 작성중
 * - joda를 많이 썻던 개발자들을 위해 샘플 작성
 *
 * @author
 */
public class LocalDateTimeSample {

	public static ZoneId pstZoneId = ZoneId.of("America/Los_Angeles"); //PST는 ZoneId가 'America/Los_Angeles' 임
	public static ZoneId pdtZoneId = ZoneId.of("GMT-07:00"); //PDT는 ZoneId가 'GMT-07:00' 임. 참고: https://savvytime.com/converter/pdt-to-kst-utc/aug-1-2021/3am

	public static DateTimeFormatter FMT_YMDHIS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

	/**
	 * Java의 java.time.LocalDateTime 관련 몇가지 샘플
	 *
	 * @param args
	 */
	public static void main(String[] args) {

		System.out.println("\n");

		final Date now = new Date();

		System.out.println(String.format("java.util.Date 타입의 현재 일시: %s\n\n", now));

		LocalDateTime ldt = LocalDateTime.ofInstant(now.toInstant(), ZoneId.systemDefault());
		System.out.println(String.format("java.util.Date를 java.time.LocalDateTime 로 변환:%s\n", ldt));

		//혹은 아래와 유사하하게 Date객체로 변환 가능
		//Instant instant = utcZonedDateTime.withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime().atZone(ZoneId.of("UTC")).toInstant();
		//java.util.Date.from(instant);

		final String pattern = "yyyy-MM-dd-HH:mm";
		System.out.println(String.format("LocalDateTime을 패턴 '%s'으로 포맷팅: %s\n", pattern, ldt.format(DateTimeFormatter.ofPattern(pattern))));

		System.out.println(String.format("1일 후는: %s", ldt.plusDays(1).format(FMT_YMDHIS)));
		System.out.println(String.format("3일전은: %s", ldt.minusDays(3).format(FMT_YMDHIS)));

		String ymd = "20220501";

		DateTimeFormatter fmtYmd = DateTimeFormatter.ofPattern("yyyyMMdd");
		LocalDate dateYmd = LocalDate.parse(ymd, fmtYmd);
		System.out.println(String.format("%s 문자열을 포맷팅 후 date객체 변환 결과: %s", ymd, dateYmd));

		LocalDate toDay = LocalDate.now();
		System.out.println(String.format("오늘은 '%s' 입니다.", toDay));
		System.out.println(String.format("이번달의 1일은 '%s' 입니다.", toDay.withDayOfMonth(1)));

		System.out.println("\n");
		ZoneId defaultZoneId = ZoneId.systemDefault();
		Date firstMonthDayDT = Date.from(toDay.atStartOfDay(defaultZoneId).toInstant());
		System.out.println(String.format("이번달의 1일의 java date타입은 '%s' 입니다.", firstMonthDayDT));

		System.out.println("\n");
		System.out.println("원본 LocalDateTime: " + ldt);
		System.out.println("\t초 미만 절삭: " + ldt.truncatedTo(ChronoUnit.SECONDS));
		System.out.println("\t분 미만 절삭: " + ldt.truncatedTo(ChronoUnit.MINUTES));
		System.out.println("\t시간 미만 절삭: " + ldt.truncatedTo(ChronoUnit.HOURS));
		System.out.println("\t일 미만 절삭: " + ldt.truncatedTo(ChronoUnit.DAYS));
	}
}

 

결과

코드 실행 결과

 

1. 쿼리 부분 예

<!-- 해당 유저ID가 존재하는지 체크(존재시 1 리턴으로 boolean 체크됨) -->
<select id="isExistUser" parameterType="String" resultType="boolean">
    /* user.isExistUser */
    SELECT
    EXISTS
    (SELECT 1 FROM user WHERE user_id = #{userId} LIMIT 1) #LIMIT 1은 없어도 무방하지만 방어차원에서
</select>



2. java부분 예(DAO영역)

public boolean isExistUser(String userId) {
    return sqlSession.selectOne(NAMESPACE + "isExistUser", userId);
}

Spring valid 자주 사용하는 내용/샘플 정리

 - 필요시 복붙 목적으로 메모해둔 글인점을 감안해주세요

 

//${validatedValue}를 이용하면 검증대상 값을 가져올 수 있음
@NotBlank(message = "'authKey' cannot be null or empty")
@Size(max = 50, message = "The 'authKey' must be a maximum of {max}. But the request is [${validatedValue}].")
private String authKey;
  1. 신규 개발자 입사 또는 성능 문제 발생시 공유하는 java 코딩 방법
  2.  모두 지킬 수는 없지만 알고 있으면 좋은 내용


p.s. 생각날때 개인 의견 추가 및 링크들 추가 예정

git 링크

 - https://github.com/oshnew/study-modern-java/blob/master/src/main/java/stream/StreamSorted.java

 

import lombok.AllArgsConstructor;
import lombok.Data;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 내부 개발자 교육을 위한 간단한 java Stream 샘플 소스
 *  - 정렬
 *
 * @author
 */
public class StreamSorted {

	public static void main(String[] args) {

		//테스트 데이터 셋팅
		List<StatVO> statList = Arrays.asList(new StatVO("a", 3), new StatVO("b_a", 2), new StatVO("b_c", 1), new StatVO("d", 7));

		System.out.println("=== cnt 오름차순 정렬");
		statList.stream().sorted(Comparator.comparing(StatVO::getCnt)).forEach(System.out::println);

		System.out.println("\n\n");
		System.out.println("=== cnt 내림차순 정렬");
		statList.stream().sorted(Comparator.comparing(StatVO::getCnt).reversed()).forEach(System.out::println);

		System.out.println("\n\n");
		System.out.println("=== stat name 오름차순 후에 cnt 내림차순정렬"); //다수 필드 정렬
		statList.stream().sorted(Comparator.comparing(StatVO::getStat).thenComparing(StatVO::getCnt).reversed()).forEach(System.out::println);

		System.out.println("\n\n");
		List<StatVO> descList = statList.stream().sorted(Comparator.comparing(StatVO::getCnt)).collect(Collectors.toList());
		System.out.println("=== 오름차순 정렬하여 collect한 리스트");
		descList.stream().forEach(System.out::println);

	}

	@Data
	@AllArgsConstructor
	public static class StatVO {
		private String stat;
		private int cnt;
	}

}

+ Recent posts