레이블이 spring framework인 게시물을 표시합니다. 모든 게시물 표시
레이블이 spring framework인 게시물을 표시합니다. 모든 게시물 표시

2014-03-07

Spring MVC/ Tomcat] SpringFramework MVC 사용시 view -> controller 로 파라미터 전달시 한글이 깨지는 경우에 해결책.

문서작성 참고 : http://springmvc.egloos.com/513986

SpringFramework MVC 사용시 view -> controller 로 파라미터 전달시 한글이 깨지는 경우에 해결책.

1. HTTP - POST
   web.xml 에 CharacterEncodingFilter 를 추가한다.
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

2. HTTP - GET
Eclipse-tomcat 개발환경에서 한글이 깨지는 경우 tomcat의 server.xml 에 아래 항목에  URIEncoding="UTF-8" 를 추가한다.
*** 아래는 Tomcat 7.x 의 server.xml 기준.

<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8"/>


<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/>

2012-12-20

Java] SpringFramework 개발 팁.




출처 : http://www.omnibuscode.com/zeroboard/zboard.php?id=seeyou_programing_spring&page=1&sn1=&divpage=1&sn=off&ss=on&sc=on&select_arrange=reg_date&desc=desc&no=59


SiteLink #1 : http://blog.naver.com/ecogeo?Redirect=Log&logNo=100010951233

스프링 MVC 적용하면서 대강 정리한 "노트"입니다. 팁이라고하기엔 좀 모자란듯...^^
(오류가 있을수도 있으니 너무 맹신하지는 마세요..-.-);

-. 한 웹app에 여러개의 *-servlet.xml 사용하기
- web.xml에서 원하는 만큼 DispatcherServlet을 선언하고 그 서블릿이름에 대응하는 [servlet-name]-servlet.xml을 작성한다.
- 이렇게 하면 한개의 웹APP 내부에서 웹자원을 몇개의 그룹으로 나누어 별도로 설정하는 것이 가능해진다.

-. 웹자원에 AOP 적용하기
- 핸들러 매핑에 인터셉터를 걸면 된다.
  <bean id="signonInterceptor" class="xxx.SignonInterceptor">
    <property name="signonView">
      <value>redirect:/login_form.html</value>
    </property>
  </bean>
  <bean id="handlerMapping"
    class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="interceptors">
      <list>
        <ref bean="signonInterceptor"/>
      </list>
    </property>
    <property name="mappings">
      .... ....
    </property>
  </bean>
- 그럼 Controller를 통하지 않고 호출되는 JSP에 AOP 적용하려면?
=> 우선은 web.xml에서 jsp 자원들이 DispatcherServlet을 타도록 만든다음 UrlFilenameViewController를 이용한다.
- 위의 SimpleUrlHandlerMapping 의 mappings 속성을 아래처럼 설정한다.(패턴은 적절히 수정)
      <property name="mappings">
         <props>
            <prop key="*">jspViewController</prop>
         </props>
      </property>
     .... ....
   <bean id="jspViewController"
      class="org.springframework.web.servlet.mvc.UrlFilenameViewController" />

- 그럼 특정 자원에 대해서만 AOP를 적용하지 않으려면?(ex: 로그인폼과 로그인콘트롤러에는 인증인터셉터를 걸면 안된다...)
=> AOP적용하면 안되는 자원에 대한 핸들러 매핑을 추가로 설정하고 우선 순위를 부여한다.
(아래에서 publicHandlerMapping에는 인증인터셉터가 없다)
  <bean id="publicHandlerMapping"
    class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="order"><value>1</value></property>
    <property name="mappings">
         <props>
            <prop key="/signon/LoginForm.do">jspViewController</prop>
            <prop key="/signon/Login.do">signonController</prop>
         </props>
    </property>
  </bean>
  <bean id="protectedHandlerMapping"
    class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="order"><value>2</value></property>
    <property name="interceptors">
      <list>
        <ref bean="signonInterceptor"/>
      </list>
    </property>
    <property name="mappings">
         <props>
            <prop key="*">jspViewController</prop>
         </props>
    </property>
  </bean>
- 위와 같은 설정에서 /signon/Login.do 요청이 들어오면 url패턴은 publicHandlerMapping과
protectedHandlerMapping에 모두 해당된다 할지라도 order 순위에 의해 publicHandlerMapping이
그 요청을 처리하게 된다.

-. ModelAndView에 여러 개의 객체를 저장하기
- Map을 만들어 거기에 적절한 이름으로 저장하면 된다.
 return new ModelAndView(this.successView, map);
- JSP에서는 Map에 저장된 키로 request 스코프에서 꺼내어 쓰면된다.

-. 콘트롤러 실행후 특정 url로 redirect하는 방법
- ModelAndView에 넘길 url 앞에 redirect: 접두문자열을 붙여주면 된다.
 <bean name="xxxController" class="xxx.XxxController">
    <property name="successView"><value>redirect:/admin/XXXForm.do</value></property>
  </bean>

-. 에러 종류별로 에러페이지 다르게 지정하기- exception resolver 빈을 설정한다. exception resolver는 콘트롤러에서 발생한 에러를 잡아낸다.
 <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
  <property name="exceptionMappings">
   <props>
    <prop key="org.springframework.dao.DataIntegrityViolationException">DupError.jsp</prop>
    <prop key="org.springframework.dao.DataAccessException">DBError.jsp</prop>
    <prop key="java.lang.Exception">Error.jsp</prop>
   </props>
  </property>
 </bean>
- exceptionMappings의 각 키의 속성값은 exception 타입별 jsp 페이지 경로이며 이 또한 view resolver에 의해 해석된다(만약 뷰resolver에 suffix를 .jsp로 주었다면 위의 설정에서 Error.jsp는 그냥 Error로 설정해야할 것이다).
- 의문 : 위 설정이 콘트롤러에서 포워딩되는 JSP에도 적용이 되는가? => 안된다!!!
- jsp에서 발생한 에러는 jsp 페이지에 선언한 error 페이지로 가거나 jsp에서 error 페이지 선언을 안했으면 web.xml에 정의한 error 페이지로 간다.

- SimpleFormController 를 이용할 경우엔 onSubmit 메소드안에서
 try {
     if (siteForm.isNewSite()) {
  this.siteService.insertSite(siteForm.getSite());
     } else {
  this.siteService.updateSite(siteForm.getSite());
     }
 } catch (DataIntegrityViolationException ex) {
     errors.rejectValue(
      "site.siteip",
      "SITE_IP_ALREADY_EXISTS",
      "Site IP already exists: choose a different Site ip.");
     return showForm(request, response, errors);
 }
이런식으로 에러처리가 가능하다.

-. 프로세스 처리 과정
- Handler mappings가 url을 분석하여 Controllers 선택 => Controllers는 로직수행후 지정된 View를 생성 => ViewResolvers는 뷰를 해석 => 해석된 뷰로 포워딩

-. 핸들러 매핑
- 여러개의 핸들러 매핑이 있을 때 순서를 부여할 수 있다.
- 패턴 사용가능하다... 특정 패턴의 url을 하나의 콘트롤러에 매핑할 수 있다.
- url 별로 빈네임을 설정하기 위해서 : SimpleUrlHandlerMapping 이용
- url을 바로 빈네임으로 사용하기 위해서 : BeanNameUrlHandlerMapping 이용(아래 소스)
    <bean id="handlerMapping"
          class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    <bean name="/editaccount.form"
          class="org.springframework.web.servlet.mvc.SimpleFormController">
        <property name="formView"><value>account</value></property>
        <property name="successView"><value>account-created</value></property>
        <property name="commandName"><value>Account</value></property>
        <property name="commandClass"><value>samples.Account</value></property>
    </bean>
- setAlwaysUseFullPath 속성에 대한 API 설명 읽어볼것.
=> setAlwaysUseFullPath 속성이 false(default)일 때 web.xml에서 /abc/* 로 매핑한 상태에서 url요청이 /abc/test.do 로 들어왔다면 빈네임은 /test.do 로 해야한다는 것이다.

-. 무한루핑 피하기
[web.xml]
"test"라는 이름의 Dispatcher 서블릿에 대한 url 패턴매핑 : /test/jsp/*
[test-servlet.xml] : test Dispatcher 서블릿에 대한 컨텍스트 파일
<bean id="viewResolver"
      class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    <property name="prefix"><value>/test/jsp/</value></property>
    <property name="suffix"><value>.jsp</value></property>
</bean>
=> 이 상황에서 viewResolver에 의한 url 조합이 web.xml의 서블릿 매핑 패턴과 일치하면 무한루프에 빠진다. 주의할 것.

-. UrlFilenameViewController
- UrlFilenameViewController은 url에서 파일명 부분만 빼내어 뷰 url을 만든다.
즉 url이 /foo/bar/test.do 로 들어오건 /bar/foo/test.do로 들어오건 상관없이 뷰 url은 test가 된다.
- 따라서 UrlFilenameViewController를 쓸 경우에는 경로는 다르지만 이름은 동일한 매핑은 없는지 주의해야 한다.
-. JSP에서 스프링 빈 참조하기- servlet context로부터 스프링 WebApplicationContext를 얻은 후 거기서 빈을 액세스한다.
  WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
  SomeBean = (SomeBean)wac.getBean("beanName");
- 그러나 이 방법은 너무 힘들어보인다. 그래서 혹시나해서 스프링 태그라이브러리를 찾아보았다.
- 스프링 태그라이브러리에는 빈을 직접 리턴해주는 태그가 안보인다...왜 없을까?
=> 아시는분? JSTL 때문일까? bind 태그를 잠깐 봤는데... 잘이해안됨.
=> 내가 바라는 건 콘트롤러 통하지 않는 JSP에서 특정 빈의 속성값을 쉽게 액세스하고 싶은거다.

-. web.xml에 대한 푸념
- web.xml에서 서블릿 url 패턴매핑에 *.foo 나 /foo/*는 되는데 이 둘의 조합은 왜 안될까?
=> 패턴의 우선 순위 등이 문제일까? 심플하게 갈려고?
- 에러페이지 설정하는데 Exception 클래스 타입별로 다른 에러페이지를 지정했는데, 예외 클래스간의 관계가 부모자식인게 있으면 최상위 부모 클래스에 대한 에러페이지가 보여진다.
=> 왜 상식과 어긋나게 행동하게 했는지...

-. web.xml에서의 url 패턴매핑에 대한 의견
- 개인적으로 /foo/* 식의 패턴매핑은 바람직하지 않다고 생각한다. 왜냐면 static 자원(html,image 등)도 서블릿을 타게 만들기 때문이다. 물론 컨테이너 앞단에 웹서버를 둔다면 어차피 static 자원은
  웹서버가 처리하기 때문에 상관은 없겠지만... 하여간 *.foo 식의 패턴을 사용하는게 좋다고 생각한다.

-. 정적 자원에 대한 의문
- 서블릿/jsp 에서 static 자원으로 포워딩했을 때 컨테이너에서 도대체 무슨일이 벌어지는 걸까?
  쓰레드 제어권이 static 자원으로 넘어갈리는 없을테고... redirect같은 특수한 응답헤더가 존재하는가?

2012-08-22

Java]스프링프레임워크 링크 모음



ibatis 에서 log4j 사용하기 :  http://v.daum.net/link/1728439

스케줄러를 이용한 메일 발송 : http://v.daum.net/link/2980934



SpringFramework + iBatis 연동시 주의점 및 참조 예제 :  http://lvsin.tistory.com/89

iBATIS에 있는 startBatch(), executeBatch() 메소드로 삽질후기 : http://mudchobo.tomeii.com/tt/category/아이바티스(iBATIS)



 
Spring+ibatis 를 이용한 미니 방명록 작성하기 : http://blog.daum.net/oraclejava/15192535

JAVA] 스프링에서 ajax 사용하기




스프링에서 Ajax 사용 하기 (Use JsonLib) by ultteky

출처 : http://beyondj2ee.blogspot.com/2009/08/ajax-use-jsonlib.html

몇년전만 해도 Ajax 사용은 몇몇 프로젝트에서만 사용했지만
최근에는 Ajax가 점점 필수 사항인 듯 합니다.
하지만 스프링에서 Ajax 지원에 대해서는 다소 미미한 편입니다.
제가 SimpleFormController에서 ajax를 적용한적이 있는데
좀 고생을 한기억이 있었습니다.그때 springsource에서
본 내용을 보면 아무리 스프링이 자유롭다지만 어느정도 J2EE에
대한 스펙을 생각하고 있고 그런 의미에서 Ajax는 아직 스펙이라
말하기가 어렵다고 합니다.
물론 그렇다고 스프링에서 Ajax를 전혀 지원하지 않는냐
그렇지는 않습니다. 서브 프로젝트 중애서 Spring WebFlow 2.0에서
"Spring JavaScript"를 번들을 제공 합니다.
개인적으로 스프링을 좋아하는 저로써는 "Spring Javascript"는
권하고 싶지 않습니다.
이유인즉 첫째 내부적으로 특정 라이브러리 (Dojo)를 사용합니다.
Dojo의 무거움은 경험하신분들은 아실겁니다.
(차라리 jQuery로 했으면..)
둘째로 DWR처럼 강한 결한 형태는 유지보수와 UI 변경을
복잡하게 합니다.
여러 이유가 있겠지만 크게 두가지네요
제 개인적인 Ajax 모델은 일단 클라이언트(Html)와
서버(Spring)가 느슨 결합이 되어야 하고 UI변경시
수정이 최소화 해야 한다고 생각합니다.
UI라이브러리는 기존에 훌륭한 (Extjs,jQuery,YahooUI..)중
플젝에 적합한 라이브러리를 사용하고 서버단은
AbstractView를 상속 받아서 Ajax 전용 뷰를 만들어서
서로간의 간섭이 없도록 구성해야 한다고
생각합니다.

여기서는 스프링에서 ajax를 처리 하기 위한 서버 설정을
설명 드리며 클라이언트 코드는 Json 패킷으로 대체
하는걸로 하겠습니다.
  • JsonLib 다운 받기
서버에서 클라이언트로 리턴할 오브젝트를 Json형태로 변환 하거나 또는 그반대로
Json 데이터를 해당 오브젝트로 변환하는 라이브러리가 필요 합니다. 그중에서
Json-lib를 사용 합니다 .
(해당 사이트에 접속하면 다양한 json 라이브러리를 다운 받을 수 있습니다. ).
여기서 최신 버전으로 다운로드를 받습니다.
다운로드 후 이클립스 프로젝트에
라이브러리를 추가 합니다.
웹 사이트 : http://json-lib.sourceforge.net/
다운로드 : http://sourceforge.net/projects/json-lib/files/
사용법은 해당 사이트를 참고 하시면 됩니다.
  • 스프링 전용 JsonView 다운 받기
아래의 사이트로 접속 후 화면 맨 하단을 보면 "json-lib-ext-spring" 가 있습니다.
거기서 최신 버전의 라이브러리를 다운로드 후 이클립스 프로젝트에
추가 합니다.
다운로드 : http://sourceforge.net/projects/json-lib/files/
  • JsonView 스프링 빈 설정
아래와 같이 JsonView를 빈으로 설정 합니다.
           <bean id="jsonView" class="net.sf.json.spring.web.servlet.view.JsonView"/>
          
ViewResolver 설정

JsonView를 인식 하기 위해서 "BeanNameViewResolver"를 설정 합니다.
WebApplication에서는 여러 Resolver가 존재 할수 있기 때문에
우선 순위를 "0"으로 설정해서 최우선으로 설정 합니다.
            <bean id="beanNameResolver"

           class="org.springframework.web.servlet.view.BeanNameViewResolver"

           p:order="0" />
          

  • Controller Code
아래의 코드를 보면 매우 평범합니다. 어떤한 라이브러리 참조도
없이 평소처럼 코딩 하면 됩니다. 모든 ajax 처리는 JsonView가
처리 함으로써 단지 JsonView가 선언된 스프링 빈 id를
ModelAndView의 "setViewName" 메서드에 선언만
하면 됩니다.
           

           public final ModelAndView handlerRequest(final HttpServletRequest request,

           final HttpServletResponse response) throws Exception {

           ModelAndView modelAndView = new ModelAndView();

           

           DummyMember dummyMember1 = new DummyMember();

           dummyMember1.setId("xxxxxxx");

           

           DummyMember dummyMember2 = new DummyMember();

           dummyMember2.setId("yyyyyy");

           

           List list = new ArrayList();

           list.add(dummyMember1);

           list.add(dummyMember2);

           

           Map resultMap = new HashMap();

           resultMap.put("result1", list);

           resultMap.put("result2", dummyMember1);

           

           modelAndView.addAllObjects(resultMap);

           modelAndView.setViewName("jsonView");

           return modelAndView;

           }
          

※ 샘플 도메인
           public class DummyMember {

           private String id;

           

           public String getId() {

           return id;

           }

           

           public void setId(String id) {

           this.id = id;

           }

           }
          
  • 결과 JSON 패킷
           {"result2":{"id":"xxxxxxx"},"result1":[{"id":"xxxxxxx"},{"id":"yyyyyy"}]}
          

customizing이 필요하면 JsonView 클래스를 상속 받은 후에 "renderMergedOutputModel"
메서드를 override 하시거 아니면 직접 다운로드 사이트에서
소스를 받은 후에 수정 후 적용 하시면 됩니다.