자바·JSP2012. 8. 29. 10:10

System.out.println()는 매우 강력하고 사랑받는 디버깅 도구이다. 문제는, 이 코드를 디버그할 때는 잘 사용하고, 그 후에는 지우지 않는다는 점이다.

이런 일이 몇번 정도 반복되면, 불필요한 메시지가 콘솔에 무더기로 출력되어 꼭 필요한 디버깅 메시징을 보기가 힘들어지는 불상사가 벌어질 수 있다. 그러나 메시지를 어디서 출력하였는지 추적하는 것은 매우 힘들다. 시스템 콘솔 출력은 디버그를 이용하여 추적하는 것도 불가능하다. 방대한 양의 소스코드를 일일히 검색하는 것도 쉬운 일은 아니며, 또 메시지는 동적으로 생성된 것이어서 검색이 불가능 할 수도 있다.

이런 경우, 아래와 같은 간단한 디버깅 툴을 삽입해 이 문제를 해결 할 수 있다:

/**
 * @author Jeeeyul 2011. 11. 1. 오후 4:36:51
 * @since M1.10
 */
public class DebugStream extends PrintStream {
	private static final DebugStream INSTANCE = new DebugStream();
 
	public static void activate() {
		System.setOut(INSTANCE);
	}
 
	private DebugStream() {
		super(System.out);
	}
 
	@Override
	public void println(Object x) {
		showLocation();
		super.println(x);
	}
 
	@Override
	public void println(String x) {
		showLocation();
		super.println(x);
	}
 
	private void showLocation() {
		StackTraceElement element = Thread.currentThread().getStackTrace()[3];
		super.print(MessageFormat.format("({0}:{1, number,#}) : ", element.getFileName(), element.getLineNumber()));
	}
}

위와 같은 클래스를 하나 만든 뒤, DebugStream.activate()를 적절한 시점에 호출 해 주면 된다. 이 후로 System.out.println 을 통해 출력되는 메시지는 다음과 같이 보이게 된다:

(SemanticPatchSystem.java:47) : 세만틱 패치 수정 시작
(AbstractDiagramEditor.java:1140) : 메시지

이 형태로 인쇄한 경우, 콘솔에서 곧바로 클릭하여 해당 소스코드를 볼 수 있게 된다.

Posted by 미랭군
데이터베이스2012. 8. 24. 16:19

문자열 대체(String Substitution)

#{} 문법은 MyBatis 로 하여금 PreparedStatement 프로퍼티를 만들어서 PreparedStatement 파라미터(예를 들면, ?)에 값을 셋팅하도록 할 것이다. 이 방법이 안전하기는 하지만, 좀더 빠른 방법이 선호되기도 한다. 가끔은 SQL 구문에 변하지 않는 값으로 삽입하길 원하기도 한다. 예를 들면, ORDER BY 와 같은 구문들이다.

ORDER BY ${columnName}

여기서 MyBatis 는 문자열을 변경하거나 이스케이프 처리하지 않는다.

 중요 : 사용자로부터 받은 값을 이 방법으로 변경하지 않고 구문에 전달하는 건 안전하지 않다. 이건 잠재적으로 SQL 주입 공격에 노출된다. 그러므로 사용자 입력값에 대해서는 이 방법을 사용하면 안된다. 사용자 입력값에 대해서는 언제나 자체적으로 이스케이프 처리하고 체크해야 한다.

'데이터베이스' 카테고리의 다른 글

Tomcat DBCP를 사용해야 하는 이유  (0) 2012.09.03
Tomcat DBCP 설정법  (0) 2012.09.03
Oracle UTF-8로 설정하기  (0) 2012.08.02
SQL Developer 실행시 오류  (0) 2012.08.01
두 날짜 사이 날짜 구하기  (0) 2012.05.24
Posted by 미랭군
스프링2012. 8. 10. 11:45

<서론>

스프링 @MVC에서 ContentsNagotiator에서 JacksonJsonView로 자동으로 JSON으로 결과물을 생성되게 만들었습니다.
그과정에서 한가지 이슈가 있었습니다.
무엇이냐면 JSON을 리턴할때 무조건 객체가 2depth 이상으로 생성이 된다는 것입니다.

만약 컨트롤러에 아래와 같은 코드가 있다면,

   1: ModelAndView mav = new ModelAndView();
   2: mav.addObject(listOfObjects);
   3: return mav;

아래와 같은 JSON이 생성이 됩니다.


   1: {"objectList" : [{"name":"object1"}, {"name":"object2"}]}

그러나 제가 원하는 JSON은 아래와 같습니다.


   1: [{"name":"object1"}, {"name":"object2"}]


 

<본론>
해결 방안은 기본 JacksonJsonView를 상속하여 filterModel함수를 오버라이딩 하는 것입니다.


   1: import java.util.Map;
   2: import org.springframework.web.servlet.view.json.MappingJacksonJsonView;
   3:  
   4: public class MappingJacksonJsonViewEx extends MappingJacksonJsonView
   5: {
   6:     @SuppressWarnings("unchecked")
   7:     @Override
   8:     protected Object filterModel(Map<String, Object> model) {
   9:  
  10:         Object result = super.filterModel(model);
  11:         if (!(result instanceof Map)) {
  12:             return result;
  13:         }
  14:         Map map = (Map) result;
  15:         if (map.size() == 1) {
  16:             return map.values().toArray()[0];
  17:         }
  18:         return map;
  19:     }
  20: }

ApplicationContext에 설정하는 내용은 (완전한 내용을 포함하진 않았지만) 아래와 같이 됩니다.


   1: <-- default view-->
   2: <property name="defaultViews">
   3:     <list>
   4:         <ref bean="xmlView" />
   5:         <ref bean="jsonView" />
   6:     </list>
   7: </property>
   8:  
   9: <!-- JSON marshalling view -->
  10: <bean id="jsonView" class="ks.spring.sample.MappingJacksonJsonViewExtension" >
  11:     <property name="renderedAttributes" value="restRoot" />
  12: </bean>


 

<결론>

JSON을 한 depth 밖으로 빼내기 위해서, JacksonJSON Viewer의 기본 Filter를 변경시키는 것입니다.

'스프링' 카테고리의 다른 글

SecurityConfig  (0) 2022.05.25
Spring Boot Sample  (0) 2021.03.07
Singleton Registry = ApplicationContext의 또 다른 이름  (0) 2012.08.31
Spring Security - username 정보 가져오기  (0) 2012.01.09
Role in Spring security  (0) 2011.05.18
Posted by 미랭군