아래 Spring web.xml의 ContextLoaderListener의 환경설정 파일인 applicationContext.xml의 위치를 지정하는 코드에서 classpath:의 위치가 어디인가?
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
만일 위 설정 내용에서 classpath:을 빼버리면 당연히 applicationContext.xml를 찾지 못한다는 에러가 발생한다. 아래와 같이
org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [applicationContext.xml]; nested exception is java.io.FileNotFoundException: class path resource [applicationContext.xml] cannot be opened because it does not exist
그렇다면 저 classpath:의 위치는 어디를 가리킨단 말인가? 만일 프로젝트 이름이 BordWebDay4Class04라고 한다면
이클립스의 프로젝트명에서 마우스 우측 클릭 ⇒ Build Path ⇒ Configure Build Path... ⇒ 상단 4개의 탭 중에서 Source 탭 선택 하면 아래와 같은 내용이 보일 것이다.
여기서 classpath:의 위치가 2곳 나타나 있다.
BordWebDay4Class04/src/main/java/
BordWebDay4Class04/src/main/resources/
따라서 applicationContext.xml를 위 두 경로 중 어느 한곳에 위치시키면 정상적으로 구동이 된다.
그런데 BordWebDay4Class04/src/main/java에는 당연히 java 소스코드를, BordWebDay4Class04/src/main/resources에는 스프링 설정 파일을 위치시킨다.
따라서 applicationContext.xml를 BordWebDay4Class04/src/main/resources/에 위치시키면 된다.
그런데 만일 applicationContext.xml가 BordWebDay4Class04/src/main/resources/joe/ 아래에 설정 파일이 있다면 역시 아래 에러가 발생할 것이다.
java.io.FileNotFoundException: class path resource [applicationContext.xml] cannot be opened because it does not exist
해결책은 몇 가지 방법이 있는데 아래 방법 중 어느 하나를 적용하면 된다.
(1) classpath:에 joe라는 경로를 포함시키는 방법
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/joe/applicationContext.xml</param-value>
</context-param>
(2) applicationContext.xml가 있는 BordWebDay4Class04/src/main/resources/joe/를 classpath에 등록하는 방법
이클립스의 프로젝트명에서 마우스 우측 클릭 ⇒ Build Path ⇒ Configure Build Path... ⇒ 상단 4개의 탭 중에서 Source 탭 선택 ⇒ 우측 "Add folder..." 버튼 클릭하여 BordWebDay4Class04/src/main/resources/joe/ 경로를 추가해 준다.
(3) 와일드 카드(**)를 이용해서 현재 classpath 하위의 모든 디렉토리를 포함하도록 설정
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/**/applicationContext.xml</param-value>
</context-param>
위와 같이 설정하면 아래의 경우들이 모두 정상적으로 동작한다.
BordWebDay4Class04/src/main/resources/joe/applicationContext.xml
BordWebDay4Class04/src/main/resources/joe/myjob/applicationContext.xml
BordWebDay4Class04/src/main/resources/joe/myjob/yourjob/applicationContext.xml
BordWebDay4Class04/src/main/resources/joe/myjob/herjob/applicationContext.xml
BordWebDay4Class04/src/main/resources/hisjob/applicationContext.xml
이 작업 후 Tomcat을 restart 하면 이제 정상적으로 구동이 될 것이다.
여기서 와일드카드가 하나일때인 /*/와 두개 일때인 /**/의 차이는
전자의 경우는(/*/의 경우는) 현재의 classpath: 디렉토리 하위에 있는 디렉토리들 중 첫번째 하위 디렉토리만 해당된다.
즉 applicationContext.xml가 classpath: 디렉토리 하위의 디렉토리들 중 어느 하위에 속해있든지 모두 인식이 된다는 뜻이다.
/joe/applicationContext.xml (정상적으로 인식됨)
/kim/applicationContext.xml (정상적으로 인식됨)
/kim/goo/applicationContext.xml (인식 안됨)
/seo/qqq/applicationContext.xml (인식 안됨)
후자의 경우는(/**/의 경우는) 현재의 classpath: 디렉토리 하위에 몇개의 하위 디렉토리들이 있어도 그 하위 모든 디렉토리들을 다 포함시킬수가 있다.
즉 applicationContext.xml가 classpath: 디렉토리 하위의 디렉토리들 중 어느 하위에 속해있든지 모두 인식이 된다는 뜻이다.
/joe/applicationContext.xml (정상적으로 인식됨)
/kim/applicationContext.xml (정상적으로 인식됨)
/kim/goo/applicationContext.xml (정상적으로 인식됨)
/seo/qqq/applicationContext.xml (정상적으로 인식됨)
아래는 Tomcat을 재구동했을 때 정상적으로 인식되었을 때의 로그이고
정보: Initializing Spring root WebApplicationContext
INFO : org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization started
INFO : org.springframework.web.context.support.XmlWebApplicationContext - Refreshing Root WebApplicationContext: startup date [Wed Jan 08 16:08:18 KST 2020]; root of context hierarchy
INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from file [D:\MyProgramStudy\Spring\.metadata\.plugins\org.eclipse.wst.server.core\tmp2\wtpwebapps\BordWebDay4Class03\WEB-INF\classes\joe\myjob\herjob\applicationContext.xml]
INFO : org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor - JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
INFO : org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization completed in 1593 ms
아래는 Tomcat을 재구동했을 때 인식되지 못했을 때의 로그이다.
정보: Initializing Spring root WebApplicationContext
INFO : org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization started
INFO : org.springframework.web.context.support.XmlWebApplicationContext - Refreshing Root WebApplicationContext: startup date [Wed Jan 08 16:15:38 KST 2020]; root of context hierarchy
INFO : org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization completed in 357 ms
2020년 1월 1일 수요일
2019년 12월 9일 월요일
AOP(Aspect Oriented Programming) 용어 정리
AOP(Aspect Oriented Programming) 용어 정리
S/W에서 클래스간의(객체간의) 결합도가 높을 경우 그들 중 어느 한 클래스(객체)에 수정이 발생하면 해당 클래스(객체)가 사용된 모든 소스 코드를 수정해야 하고 이러한 수정은 S/W 유지 보수의 측면에서 뜻하지 않은 문제를 발생시키거나 유지 보수를 복잡하고 어렵게 만드는 요인이 된다. 따라서 가능한 객체들간의 결합도를 낮추는 방향으로 가야 한다.
Spring에서 결합도를 낮추는 기법이 의존성 주입(IoC)과 AOP가 있는데 AOP의 용어를 명확히 핵심적으로 정리하고자 한다.
IoC와 AOP는 개발자가 소스코드에서 해 주지 않아도 Spring 컨테이너가 알아서 처리해 주므로 인해 소스코드 수정을 하지 않아도 된다는 개념이 핵심이다. 그렇게 하도록 하기 위해 필요한 것이 Spring 설정 파일에서의 설정을 통해서 Spring 컨테이너가 처리하도록 하는 식이다.
▶ 횡단 관심(Crosscutting Concerns)
비지니스 메소드마다 공통으로 등장하는 코드를 의미(예외, 로깅, 트랜잭션같은 코드).
▶ 핵심관심(Core Concerns)
핵심 비지니스 로직을 의미.
▶ Joinpoint
모든 비지니스 메소드들을 의미
▶ Pointcut
모든 비지니스 메소드들 중에서 횡단 관심 코드를 수행하기 원하는 "특정 비지니스 메소드"를 의미
▶ Advice
횡단관심에 해당하는 코드를 담고 있는 메소드를 의미
▶ Aspect
Pointcut과 Advice의 결합(어떤 Pointcut 메소드에 대해 어떤 Advice 메소드를 실행할지를 정의)
▶ Weaving
Advice가 삽입되는 과정
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
비지니스 로직 메소드 횡단관심 메소드
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Joinpoint Advice
Pointcut
Weaving
Aspect
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
S/W에서 클래스간의(객체간의) 결합도가 높을 경우 그들 중 어느 한 클래스(객체)에 수정이 발생하면 해당 클래스(객체)가 사용된 모든 소스 코드를 수정해야 하고 이러한 수정은 S/W 유지 보수의 측면에서 뜻하지 않은 문제를 발생시키거나 유지 보수를 복잡하고 어렵게 만드는 요인이 된다. 따라서 가능한 객체들간의 결합도를 낮추는 방향으로 가야 한다.
Spring에서 결합도를 낮추는 기법이 의존성 주입(IoC)과 AOP가 있는데 AOP의 용어를 명확히 핵심적으로 정리하고자 한다.
IoC와 AOP는 개발자가 소스코드에서 해 주지 않아도 Spring 컨테이너가 알아서 처리해 주므로 인해 소스코드 수정을 하지 않아도 된다는 개념이 핵심이다. 그렇게 하도록 하기 위해 필요한 것이 Spring 설정 파일에서의 설정을 통해서 Spring 컨테이너가 처리하도록 하는 식이다.
▶ 횡단 관심(Crosscutting Concerns)
비지니스 메소드마다 공통으로 등장하는 코드를 의미(예외, 로깅, 트랜잭션같은 코드).
▶ 핵심관심(Core Concerns)
핵심 비지니스 로직을 의미.
▶ Joinpoint
모든 비지니스 메소드들을 의미
▶ Pointcut
모든 비지니스 메소드들 중에서 횡단 관심 코드를 수행하기 원하는 "특정 비지니스 메소드"를 의미
▶ Advice
횡단관심에 해당하는 코드를 담고 있는 메소드를 의미
▶ Aspect
Pointcut과 Advice의 결합(어떤 Pointcut 메소드에 대해 어떤 Advice 메소드를 실행할지를 정의)
▶ Weaving
Advice가 삽입되는 과정
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
비지니스 로직 메소드 횡단관심 메소드
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Joinpoint Advice
Pointcut
Weaving
Aspect
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2019년 5월 7일 화요일
전자정부프레임웤에서 컨트롤러 클래스 인식되게 하기 위한 환경설정법
전자정부프레임워크을 이용해서 웹 애플리케이션을 개발하면 통상적으로 MVC 모델 형태로 개발을 하게 된다.
이때 Controller 클래스(@Controller가 붙여지는 클래스)에 각종 사용자의 request 처리하는 코드가 모이게 된다.
따라서 request 관련을 살펴봐야 한다면 Controller 클래스만 보면 되므로 한 자리에서 파악할수 있는 잇점이 있어 편리하다.
그런데 Spring 프레임웤이 Controller 클래스를 인식하도록 할려면 환경을 어떻게 설정해야 하는가?
물론 전자정부프레임웤에서
eGovFrame - Start - New Web Project - Project name과 Group Id 설정 후 - Next - Generate Example 창에서
"Generate Example"을 체크하게 되면 전자정부프레임웤에서 모든 환경설정을 해주게 되고 Controller 클래스가 정상적으로 인식이 된다.
그러나 만일 전자정부프레임웤의 기본 환경설정과 다르게 설정하기 원한다거나 그렇게 디폴트로 생성된 파일들 등을 사용하기 원치않는다면 이때 어떻게 설정해야
Controller 클래스를 인식하게 할수 있을까?
이에 대한 환경 설정에 대해서 정리해 보고자 한다.
본 포스트는 이해를 수이하기 위해서 DB 설정은 제외하고 순전히 Controller 클래스의 등록에 대한 부분만 다룬다.
eGovFrame - Start - New Web Project - Project name과 Group Id 설정 후 - Next - Generate Example 창에서 - "Generate Example"을 체크해제 - Finish
이렇게 프로젝트를 생성해서 아래와 같이 해당 프로젝트를 실행하면 404 에러를 출력하는 페이지만 보일 것이다(프로젝트명이 TestTest라고 하자).
http://localhost:8081/TestTest/
그렇다고 프로젝트가 잘못 생성된 것은 아니다. 확인하기 위해서 간단하게 index.jsp를 생성해서 실행해 보자.
해당 프로젝트의 src/main/webapp/ 아래에 index.jsp를 생성해야 한다. 중요한것은 webapp 폴더가 Root 폴더로 인식되기 때문이다.
Webapp 폴더에서 마우스 우측 클릭 - New - JSP File - File name을 index.jsp로 지정 후 Finish
<body> 태그 안에
<h2>Hello world. I am index.jsp</h2>
를 추가후 해당 프로젝트 명에서 우측 클릭 후 Run As - Run on Server - Finish
정상적으로 index.jsp의 내용이 보일것이다.
이제부터 Controller 클래스가 인식되도록 환경 설정을 할 것이다. 우선 web.xml 파일을 아래의 내용과 같이 설정 내용을 작성한다.
최초 web.xml에는 아래의 내용만 되어 있을 것이다.
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
아래는 web.xml의 Controller 클래스가 인식되도로 하기 위한 기본 설정 내용이다.
*** web.xml의 기본 설정 내용 ***
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>MyTest</display-name>
<!-- 인코딩 관련 -->
<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>*.do</url-pattern>
</filter-mapping>
<!-- 크로스 스크립팅이라는 해킹 기법을 사전에 막는 기능. -->
<filter>
<filter-name>HTMLTagFilter</filter-name>
<filter-class>egovframework.rte.ptl.mvc.filter.HTMLTagFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HTMLTagFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<!-- 어떤 객체들을 미리 만들어 놓을지가 작성된 설정 파일의 경로를 값으로 할당 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<!-- Spring 환경설정 파일인 context-*.xml을 읽은다.
src/main/resources/egov/spring/context-*.xml을 의미한다. -->
<param-value>classpath*:egov/spring/context-*.xml</param-value>
</context-param>
<!-- -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- MVC에서 Controller 역할을 하게 될 DispatcherServlet 객체 등록.
*.do라는 요청이 들어오면 appServlet이름의 서블릿 클래스인
org.springframework.web.servlet.DispatcherServlet를 실행한다.
DispatcherServlet 클래스에 대한 설정 내용은 /WEB-INF/spring/appServlet/dispatcher-servlet.xml에
설정되어 있다.
-->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
아래는 context-root.xml을 설정내용인데 현재 시점에서는 아래와 같이 파일만 생성해 둔다.
*** context-root.xml 설정 내용 ***
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
</beans>
아래는 DispatcherServlet을 위한 환경 설정이다.
*** dispatcher-servlet.xml 환경 설정 내용 ***
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<!-- xmlns:mvc="http://www.springframework.org/schema/mvc" -->
<!-- annotation을 사용하도록 설정 -->
<mvc:annotation-driven /> <!-- 근데 이것 없이도 정상적으로 동작함 -->
<!--
base-package는 src/main/java/ 하위에 있는 패키지 명 중에서 ""안에 지정한 패키지 이하를 스캔하라는 뜻임.
즉 base-package="egovframework"라고 하면
egovframework.example.cmmn
egovframework.example.cmmn.web
egovframework.example.sample.service
egovframework.example.sample.service.impl
egovframework.example.sample.web
모두가 다 해당된다.
base-package="egovframework.example"과 같이 해도 된다.
다음과 같은 식으로도 가능
<context:component-scan base-package="com.yk.yboard, com.yk.common"/>
아래는 버스앱의 경우에 대한 것이다.
<context:component-scan base-package="com.hubizict.bus" />
<context:include-filter type="" expression=""/>는 자동 스캔 대상에 포함시킬 클래스를 의미
<context:exclude-filter type="" expression=""/>는 자동 스캔 대상에 포함시키지 않을 클래스를 지정하는 의미
-->
<context:component-scan base-package="com.joe">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/>
</context:component-scan>
</beans>
이상의 작업을 통해서 eGov 프레임워크가 Controller 클래스를 인식하도록 설정이 되었다.
이제 Controller 클래스를 간단하게 만들어 보자. 해당 프로젝트의 src/main/java/ 아래에 패키지를 만든다.
src/main/java/ 위에서 마우스 우측 클릭 - New - Package
패키지 이름을 com.joe.egov.test를 만들어 보자.
생성된 패키지명 위에서 마우스 우측 클릭 - New - Class - MyController로 컨트롤러 클래스를 만들자.
이제 MyController 클래스를 다음과 같이 작성해 보자.
package com.joe.egov.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class MyController {
@RequestMapping(value="/mytest.do", method=RequestMethod.GET)
public String test(){
System.out.println("####### Hello this is MyController 클래스 ");
return "test.jsp";
}
}
이제 webapp 폴더 아래에 test.jsp파일을 생성해서 원하는 내용으로 작성해두면 MyController 실행후 test.jsp가 실행되어 확인이 편리할 것이다.
아래와 같이 실행해서 컨트롤러 클래스가 정상적으로 작동하는지 확인해 보자.
http://localhost:8081/TestTest/mytest.do
이때 Controller 클래스(@Controller가 붙여지는 클래스)에 각종 사용자의 request 처리하는 코드가 모이게 된다.
따라서 request 관련을 살펴봐야 한다면 Controller 클래스만 보면 되므로 한 자리에서 파악할수 있는 잇점이 있어 편리하다.
그런데 Spring 프레임웤이 Controller 클래스를 인식하도록 할려면 환경을 어떻게 설정해야 하는가?
물론 전자정부프레임웤에서
eGovFrame - Start - New Web Project - Project name과 Group Id 설정 후 - Next - Generate Example 창에서
"Generate Example"을 체크하게 되면 전자정부프레임웤에서 모든 환경설정을 해주게 되고 Controller 클래스가 정상적으로 인식이 된다.
그러나 만일 전자정부프레임웤의 기본 환경설정과 다르게 설정하기 원한다거나 그렇게 디폴트로 생성된 파일들 등을 사용하기 원치않는다면 이때 어떻게 설정해야
Controller 클래스를 인식하게 할수 있을까?
이에 대한 환경 설정에 대해서 정리해 보고자 한다.
본 포스트는 이해를 수이하기 위해서 DB 설정은 제외하고 순전히 Controller 클래스의 등록에 대한 부분만 다룬다.
eGovFrame - Start - New Web Project - Project name과 Group Id 설정 후 - Next - Generate Example 창에서 - "Generate Example"을 체크해제 - Finish
이렇게 프로젝트를 생성해서 아래와 같이 해당 프로젝트를 실행하면 404 에러를 출력하는 페이지만 보일 것이다(프로젝트명이 TestTest라고 하자).
http://localhost:8081/TestTest/
그렇다고 프로젝트가 잘못 생성된 것은 아니다. 확인하기 위해서 간단하게 index.jsp를 생성해서 실행해 보자.
해당 프로젝트의 src/main/webapp/ 아래에 index.jsp를 생성해야 한다. 중요한것은 webapp 폴더가 Root 폴더로 인식되기 때문이다.
Webapp 폴더에서 마우스 우측 클릭 - New - JSP File - File name을 index.jsp로 지정 후 Finish
<body> 태그 안에
<h2>Hello world. I am index.jsp</h2>
를 추가후 해당 프로젝트 명에서 우측 클릭 후 Run As - Run on Server - Finish
정상적으로 index.jsp의 내용이 보일것이다.
이제부터 Controller 클래스가 인식되도록 환경 설정을 할 것이다. 우선 web.xml 파일을 아래의 내용과 같이 설정 내용을 작성한다.
최초 web.xml에는 아래의 내용만 되어 있을 것이다.
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
아래는 web.xml의 Controller 클래스가 인식되도로 하기 위한 기본 설정 내용이다.
*** web.xml의 기본 설정 내용 ***
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>MyTest</display-name>
<!-- 인코딩 관련 -->
<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>*.do</url-pattern>
</filter-mapping>
<!-- 크로스 스크립팅이라는 해킹 기법을 사전에 막는 기능. -->
<filter>
<filter-name>HTMLTagFilter</filter-name>
<filter-class>egovframework.rte.ptl.mvc.filter.HTMLTagFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HTMLTagFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<!-- 어떤 객체들을 미리 만들어 놓을지가 작성된 설정 파일의 경로를 값으로 할당 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<!-- Spring 환경설정 파일인 context-*.xml을 읽은다.
src/main/resources/egov/spring/context-*.xml을 의미한다. -->
<param-value>classpath*:egov/spring/context-*.xml</param-value>
</context-param>
<!-- -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- MVC에서 Controller 역할을 하게 될 DispatcherServlet 객체 등록.
*.do라는 요청이 들어오면 appServlet이름의 서블릿 클래스인
org.springframework.web.servlet.DispatcherServlet를 실행한다.
DispatcherServlet 클래스에 대한 설정 내용은 /WEB-INF/spring/appServlet/dispatcher-servlet.xml에
설정되어 있다.
-->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
아래는 context-root.xml을 설정내용인데 현재 시점에서는 아래와 같이 파일만 생성해 둔다.
*** context-root.xml 설정 내용 ***
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
</beans>
아래는 DispatcherServlet을 위한 환경 설정이다.
*** dispatcher-servlet.xml 환경 설정 내용 ***
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<!-- xmlns:mvc="http://www.springframework.org/schema/mvc" -->
<!-- annotation을 사용하도록 설정 -->
<mvc:annotation-driven /> <!-- 근데 이것 없이도 정상적으로 동작함 -->
<!--
base-package는 src/main/java/ 하위에 있는 패키지 명 중에서 ""안에 지정한 패키지 이하를 스캔하라는 뜻임.
즉 base-package="egovframework"라고 하면
egovframework.example.cmmn
egovframework.example.cmmn.web
egovframework.example.sample.service
egovframework.example.sample.service.impl
egovframework.example.sample.web
모두가 다 해당된다.
base-package="egovframework.example"과 같이 해도 된다.
다음과 같은 식으로도 가능
<context:component-scan base-package="com.yk.yboard, com.yk.common"/>
아래는 버스앱의 경우에 대한 것이다.
<context:component-scan base-package="com.hubizict.bus" />
<context:include-filter type="" expression=""/>는 자동 스캔 대상에 포함시킬 클래스를 의미
<context:exclude-filter type="" expression=""/>는 자동 스캔 대상에 포함시키지 않을 클래스를 지정하는 의미
-->
<context:component-scan base-package="com.joe">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/>
</context:component-scan>
</beans>
이상의 작업을 통해서 eGov 프레임워크가 Controller 클래스를 인식하도록 설정이 되었다.
이제 Controller 클래스를 간단하게 만들어 보자. 해당 프로젝트의 src/main/java/ 아래에 패키지를 만든다.
src/main/java/ 위에서 마우스 우측 클릭 - New - Package
패키지 이름을 com.joe.egov.test를 만들어 보자.
생성된 패키지명 위에서 마우스 우측 클릭 - New - Class - MyController로 컨트롤러 클래스를 만들자.
이제 MyController 클래스를 다음과 같이 작성해 보자.
package com.joe.egov.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class MyController {
@RequestMapping(value="/mytest.do", method=RequestMethod.GET)
public String test(){
System.out.println("####### Hello this is MyController 클래스 ");
return "test.jsp";
}
}
이제 webapp 폴더 아래에 test.jsp파일을 생성해서 원하는 내용으로 작성해두면 MyController 실행후 test.jsp가 실행되어 확인이 편리할 것이다.
아래와 같이 실행해서 컨트롤러 클래스가 정상적으로 작동하는지 확인해 보자.
http://localhost:8081/TestTest/mytest.do
2018년 10월 26일 금요일
Instantiation of bean failed; Failed to instantiate [......]: Specified class is an interface 에러 문제
Spring(혹은 전자정부프레임워크)에서 maven build가 정상적으로 수행된 후에 『Run As - Java Application』으로 해당 클래스를 실행했을 때 다음과 같은 에러가 발생했다면 무엇이 문제라는 것일까?
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'messageBean' defined in class path resource [context-hello.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.joe.MessageBean]: Specified class is an interface
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1105)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1050)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at com.joe.HelloApp.main(HelloApp.java:10)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.joe.MessageBean]: Specified class is an interface
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:68)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1098)
... 13 more
위의 에러메시지에서 몇 가지 단서들을 확인할수 있는데
-. context-hello.xml에 있는 messageBean이라는 이름의 bean 객체를 생성하지 못했다는 것이고
Error creating bean with name 'messageBean' defined in class path resource [context-hello.xml]
-. bean을 생성하기 위해 지정된 클래스가 interface이기 때문에 bean(객체)를 생성할수 없다
Failed to instantiate [com.joe.MessageBean]: Specified class is an interface
참고로 context-hello.xml 파일의 내용은 다음과 같다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<bean name="messageBean" class="com.joe.MessageBean" />
</beans>
그러면 bean을 생성할 대상이 되는 클래스인 com.joe.MessageBean를 보면 다음과 같다.
package com.joe;
public interface MessageBean {
public void sayHello(String name);
}
따라서 결국은 문제가 된 것은 context-hello.xml에서 bean 생성 할 대상으로 지정한 클래스가 interface여서 발생한 에러였다. Java는 근본적으로 interface를 막바로 객체(bean) 생성할수가 없다. 만일 객체를 생성할수 있다고 한들 그 객체가 행할수 있는 기능(메소드) 자체가 정의되어 있지 않기 때문에, 위에서 보듯이 sayHello()라는 메소드가 무엇을 행할지 내용이 없다. 이것이 interface이다.
따라서 interface는 객체를 막바로 생성할수가 없고 생성할수 있다고 해도 그 객체(bean)이 아무런 동작도 할것이 없는것이다.
따라서 interface는 객체를 막바로 생성할수가 없고 생성할수 있다고 해도 그 객체(bean)이 아무런 동작도 할것이 없는것이다.
따라서 interface를 구현한(implements) 클래스를 객체로(bean)으로 생성하도록 context-hello.xml의 내용을 변경해 주어야 한다.
여기서 MessageBean 인터페이스를 구현한 하위 클래스는 다음과 같다.
package com.joe;
public class MessageBeanEng implements MessageBean {
@Override public void sayHello(String name){
System.out.println("Hello, "+name);
}
}
따라서 context-hello.xml의 내용을 바꾸어 주어야하는데 interface인 MessageBean을 그 구현 클래스인 MessageBeanEng로 변경해 주어야 하는 것이다.
<bean name="messageBean" class="com.joe.MessageBean" />
를 아래와 같이 바꾸어 주어야 한다.
<bean name="messageBean" class="com.joe.MessageBeanEng" />
피드 구독하기:
글 (Atom)

