Spring MVC: Maven + web.xml + JSP

suah·2025년 5월 1일

처음에는 Spring Legacy Project를 생성하려고 STS3을 사용해보려고 했다. 그런데 최신 JDK와의 호환 문제로 인해 프로젝트 생성이 안됐고 STS3은 오래된 버전이라 최신 환경과 맞지 않는 부분이 많았다. 그래서 Eclipse 최신 버전에서 직접 Spring MVC + Maven 환경을 구성하는 방향으로 전환했다.

Spring MVC 시작하기

  • Maven으로 Dynamic Web Project 생성
  • pom.xml: Spring MVC 라이브러리 추가
  • web.xml: DispatcherServlet 등록
  • servlet-context.xml: ViewResolver 설정
  • Controller/Service/Repository/VO 만들기
  • JSP 만들기

web.xml

: 웹 애플리케이션의 초기 설정 파일
(src/main/webapp/WEB-INF/web.xml)

  • DispatcherServlet은 Spring MVC의 프론트 컨트롤러이다.
  • DispatcherServlet을 등록해서 모든 요청을 가로채고 Spring이 처리하게 만든다.
  • 모든 요청을 /로 받게 되면, 전체 웹 요청을 Spring이 처리한다.
  • servlet-context.xml을 읽어 Spring 설정을 로딩한다.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
                             http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
         
  <!-- DispatcherServlet 등록 -->
	<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/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	
	<!-- URL 매핑 -->
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
</web-app>

servlet-context.xml

: Spring MVC의 내부 설정 파일
(src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml)

  • 컴포넌트 스캔, 뷰 리졸버, 메시지 변환기 등을 등록한다.
  • component-scan: 자동으로 Bean을 등록한다. (Controller, Service 등)
  • ViewResolver: 컨트롤러에서 반환한 "hello" -> /WEB-INF/views/hello.jsp로 찾아간다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       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.xsd
           http://www.springframework.org/schema/mvc 
           http://www.springframework.org/schema/mvc/spring-mvc.xsd
           http://www.springframework.org/schema/context 
           http://www.springframework.org/schema/context/spring-context.xsd">
	
	<!-- @Controller, @Service 등 스캔할 패키지 -->
	<context:component-scan base-package="com.spring.pro27" />
	
	<!-- @RequestMapping, @ResponseBody 등 MVC 기능 활성화 -->
	<mvc:annotation-driven />
	
	<!-- JSP에서 사용될 자바스크립나 이미지 파일 경로 지정 -->
	<mvc:resources mapping="/resources/**" location="/resources/" />
	
	<!-- ViewResolver: /WEB-INF/views/OOO.jsp로 이동 -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/views/" />
		<property name="suffix" value=".jsp" />
	</bean>
</beans>

Controller/Service/DAO/VO

(src/main/java/com/spring/pro27/member/controller/MemberController.java)

@Controller("memberController")
public class MemberController {
	@Autowried
    private MemberService memberService;
    
    @RequestMapping(value="/member/listMembers.do" ,method = RequestMethod.GET)
	public ModelAndView listMembers(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String viewName = "listMembers";
		List<MemberVO> membersList = memberService.listMembers();
		ModelAndView mav = new ModelAndView(viewName);
		mav.addObject("membersList", membersList);
		return mav;
	}
    
    @RequestMapping(value="/member/addMember.do", method=RequestMethod.POST)
    public ModelAndView addMember(@ModelAttribute("member") MemberVO member, HttpServletRequest request, HttpServletResponse response) throws Exception {
    	request.setCharacterEncoding("utf-8");
        int result = memberService.addMember(member);
        ModelAndView mav = new ModelAndView("redirect:/member/listMembers.do");
        return mav;
    }
    
    @RequestMapping(value="/member/removeMember.do" ,method = RequestMethod.GET)
	public ModelAndView removeMember(@RequestParam("id") String id, 
			           HttpServletRequest request, HttpServletResponse response) throws Exception{
		request.setCharacterEncoding("utf-8");
		memberService.removeMember(id);
		ModelAndView mav = new ModelAndView("redirect:/member/listMembers.do");
		return mav;
	}
}

(src/main/java/com/spring/pro27/member/service/MemberService.java)

@Service("memberService")
@Transactional(propagation = Propagation.REQUIRED)
public class MemberService {
	@Autowired
    private MemberDAO memberDAO;
    
    public List<MemberVO> listMembers() throws DataAccessException {
		List<MemberVO> membersList = null;
		membersList = memberDAO.selectAllMemberList();
		return membersList;
	}
    
	public int addMember(MemberVO member) throws DataAccessException {
		return memberDAO.insertMember(member);
	}

	public int removeMember(String id) throws DataAccessException {
		return memberDAO.deleteMember(id);
	}
}

(src/main/java/com/spring/pro27/member/dao/MemberDAO.java)

@Repository("memberDAO")
public class MemberDAO {
	@Autowired
	private SqlSession sqlSession;
    
    public List<MemberVO> selectAllMemberList() throws DataAccessException {
		List<MemberVO> membersList = null;
		membersList = sqlSession.selectList("mapper.member.selectAllMemberList");
		return membersList;
	}
    
	public int insertMember(MemberVO memberVO) throws DataAccessException {
		int result = sqlSession.insert("mapper.member.insertMember", memberVO);
		return result;
	}

	public int deleteMember(String id) throws DataAccessException {
		int result = sqlSession.delete("mapper.member.deleteMember", id);
		return result;
	}
}

(src/main/java/com/spring/pro27/member/vo/MemberVO.java)

@Component("memberVO")
@Getter
@Setter
public class MemberVO {
	private String id;
	private String pwd;
	private String name;
	private String email;
	private Date joinDate;
	
	public MemberVO() {
	}
	
	public MemberVO(String id, String pwd, String name, String email) {
		this.id = id;
		this.pwd = pwd;
		this.name = name;
		this.email = email;
	}
}

MyBatis 연동

  • web.xml: Spring과 MyBatis 연동을 위한 설정 파일 로드
  • action-mybatis.xml: DB 및 MyBatis 관련 설정 정의
  • jdbc.properties: DB 연결 정보를 담은 외부 설정 파일
  • modelConfig.xml: MyBatis 전역 설정 파일로, TypeAlias 정의
  • member.xml: 실제 DB와의 상호작용 수행하는 SQL 쿼리 정의

web.xml

<!-- action-mybatis.xml 읽음 -->
<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>/WEB-INF/spring/action-mybatis.xml</param-value>
</context-param>
	
<!-- 모든 서블릿과 필터가 공유하는 스프링 컨테이너 생성 -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

action-mybatis.xml

(src/main/webapp/WEB-INF/spring/action-mybatis.xml)

sqlSession을 bean으로 설정해놓아야 @Autowired private SqlSession sqlSession;에 bean이 들어와 처리가 가능하다.

<?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.xsd">
	      
	<bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<value>/WEB-INF/config/jdbc/jdbc.properties</value>
		</property>
	</bean>
	
    <!-- MyBatis가 사용하는 커넥션 풀 설정 -->
	<bean id="dataSource" class="org.apache.ibatis.datasource.pooled.PooledDataSource">
		<property name="driver" value="${jdbc.driverClassName}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
	</bean>

	<!-- MyBatis의 SQL 세션을 생성하는 핵심 Bean -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="configLocation" value="classpath:mybatis/model/modelConfig.xml" />
		<property name="mapperLocations" value="classpath:mybatis/mappers/*.xml" />
	</bean>

	<!-- DAO에서 사용할 MyBatis의 SQL 실행 템플릿 -->
	<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
	</bean>
</beans>

jdbc.properties

(src/main/webapp/WEB-INF/config/jdbc/jdbc.properties)

jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1521:XE
jdbc.username=c##scott
jdbc.password=tiger

modelConfig.xml

(src/main/resources/mybatis/model/modelConfig.xml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
	<typeAliases>
		<typeAlias type="com.spring.pro27.member.vo.MemberVO" alias="memberVO" />
	</typeAliases>
</configuration>

member.xml

(src/main/resources/mybatis/mappers/member.xml)

<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
   	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="mapper.member">
	<resultMap id="memResult" type="memberVO">
		<result property="id" column="id" />
    	<result property="pwd" column="pwd" />
    	<result property="name" column="name" />
    	<result property="email" column="email" />
    	<result property="joinDate" column="joinDate" />
	</resultMap>

	<select id="selectAllMemberList" resultMap="memResult">
		<![CDATA[
    		select * from t_member	order by joinDate desc	 	
    	]]>
	</select>
    
  	<insert id="insertMember"  parameterType="memberVO">
		<![CDATA[
		 	insert into t_member(id,pwd, name, email)
		 	values(#{id}, #{pwd}, #{name}, #{email})
		]]>      
	</insert>
     
  	<delete id="deleteMember"  parameterType="String">
		<![CDATA[
	  		delete from  t_member
	  		where
	  		id=#{id}
		]]>      
	</delete>
</mapper>
profile
IT developer

0개의 댓글