아직 스프링에 대한 이해도가 높지 못하기 때문에 설정에 일부 불필요한 부분이 있을 수 있고 자세한 설명은 (저도 잘 모르는 관계로) 어느정도 생략하고 넘어갑니다.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>outsider.ne.kr</groupId>
<artifactId>helloworld</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>helloworld</name>
<url>http://maven.apache.org</url>
<properties>
<java.version>1.6</java.version>
<spring.version>3.0.5.RELEASE</spring.version>
<org.slf4j.version>1.6.1</org.slf4j.version>
<downSource>true</downSource>
<downJavadoc>true</downJavadoc>
<wtpContextName>helloworld</wtpContextName>
</properties>
<dependencies>
<!-- Spring dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>org.springframework.spring-library</artifactId>
<type>libd</type>
<version>${spring.version}</version>
<exclusions>
<exclusion> <!-- declare the exclusion here -->
<groupId>javax.servlet</groupId>
<artifactId>com.springsource.javax.servlet</artifactId>
</exclusion>
</exclusions>
</dependency> </dependencies>
<repositories>
<repository>
<id>com.springsource.repository.bundles.release</id>
<name>SpringSource Enterprise Bundle Repository - SpringSource Bundle Releases</name>
<url>http://repository.springsource.com/maven/bundles/release</url>
</repository>
<repository>
<id>com.springsource.repository.bundles.external</id>
<name>SpringSource Enterprise Bundle Repository - External Bundle Releases</name>
<url>http://repository.springsource.com/maven/bundles/external</url>
</repository>
<repository>
<id>com.springsource.repository.libraries.release</id>
<name>SpringSource Enterprise Bundle Repository - SpringSource Library Releases</name>
<url>http://repository.springsource.com/maven/libraries/release</url>
</repository>
<repository>
<id>com.springsource.repository.libraries.external</id>
<name>SpringSource Enterprise Bundle Repository - External Library Releases</name>
<url>http://repository.springsource.com/maven/libraries/external</url>
</repository>
</repositories>
</project>
Maven을 사용하고 있는 관계로 프로젝트 관리를 위한 pom.xml입니다.(필요없는 부분은 지웠습니다.) pom.xml의 양이 많기 때문에 다 설명하기는 어렵기 때문에 간단히 설명하면 Spring 3.0.5.RELEASE 버전을 사용하며 간단한 Hello World코드이기 때문에 스프링프레임워크가 전부 필요하진 않지만 차후 확장을 위한 기본 골격이기에(일일이 의존성까지 맞추기도 어렵고 해서) SpringSource Enterprise Bundle Repository에서 Spring 3.0.5 RELEASE를 모두 가져오도록 했으며 EBR에서 라이브러리를 가져오도록 <repository>를 추가했습니다.
<?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" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 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>HelloWorld</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext*.xml</param-value>
</context-param>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log4j.properties</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
web/WEB-INF/web.xml 파일입니다. <context-param>을 이용해서 스프링의 applicationContext.xml를 설정하고(여러가지 applicationContext를 사용하도록 applicationContext*.xml과 같이 작성하였습니다.) log4j에 대한 프로퍼티 파일을 지정하였습니다. vaule에 classpath:를 지정하였기 때문에 해당 파일을 클래스패스에서 찾게 되기 때문에 소스폴더인 src폴더 바로 아래에 위 파일들을 위치해두면 컴파일시에 클래스패스에 포함되게 됩니다. 리스너는 ContextLoaderListener를 지정하고 요청을 처리하기 위해서 DispatcherServlet을 spring이라는 이름으로 등록해주고 이 서블릿은 /app/*에 매핑합니다.
<?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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<context:component-scan base-package="kr.ne.outsider.helloworld.web" />
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
web/WEB-INF/spring-servlet.xml 파일입니다. web.xml에서 DispatcherServlet을 spring이라는 이름으로 등록했기 때문에 spring-servlet.xml이라는 파일명을 사용했습니다. 다른 파일명을 사용하려면 web.xml에서 서블릿을 등록할 때 contextConfigLocation를 이용하여 파일을 지정해 주어야 합니다.
<context:component-scan>에서는 annotation을 찾을 패키지명을 지정합니다. 여러개를 지정할 경우에는 콤마(,)를 이용합니다. DefaultAnnotationHandlerMapping는 type레벨에서 @RequestMapping을 처리하고 AnnotationMethodHandlerAdapter는 메서드레벨에서 처리하는데 사용합니다. 이 2가지는 DispatcherServlet을 사용할 경우 디폴트로 사용되지만 다른 핸들러맵핑을 합께 사용하려고 하면 지정하여야 합니다. InternalResourceViewResolver에서 prefix와 suffix를 주어서 Controller에서 이름만 지정해주고 뷰로 사용할 JSP를 찾도록 하였습니다.
// HelloWorldController.java
package kr.ne.outsider.helloworld.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class HelloWorldController {
@RequestMapping(value="/helloworld", method=RequestMethod.GET)
public ModelAndView example() {
return new ModelAndView("helloworld", "message", "Hello World");
}
}
헬
로월드를 출력할 컨트롤러 파일입니다. 로직은 필요없기 때문에 소스는 컨트롤러만 구성했으며 컨트롤러를 사용하기 위해서
@Controller를 지정하고 /helloworld에 대한 GET요청을 받아서 Hello World를 출력하도록
@RequestMapping를 설정했습니다.
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Hello World</title>
</head>
<body>
${message}
</body>
</html>
web/WEB-INF/views/helloworld.jsp 파일입니다. 여기서 HelloWorldController에서 message에 지정한 "Hello World"를 출력합니다. 이제 http://localhost:8080/helloworld/app/helloworld에 접근하면 Hello World가 찍히는 페이지를 볼 수 있습니다.(context명때문에 URL이 이쁘진 않군요 ㅎㅎ) 혹 참고용으로 프로젝트 소스를 함께 올려놓습니다.
스프링소스에서 제공하는 샘플을 참고해도 많이 도움이 될 것 같습니다.
안녕하세요!
여러 가지로 도움을 받고 있는 사람입니다~
방대한 양의 자료와 다양한 분야에 대해서 알려주셔서 감사드려요 ㅋ
얼마 전에 node.js 책 집필하신 것도 구매해서 잘 보고 있습니다 ㅋ
다름이 아니라 좀 여쭤봐도 될까요?
Spring 구조에서 WebContent폴더 하단이 아니라
WEB-INF 하단에 jsp 파일들을 위치시켰을 때, 여러 가지 CSS파일이나 JS파일들을
끌어다 쓸 때 계속 오류가 나서요.
1. Spring구조에서 WebContent폴더 하단에 위치해서 썼을 때 문제가 있는것인지
(직접 접근을 할 수는 있지만 굳이 WEB-INF에 넣어서 직접 접근을 막아야 하는지)
2. WEB-INF에 위치시켰을때
<script type="text/javascript" src="~" /> 이런 방법 외에
끌어다 쓸 수 있는 방법이 있는지 궁금합니다.
워낙 유명하시고 바쁘셔서 답변을 해주실 여유가 있으실 지 걱정되지만,
기대해봅니다~ ;D
좋은 포스팅 감사드립니다!
hjsohn.ex@gmail.com 으로 해주시면 더 감사하겠습니당.
댓글도 감사하구용.
구매해주셔서 감사합니다. ㅎㅎㅎㅎ
제가 스프링은 명확하게 답변드리기가 여려울것 같아서 스프링 전문가를 모셔와서 아래 답변 달았습니다. ㅎㅎㅎ 참고하세요 ㅎ
@Hyunjoon Sohn
지나가다가 간단히 답변 달아봅니다.
1. Spring구조에서 WebContent폴더 하단에 위치해서 썼을 때 문제가 있는것인지
(직접 접근을 할 수는 있지만 굳이 WEB-INF에 넣어서 직접 접근을 막아야 하는지)
=> 서블릿 컨테이너는 WEB-INF 이하 디렉토리는 보안상 외부 접근을 막지만, request forwarding을 통한 접근을 허용합니다.
대부분의 Web Framework은 MVC 모델을 사용합니다.
Model과 Controller에서 적절한 비즈니스 행위를 수행한 후 View(JSP)로 일련의 값이 전달되어 결과가 그려지게되는 구조인데, 이런 구조에서 직접 JSP에 접근을 할 필요도 없을 뿐더러, 직접 접근이 가능할때는 JSP의 소스가 그대로 노출되는 보안 위협도 있습니다. 그래서 WEB-INF 이하에 넣어두는것을 '추천' 합니다.
(참고: 서블릿 컨테이너 설정을 통해서 jsp 접근을 차단 할 수도 있습니다.)
2. WEB-INF에 위치시켰을때 <script type="text/javascript" src="~" /> 이런 방법 외에
끌어다 쓸 수 있는 방법이 있는지 궁금합니다.
끌어다 쓴다라는 말이 잘 이해가 안가네요;;
어디에서 사용을 하던 css, js 등의 리소스는 jstl url tag 류로 full path를 많이 사용하는것으로 알고 있습니다.
@arawn 땡큐~
안녕하세요!
다음날 댓글 달아주신거 확인하고 너무 감사드렸는데 글을 이제야 남기네요~
유용한 정보들을 이렇게 생산해내실 수 있다는게 부러울 따름입니다.
@arawn 님께서 말씀하신대로 WEB-INF에 jsp파일들을 두고 나머지 리소스들은
WebContents 바로 하단폴더에 위치해서 개발하고 있습니다.
(분리하면 되는 것을 인지하지 못한 게 부끄럽네요.)
저는 UI쪽으로만 계속 개발하고 있었는데, 곧 Spring+node.js 까지 해보려고 합니다.
그때는 더 많이 와서 질문... >_<)b
배우는 입장에서 댓글을 달아주신 게 싸인받는 것보다 기분이 좋네요 :D
날씨도 좋은데, 좋은 하루 보내세요!
잘 해결하셨다니 다행이네요... ㅎㅎㅎㅎ
뭐 정보는 별거는 아니지만 누군가 저보다 늦게 보는 사람이 있는거니까요 ^^
좋은 하루 보내세요.