2016년 12월 29일 목요일

스프링 MVC STATIC 폴더 설정

보통 images ,js, css 파일의 경우 static으로 폴더를 따로 빼서 구분하는데
ex)webapp/static/js

Spring mvc의 경우 처음 세팅에 이걸 허용해 놓지 않아서 따로 허용해줘야한다 

하는 방법은 servlet-context.xml 파일 내에 기존의 resources 설정 되있는곳에 추가로 작성하면 된다

<mvc:resources mapping="/resources/**" location="/resources/" />
<mvc:resources mapping="/static/**" location="/static/" />
<mvc:resources mapping="/robots.txt" location="/robots.txt" />

2016년 12월 19일 월요일

오버로딩 오버라이딩

http://hyeonstorage.tistory.com/185


2016년 12월 14일 수요일

JSON 간단 예제

--JAVA 부분
@RequestMapping(value="/financeList", method=RequestMethod.GET)
public String financeList(ModelMap modelMap){

        JSONObject obj = new JSONObject();
        obj.put("Test", "New");
        obj.put("Test1", "New1");
       
        JSONArray arr = new JSONArray();
        arr.put(12);
        arr.put(122);
        arr.put(453);
        arr.put(123);
       
        obj.put("NumberList", arr);
       
        System.out.println(obj.toString());
       
        modelMap.put("json", obj.toString());
       
        return "jsonTest";
}

--JSP 부분

<jsp:directive.page contentType="text/html;charset=UTF-8" />${json}

2016년 12월 12일 월요일

logback 설정 및 로컬 폴더 설정

--로컬파일쓸때 폴더 설정시 중요사항
d:/  or d:\\

/ 최상위경로
./ 현재 폴더
../ 상위폴더

pom.xml 추가
<dependency>
<groupId>org.lazyluke</groupId>
<artifactId>log4jdbc-remix</artifactId>
<version>0.2.7</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.2</version>
</dependency>
<!-- Updated at 03-Apr-2014 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.2</version>
</dependency>
<!-- Updated at 03-Apr-2014 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
<version>1.1.2</version>
</dependency>
  <dependency>
       <groupId>org.logback-extensions</groupId>
       <artifactId>logback-ext-spring</artifactId>
       <version>0.1.2</version>
   </dependency>
web.xml 설정
<!-- logback 외부 클래스 -->
 <!-- logback --> <listener> <listener-class>ch.qos.logback.ext.spring.web.LogbackConfigListener</listener-class> </listener> <context-param> <param-name>logbackConfigLocation</param-name> <param-value>classpath:/log/logback-${spring.profiles.active}.xml</param-value> </context-param>

로그파일쓰기
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true">

<property name="PROJECT_NAME" value="localApi" />
<property name="LOG_FILE_PATH" value="D:\\log\\local" />

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned by default the type ch.qos.logback.classic.encoder.PatternLayoutEncoder -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%-5level] %-50class{50} : %-5line - %msg%n
</pattern>
</encoder>
</appender>

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_FILE_PATH}/${PROJECT_NAME}.log</file>

<encoder>
<pattern>%d{HH:mm:ss.SSS} [%-5level] %-50class{50} : %-5line - %msg%n</pattern>
</encoder>

        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 파일이 하루에 한개씩 생성된다 -->
            <fileNamePattern>D:/log/sujemall-webapp.%d{yyyy-MM-dd}.log</fileNamePattern>

            <!-- maxHIstory 설정은 위 부분에 롤링 정책에 따라 적용되 된다고 보면된다.
             위 설정데로 라면 30일이 지난 파일은 삭제가 된다.-->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
</appender>

<root level="DEBUG">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
</configuration>

2016년 11월 27일 일요일

form submit form 임시생성해서 전송하는 방법

$('body').append('<form id="tmpForm" method="post"/>');
$('#tmpForm').attr('action', '${popupUrl}');
$('#tmpForm').attr('target', '_new');
$('#tmpForm').append('<input type="hidden" name="originErpCustCd" value="1233"/>');
$('#tmpForm').submit();

2016년 11월 13일 일요일

2016년 11월 9일 수요일

jstl c:forEach list 관련 정리

http://marobiana.tistory.com/9

추가 설명
아래와 같이 객체 안에 객체를 . 으로 참조하여 화면에 보여줄 수 있다

<td colspan="3">
  <c:forEach var="account" items="${partner.erp.accounts }">
  <p>${account.bank.name}
  , ${account.bankCodeEnum.name}
  , ${account.number}</p>
  </c:forEach>
</td>

2016년 11월 8일 화요일

java fileupload 관련

로컬 파일 경로 잡는게 두가지가 있는데
1. d:/image/55.jpg
2. d:\\image\\55.jpg

이와 같이 \일 경우2개를 넣어야함

2016년 10월 28일 금요일

이클립스 기본설정(validation, font etc)

http://start.goodtime.co.kr/2013/06/%EC%83%88-%EC%9D%B4%ED%81%B4%EB%A6%BD%EC%8A%A4%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%A0-%EB%95%8C-%EB%82%98%EC%9D%98-5%EB%B6%84-%EC%84%A4%EC%A0%95/

이클립스 처음설치했을때 5분안에 기본설정하기

2016년 10월 26일 수요일

component-scan / annotation-config / annotation-driven 차이점 + @Component

http://hamait.tistory.com/322

스프링컨테이너와 IOC, 스프링빈과 자바빈 차이

http://limmmee.tistory.com/13 퍼옴
스프링 프레임워크 2 - 컨테이너와 빈의 생명주기
 자 그럼 이제 본격적으로 스프링 프레임워크에 대해서 얘기를 해 볼까? 
어마어마한 두께를 자랑하며 한 장만 봐도 눈물을 흘린다는 스프링 입문서. 토비의 스프링에서는 이렇게 말한다. 
스프링은 거대한 컨테이너임과 동시에 IoC/DI를 기반으로 하고 있는 거룩한 존재이며 서비스 추상화를 통해 삼위일체로 분리되는 3단 변신로봇이다. (응? 한글인데 무슨말인지 1도 모르겠다.)
음. 대충 보니, 컨테이너, IoC/DI 가 키워드인것 같군. 
컨테이너란?
Spring은 하나의 프레임워크이다. 그런데 왜 Spring 컨테이너, IoC 컨테이너라는 말을 사용할까? 그렇다면 컨테이너의 정의는 무엇인가?

Servlet 컨테이너, EJB 컨테이너라고 말하는 것을 종종 들어봤을 것이다. 컨테이너는 보통 인스턴스의 생명주기를 관리하며, 생성된 인스턴스들에게 추가적인 기능을 제공하도록하는 것이라 할 수 있다.
 다시말해, 컨테이너란 당신이 작성한 코드의 처리과정을 위임받은 독립적인 존재라고 생각하면 된다. 컨테이너는 적절한 설정만 되어있다면 누구의 도움없이도 프로그래머가 작성한 코드를 스스로 참조한 뒤 알아서 객체의 생성과 소멸을 컨트롤해준다.

Servlet 컨테이너는 Servlet의 생성, 생성 후 초기화, 서비스 실행, 소멸에 관한 모든 권한을 가지고 있다. 개발자들이 직접 Servlet을 생성하고 서비스하지는 않는다. 이처럼 Servlet 인스턴스에 대한 생명주기를 관리하는 기능을 가진다. 또한, Servlet 컨테이너의 web.xml을 보면 JSP/Servlet 접근 권한에 대한 추가적인 서비스도 지원하고 있다. 이는 Servlet의 구현과는 별도로 각 JSP/Servlet에 대한 Security를 관리해주는 기능을 한다.

 스프링 컨테이너는 스프링 프레임워크의 핵심부에 위치하며, 종속객체 주입을 이용하여 애플리케이션을 구성하는 컴포넌트들을 관리한다.
다시 말하면, 프로그래머가 작성한 코드는 컨테이너를 사용하게 됨으로서 프로그래머의 손을 떠나 컨테이너의 영역으로 떠나버리게 된다. (정확히 말하자면 컨테이너가 맘대로 객체를 생성하는 게 아니라 프로그램을 이용하는 이용자의 호출에 의해 컨테이너가 동작하게 되는 구조이다.)




스프링 컨테이너의 두 종류

1. 빈팩토리 BeanFactory (org.springframework.beans.factory.BeanFactory) 

DI의 기본사항을 제공하는 가장 단순한 컨테이너
팩토리 디자인 패턴을 구현한 것. Bean(이하 빈) 팩토리는 빈을 생성하고 분배하는 책임을 지는 클래스
빈 팩토리가 빈의 정의는 즉시 로딩하는 반면, 빈 자체가 필요하게 되기 전까지는 인스턴스화를 하지 않는다 (lazy loading, 게으른 호출)


 BeanFactory factory = new XmlBeanFactory(new FileInputStream("bean.xml"));
 MyBean myBean = (Mybean) factory.getBean("myBean");


getBean()이 호출되면, 팩토리는 의존성 주입을 이용해 빈을 인스턴스화하고 빈의 특성을 설정하기 시작. 여기서 빈의 일생이 시작된다.


2. 어플리케이션 컨텍스트 ApplicationContext (org.springframework.context.factory.BeanFactory) 

빈팩토리와 유사한 기능을 제공하지만 좀 더 많은 기능을 제공하는 어플리케이션 컨텍스트

빈팩토리보다 더 추가적으로 제공하는 기능
  • 국제화가 지원되는 텍스트 메시지를 관리해 준다.
  • 이미지같은 파일 자원을 로드 할 수 있는 포괄적인 방법을 제공해준다.
  • 리너스로 등록된 빈에게 이벤트 발생을 알려준다.
따라서 대부분의 애플리케이션에서는 빈팩토리보다는 어플리케이션 컨텍스트를 사용하는 것이 좋다.

가장 많이 사용되는 어플리케이션 컨텍스트 구현체
  • ClassPathXmlApplicationContext : 클래스패스에 위치한 xml 파일에서 컨텐스트 정의 내용을 읽어들인다.
  • FileSystemxmlApplicationContext : 파일 경로로 지정된 xml 파일에서 컨텐스트 정의 내용을 읽어들인다.
  • XmlWebApplicationContext : 웹 어플리케이션에 포함된 xml 파일에서 컨텐스트 정의 내용을 읽어들인다.


 ApplicationContext context = new ClassPathXmlApplicationContext("conf/bean.xml");
 MyBean bean = context.getBean("myBean");



빈 팩토리와 애플리케이션컨텍스트의 기능상의 차이점 말고 또 다른 차이점은 다음과 같다.

빈 팩토리 : 처음으로 getBean()이 호출된 시점에서야 해당 빈을 생성(lazy loading)
애플리케이션 컨텍스트 : 컨텍스트 초기화 시점에 모든 싱글톤 빈을 미리 로드한 후 애플리케이션 기동 후에는 빈을 지연 없이 얻을 수 있음(미리 빈을 생성해 놓아 빈이 필요할 때 즉시 사용할 수 있도록 보장)

IoC  (Inversion of Control, 제어의 역전)

IoC란 Inversion of Control의 약어이다. inversion은 사전적 의미로는 '도치, 역전'이다. 보통 IoC를 제어의 역전, 의존적 주입이라 번역한다. 
역시, 한글인데 무슨말인지 이해가 안간다.

IoC 란 제어의 역전 즉 외부에서 제어를 한다는 것이다. 음 감이 딱 온다면, 당신은 천재!
맞다. IoC는 바로 컨테이너이다. 

위에서 컨테이너를 설명하면서 말했던 것 처럼 기존에 자바 기반으로 어플리케이션을 개발할 때 자바 객체를 생성하고 서로간의 의존관계를 연결시키는 작업에 대한 제어권은 보통 개발되는 어플리케이션에 있었다. 그러나 Servlet, EJB등을 사용하는 경우 Servlet Container, EJB Container에게 제어권이 넘어가서 객체의 생명주기(라이프사이클)을 Container들이 전담하게 된다. 이처럼 IoC에서 이야기하는 제어권의 역전이란 객체의 생성에서부터 생명주기의 관리까지 모든 객체에 대한 제어권이 바뀌었다는 것(IoC 컨테이너)을 의미 한다.




IoC와 DI의 관계

스프링 프레임워크의 가장 큰 장점으로 IoC 컨테이너 기능이 부각되어 있으나, IoC 기능은 스프링 프레임워크가 탄생하기 훨씬 이전부터 사용되던 개념이었다. 그러므로 "IoC 기능을 스프링 프레임워크의 장점이라고 이야기하는 것은 적합하지 않다"고 반론을 제기하면서 "새로운 개념을 사용하는 것이 적합하다"고 주장한 사람이 마틴 파울러이다. 경량 컨테이너들이 이야기하는 IoC를 DI라는 용어로 사용하는 것이 더 적합하다고 이야기하고 있다. 마틴 파울러의 이 같은 구분 이후 IoC 개념을 개발자들마다 다양한 방식으로 분류하고 있으나 다음 그림과 같이 IoC와 DI 간의 관계를 분류하는 것이 일반적이다.


+) 자바빈 VS 스프링 빈

자바 빈 : 데이터를 표현하는 것을 목적으로 하는 자바클래스이다. 컴포넌트와 비슷한 의미로 사용되기도 한다.
클래스에는 값을 저장하는 속성필드, get,set 메소드, 기본 생성자등을 포함하고 있다.

+) java.io.Serializable 인터페이스는 생략 가능하나 빈즈 규약에 명시된 내용으로 자바 빈즈에 저장된 프로퍼티를 포함한 채로 파일 시스템에 저장되거나 네트워크로 전송될 수 있도록 객체 직렬화를 제공해야 하므로 implements 한다.

스프링 빈 : 스프링이 제어권을 가지고 직접 만들고 관계를 부여하는 오브젝트

http://limmmee.tistory.com/13

2016년 10월 20일 목요일

static 와 singleton 관련 자료

https://wikidocs.net/228
참조

스프링 .properties 참조 방법

간단히 설명을 하면
1. web.xml 서버띄울때 필요한 정보 입력
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/applicationContext*.xml</param-value>
</context-param>

2. applicationContext*.xml 파일 내부 설정
<import resource="database.xml"/>  <!--DB설정파일-->

<context:property-placeholder location="classpath*:properties/local.properties" />

추가)database.xml 예시파일
${db.mail.driverClassName}이와 같은 정보가 properties에 기입되어있다
<bean id="dataSource" class="해당 클리스" destroy-method="close">
<property name="driverClassName" value="${db.mail.driverClassName}" />
<property name="url" value="${db.mail.url}" />
<property name="username"        value="${db.mail.username}" />
<property name="password"        value="${db.mail.password}" />
<property name="maxActive"       value="5" />
<property name="maxIdle"         value="1" />
<property name="minIdle"         value="1" />
<property name="maxWait"         value="30000" />
<property name="defaultTransactionIsolation" value="1" />
</bean>

3. 설정후 자바와 jsp에서 properties 파일의 값을 읽는방법
java
@Value("${file_dir.url}")
private String fileUploadLo

jsp
<spring:eval var="httpsPort" expression="@applicationProperties.getProperty('port.https')" />

jsp에서 사용하긴 위해서 아래와 같이 bean id가 잡혀있어야함
<!-- Properties -->
<context:property-placeholder location="classpath*:properties/*-${spring.profiles.active}.properties" />
<bean id="applicationProperties" class="클래스명">
<property name="singleton" value="true" />
<property name="location" value="classpath:properties/local.properties" />
</bean>



상세내용은 아래를 참조
http://jijs.tistory.com/entry/spring-%EC%84%A4%EC%A0%95-xml%EA%B3%BC-%EC%86%8C%EC%8A%A4%EC%BD%94%EB%93%9C%EC%97%90%EC%84%9C-properties-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

스프링 .properties 참조 방법

간단히 설명을 하면
1. web.xml 서버띄울때 필요한 정보 입력
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/applicationContext*.xml</param-value>
</context-param>

2. applicationContext*.xml 파일 내부 설정
<import resource="database.xml"/>  <!--DB설정파일-->

<context:property-placeholder location="classpath*:properties/local.properties" />

추가)database.xml 예시파일
${db.mail.driverClassName}이와 같은 정보가 properties에 기입되어있다
<bean id="dataSource" class="해당 클리스" destroy-method="close">
<property name="driverClassName" value="${db.mail.driverClassName}" />
<property name="url" value="${db.mail.url}" />
<property name="username"        value="${db.mail.username}" />
<property name="password"        value="${db.mail.password}" />
<property name="maxActive"       value="5" />
<property name="maxIdle"         value="1" />
<property name="minIdle"         value="1" />
<property name="maxWait"         value="30000" />
<property name="defaultTransactionIsolation" value="1" />
</bean>

3. 설정후 자바와 jsp에서 properties 파일의 값을 읽는방법
java
@Value("${file_dir.url}")
private String fileUploadLo

jsp
<spring:eval var="httpsPort" expression="@applicationProperties.getProperty('port.https')" />

상세내용은 아래를 참조
http://jijs.tistory.com/entry/spring-%EC%84%A4%EC%A0%95-xml%EA%B3%BC-%EC%86%8C%EC%8A%A4%EC%BD%94%EB%93%9C%EC%97%90%EC%84%9C-properties-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

2016년 10월 18일 화요일

shell script , 리눅스 명령어

참조 SITE
http://blog.daum.net/99445015/171

RSYNC 정리
https://www.joinc.co.kr/w/Site/Tip/Rsync

서버점검명령어
top
vmstat
free -m

http://1828.tistory.com/entry/Linux-%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%9D%98-%EC%A0%84%EC%B2%B4%EC%83%81%ED%83%9C%EB%A5%BC-%EC%8B%A4%EC%8B%9C%EA%B0%84%EC%9C%BC%EB%A1%9C-%ED%8C%8C%EC%95%85

배치목록명렁어
-각 계정별로 설정되어 있음
crontab -l

현재 사용유저 정보 명령어
id

class diagram example 퍼옴

http://www.nextree.co.kr/p6753/

2016년 10월 17일 월요일

MAVEN 돌아가는 원리 퍼옴

http://javacan.tistory.com/entry/MavenBasic

extends 와 implements의 정의 퍼옴

http://oybso.tistory.com/entry/Java%EC%97%90%EC%84%9C-extends%EC%99%80-implements-%EC%9D%98-%EC%A0%95%EC%9D%98

엄청설명 잘 되있음

2016년 10월 11일 화요일

2016년 10월 6일 목요일

2016년 9월 20일 화요일

DispatcherServlet 역할(퍼옴)



                                                                  
글출처: http://ellehu.com/jsp/3793
SpringFrameWork는 웹을 개발하는데 있어 Full Spec을 지원하는 프레임 웍이다.
SpringMVC로 웹개발을 할때 작동 순서는 위의 그림과 같다.

1. 클라이언트로 부터 URL이 요청되어 들어오면 제일먼저 web.xml 파일을 로딩하여 스프링에서 지원하는 DispatcherServlet이 실행된다.
(이름에서 알수 있듯이 SpringFramework는 Servlet 기반임으로 스프링에서 지원해주는 Controller에서는 HttpServletRequest,HttpServletResponse 인터페이스를 이용해서 request, response 인스턴스를 사용 할 수가 있다.)

2. DispatcherServlet은 클라이언트로부터 들어온 URL을 HandlerMapping 이라는 곳으로 전송후에 URL을 분석해서 알맞은 컨트롤러 이름을 DispatcherServlet 으로 보낸다.

3. HandlerMapping이라는 것을 통해서 실행될 Controller의 이름을 입력받은 DispatcherServlet은 전달받은 Controller를 실행 시킨다. 이렇게 실행된 Controller는 스프링에서 제공하는 ModelAndView 객체에 뷰페이지에 전달할 객체와 뷰페이지 이름 정보를 담고 DispatcherServlet으로 보낸다.

4. ViewResolver를 통해 보여질 View페이지를 탐색한후 View페이지를 보여준다.

SpringMVC 의 웹개발은 위와같은 루틴으로 움직이기 때문에 스프링 초기 설정을 할때는 다음과 같이 순서를 생각하면서 셋팅을 하면 잊어 버리지 않는다.

<스프링 설정>
1. web.xml 세팅
① DispatcherServlet을 세팅해 준다.
<servlet>
   <servlet-name>dispatcher</servlet-name>
   <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
   <!-- 기본 위치는 [servlet name]-servlet.xml 은 WEB-INF에서 불러 오지만 기타 다른위치에 있을때는 위치를 지정한다 -->
   <init-param>
    <param-name>contextConfigLocation</param-name>
     <!-- 클래스 패스에 위치한 파일로부터 설정정보를 읽으려면 "classpath:" 를 붙이고 경로를 써준다 -->
     <!-- ex) classpath:kr/co/springboard/config.xml -->

    <param-value>/WEB-INF/config/dispatcher-servlet.xml</param-value>
   </init-param>
  </servlet>


<servlet-mapping>
   <servlet-name>dispatcher</servlet-name>
   <url-pattern>*.do</url-pattern>
</servlet-mapping>

Url pattern이 ~~.do 로 들어오게 되면 위에 설정에 servlet name이 dispatcher인 servlet을 실행해서 Spring의 핵심인 DispatcherServlet을 실행한다.

② DI 를 선언할 applicationContext 파일을 로딩하기 위해서 알맞은 리스너와 Context Param을 설정해 준다.

<listener>
   <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>
   /WEB-INF/config/applicationContext.xml
  </param-value>
 </context-param>

ContextLoaderListner는 기본적으로 /WEB-INF/applicationContext.xml 을 설정 파일로 로딩한다.
다른위치에 있을때 위와같이 context-param설정을 통해 위치를 정해 준다. 그리고 context파일이 많을때는 ,(콤마)를 찍고 다른 경로를 또 입력하면 된다.
context파일 이름이 applicationContext.xml 과 applicationContext-ibatis.xml 이라면 applicationContext*.xml 이라고 설정하면 한번에 두가지 파일을 불러 들인다.

③ encoding 설정을 해준다.
jsp에서 response.setCharactorEncoding() 메소드를 사용해서 페이지에 맞는 케릭터셋을 지정할 수 있으나 스프링에서는 위와 같은 설정 없이 케릭터 셋을 지정해 줄 수 있다.

<filter>
   <filter-name>encodingFilter</filter-name>
   <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
   <init-param>
    <param-name>encoding</param-name>
    <param-value>EUC-KR</param-value>
   </init-param>
  </filter>
  
  <filter-mapping>
   <filter-name>encodingFilter</filter-name>
   <url-pattern>/*</url-pattern>
  </filter-mapping>

2. 위에서 선언한 dispatcher-servlet.xml 파일을 생성한다.
① urlHandlerMapping을 설정한다.
<bean id="springBoardUrlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
     <property name="mappings">  <!-- mappings는 바뀌면 안된다. -->
      <props>
       <prop key="/boardList.do">listAbstractCommandController</prop>
       <prop key="/boardWrite.do">writeSimpleFormController</prop>
       <prop key="/boardReadDelete.do">readDeleteMultiActionController</prop>
      </props>
     </property>
    </bean>

boardList.do 라는 url로 들어오면 listAbstractCommandController 클래스를 실행 시킨다. 물론 이 이름은 나중에 설정할 applicationContext.xml 에 선언되어있는 bean의 id와 같아야 한다.

② ModelAndView객체를 받아 View페이지로 이동시켜줄 View Resolver를 구현한다.

<bean id="viewResolver"
       class="org.springframework.web.servlet.view.InternalResourceViewResolver">
       <property name="prefix" value="/WEB-INF/view/"/>
       <property name="suffix" value=".jsp"/>
</bean> 

위와 같은 설정으로 만약에 ModelAndView 에 ViewName 이 boardList 라는 String 값이 들어 있으면 /WEB-INF/view/boardList.jsp 라는 파일을 부르게 된다. prefix는 경로의 앞에 붙는 것, 즉 viewName의 앞쪽에 붙는 것, subffix는 viewName뒤에 붙는것, 즉 확장자라고 생각하면 되겠다.


3.스프링에서 사용할 DI를 applicationContext.xml에 설정한다.

4. 기능에 맞게 각종 Controller를 사용해서 구현한다

web.xml url-pattern / 와 /* 의 차이점

출처 :  http://lng1982.tistory.com/97

[*.do에서 /* 로 바꾸게 된 이유]
스프링 3.1 샘플 프로젝트의 web.xml(DD) 구성 시 url-pattern을 *.do와 같이 설정하였다.
이유는 단순하다.
프로젝트를 진행할 때 항상 *.do를 사용했기 때문이다.

하지만 REST 방식의 웹 어플리케이션을 구성하기 위해서는 다음과 같은 URL 형식을 제공해야 하는데 현재는 *.do와 같이 되어 있기 때문에 pattern을 /* 와 같이 변경해야만 했다.
http://localhost:8080/user/list


[현상]
이제 내가 만들어 놓은 프로젝트는 REST 방식을 지원하는 spring web application이 되었다.
허나 controller mapping url을 호출하면 404 에러가 발생하면서 아래와 같은 로그가 찍힌다.
No mapping found for HTTP request with URI [/WEB-INF/view/common/layout/default/layout.jsp] in 
DispatcherServlet with name 'dispatcher'


[원인]
controller mapping url을 못 찾아서 발생하는 404가 아닌 /WEB-INF/view/common/layout/default/layout.jsp 의 매핑 URL을 찾을 수 없어서 발생하는 오류였다.

이 오류가 발생하는 원인을 알기 위해서는 서블릿 컨테이너와 웹 어플리케이션간의 연동 방법을 알아야 한다.
일단 url-pattern에 등록할 수 있는 URL은 다음과 같다.
"/"로 시작하고 "/*"로 끝나는 패턴은 path로 인식
"*."으로 시작하는 경우 확장자 매칭
"/"만 정의한 경우 디폴트 서블릿 의미
그 외의 경우 동치 매칭

위의 패턴 매칭에 존재하지는 않지만 /*는 요청 받는 모든 URL을 처리한다는 의미다. (아래와 같은 유형의 패턴 모두)
/user/list
/user/list.do
/user/userList.jsp
/img/test.png

결국 모든 요청을 DispatcherServlet에서 처리하겠다고 지정했으니 jsp에 대한 호출도 DispatcherServlet이 처리를 하려고 했던 것이다.
이로 인하여 jsp에 해당하는 mapping url을 찾을 수 없어 HTTP 404 오류가 발생하게 된 것이다.


[해결 방안]
그럼 해결 방법은 뭘까?
결론적으로 말하자면 url-pattern을 "/" 로 지정하면 된다.
해결 방법은 간단하지만 왜 이렇게 설정하면 잘 되는지 궁금해 졌다.

위에서 언급했지만 "/"로 정의한 경우 디폴트 서블릿을 의미한다고 하였다.

이게 뭔 말인가?
이 말의 의미를 찾아 보니 디폴트 서블릿은 서블릿 매핑 URL에 걸리지 않는 요청들을 처리한다고 한다.

또 의문이 생긴다.
난 서블릿 매핑을 "/" 와 같이 한 개만 만들었는데...결국 거르는 작업 없이 내가 만들어 놓은 서블릿 매핑에 모두 걸리는 것 아닌가?
그리고 디폴트 서블릿은 뭔가?

위의 의문들을 해결하기 위해서 이제 tomcat 서블릿 컨테이너에 대해서 언급할 때가 왔다.
${TOMCAT_HOME}/conf/web.xml 파일을 열어 보면 다음과 같이 세 개의 서블릿 매핑이 존재한다.
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>


<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>



<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jspx</url-pattern>
</servlet-mapping>

<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>

*.jsp, *.jspx와 같은 url 패턴은 JspServlet이 처리하고, DefaultServlet은 spring Controller mapping과 jsp 패턴에 걸리지 않는 요청 들을 처리한다는 결론이 나온다.
즉, DefaultServlet은 png, jpg, js, html등 정적인 content를 처리한다는 말이다.

정리하면 
http://localhost:8080/user/userList.jsp <- JspServlet 요청 처리
http://localhost:8080/img/button.jpg <- DefaultServlet 요청 처리
http://localhost:8080/user/list <- DispatcherServlet 요청 처리


[스프링에서 정적 content 호출 시 404 에러 발생]
문제가 생겼다.
http://localhost:8080/user/list 는 정상적으로 동작하는데 
http://localhost:8080/img/button.jpg 로 호출 할 때 404 에러가 발생한다.

DispatcherServlet with name 'dispatcher' processing GET request for [/img/button.jpg]

로그를 보면 *.jpg 호출 시 DefaultServlet이 처리하는 것이 아닌 DispatcherServlet이 처리를 하게 되는 것을 볼 수 있다.
당연히 DispatcherServlet이 처리를 하게 되면 controller mapping URL이 존재하지 않으니 404 오류가 발생한다.

DispatcherServlet은 url-pattern을 "/" 와 같이 설정하게 되면서 tomcat의 server.xml에 정의되어 있는 url-pattern "/"을 무시하기 때문이다.
결국 DispatcherServlet url-pattern을 재정의하게 되어서 DefaultServlet은 더이상 동작할 수 없게 된 것이다.

스프링에서는 이를 해결하기 위해서 <mvc:default-servlet-handler /> 설정을 지원한다.

<mvc:default-servlet-handler /> 설정은 내부적으로 DefaultServletHttpRequestHandler가 담당하게 되고, 이 핸들러(컨트롤러)는 /**로 매핑되어 있다고 한다. (아래 토비님 글 참고)

DefaultServletHttpRequestHandler가 하는 역할은 DispatcherServlet이 처리 못하는 매핑 url을 DefaultServlet으로 넘기는 것이다.

드디어 정리 끝...
이라고 생각하면 오산.
<mvc:default-servlet-handler /> 설정을 추가하니 http://localhost:8080/user/list 호출 시 404에러가 발생한다.
로그를 확인해 보니 이상한 부분이 있었다. 
아래와 같이 SimpleUrlHandlerMapping에서 처리를 하고 있는 것이다.
SimpleUrlHandlerMapping - Matching patterns for request [/user/list] are [/**]

디폴트 핸들러 매핑인 DefaultAnnotationHandlerMapping이 처리해야 하는데 왜 SimpleUrlHandlerMapping이 처리를 하게 된 것일까?
이유는 두 개 이상의 핸들러 매핑이 등록되었을 경우에는 디폴트 전략이 무시되기 때문이다.

결국 <mvc:annotation-driven /> 설정을 통해 DefaultAnnotationHandlerMapping이 자동 등록되게 설정하였고, 이로써 모든 요청이 정상적으로 동작하였다.

단지 url-pattern만 정리하려고 했는데 꼬리에 꼬리를 물어서 스프링까지 설정까지 오게 되었다.

지금까지 url-pattern에 대해서 대수롭지 않게 생각했는데 까면 깔수록 공부해야 할 것들이 산더미이다.
그래도 오늘 하루 내가 뭔가를 배울 수 있었다는 것에 보람을 느낀다.

2016년 9월 19일 월요일

eclipse font control java, jsp, Console

All change
Preferences -> Fonts -> basic -> Text Editor

java
Preferences -> Fonts -> java

jsp
Preferences -> Fonts -> Structured Text Editors

Console(log)
Preferences -> Fonts ->Debug

xml
Preferences-> Appearance-> Colors and Fonts->Basic->Text Font

2016년 9월 1일 목요일

confirm IT Technology

1 16.09.01
System.out.println 보다는 Thread.dumpStack()을 활용하라.
최근 오픈 소스는 리플렉션을 적극 활용하거나 DI 등을 이용하여 코드 그 차제만으로는 어떤 클래스가 실행중에 바인딩 되는지 찾기 어려운 경우가 많습니다.  그리고 해당 로직이 어떤 경로를 거쳐 호출되는지 찾기 어려운 경우가 많습니다.이 경우 앞에서 설명한 디버거를 이용할 경우에도 어디에 breakpoint를 걸어야 할 지 애매한 경우가 많은데 이 경우 짐작이 가는 부분에 Thread.dumpStack() 코드를 추가하면 전체 호출 흐름 및 실제 바인딩 되는 클래스를 확인할 수 있습니다. 

2016년 8월 31일 수요일

2016년 8월 1일 월요일

spring 로그 찍을 시 한글 깨지는 문제 해결

web.xml 에 아래와 같은 내용을 추가하면됨(스프링4 버전 기준)

<filter>
<filter-name>encoding</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>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

2016년 7월 25일 월요일

[WAS] Web / JSP : 동작구조

출처 http://installed.tistory.com/entry/1-JSP%EB%8F%99%EC%9E%91%EA%B5%AC%EC%A1%B0
< Web 프로그래밍 >

기본적으로 클라이언트/서버 방식으로 이루어진다.
클라이언트(웹 브라우저)가 특정 페이지를 웹서버에 요청(Request)하게 되면 웹서버가 이를 처리한 후 결과를 클라이언트(웹브라우저)에게 응답(Response)을 하게 되는 구조




① 요청 (Request) : 웹 브라우저가 웹서버에 해당 페이지를 요청
② 해당 웹서버는 요청페이지를 판단
   html 인지 jsp인지 확인하여 html인 경우 html로 응답하고, 아닌경우는 요청된 페이지의 로직 / DB 연동을 위해 WAS에 처리를 요청한다.
③ WAS에서 DB연동이 필요하면 DB 처리를 수행한다.
④ 처리 결과를 웹서버로 응답한다.
⑤ 결과를 웹브라우저에 응답한다.

- 웹 브라이우저 : 사용자 작업창
- 웹 서버 : 웹브라우저의 요청을 받아들이는 곳이며, 기본인식 언어는 HTML 이다. 결과를 브라우저에 응답한다.
               대표적으로 Apache, IIS ( windows 플랫폼에서만 )
- WAS : 요청 페이지의 로직 처리, DB 처리를 수행
            WebLogic, WebSphere, 제우스 등
              

< 웹 어플리케이션 서버 방식 >

- 웹서버가 처리를 하는 것이 아니라 어플리케이션 서버에게 처리를 넘김.
- 여러명의 사용자가 동일한 페이지를 요청하여 같은 어플리케이션 프로그램을 처리할때 한개의 프로세스만 할당하고 사용자요청을 쓰레드 방식으로 처리한다. 




< JSP동작구조 >

1. 사용자의 웹브라우저에서 http://서버주소/xxx.jsp 형태로 해당 페이지 (JSP 페이지)를 웹서버로 요청한다.

2. 웹서버는 JSP에 대한 요청을 JSP컨테이너(웹컨테이너)에 처리를 넘김.

3. JSP 파일이 처음 요청된 것이면 JSP파일을 서블릿(.java파일생성)으로 변화하는 파싱을 거친다.
(이전에 요청했던 페이지면 파싱할 필요 없이 파싱했던 클래스파일을 메모리에 적재한다.)
JSP파일은 실행을 위해 서블릿으로 파싱되고, 클래스파일로 컴파일이 되는데 이런 과정은 JSP파일이 처음으로 호출되었을때만 거친다. 

4. 서블릿 파일은 자바에서 실행가능한 클래스파일로 컴파일 된다.

5. 클래스파일은 메모리에 적재가 되어 실행된다.

6. 실행결과는 다시 웹서버에게 넘겨진다.

7. 웹서버는 웹브라우저가 인식할수 있는 HTML형태로 결과를 응답한다. HTML페이지를 브라우저에서 실행시켜 표시한다.
( 브라우저는 HTML태그로 구성된 페이지를 실행시켜 주는 프로그램으로, 웹서버에서 HTML이 실행되는것이 아니라 브라우저에서 실행되어 보여진다.)

--> 과정은 해당 JSP페이지가 최초로 요청되었을때 한번만 실행된다. 이후 같은 페이지에 대한 요청이 있으면 변환된 서블릿파일로 서비스를 처리한다.


< HTTP 프로토콜 >

- 비 연결 : 클라이언트의 요청에 응답 후 연결을 끊음.
- 비 상태 : 서버 상태와 상관없이 요청함.