처음에는 Spring Legacy Project를 생성하려고 STS3을 사용해보려고 했다. 그런데 최신 JDK와의 호환 문제로 인해 프로젝트 생성이 안됐고 STS3은 오래된 버전이라 최신 환경과 맞지 않는 부분이 많았다. 그래서 Eclipse 최신 버전에서 직접 Spring MVC + Maven 환경을 구성하는 방향으로 전환했다.
- Maven으로 Dynamic Web Project 생성
- pom.xml: Spring MVC 라이브러리 추가
- web.xml: DispatcherServlet 등록
- servlet-context.xml: ViewResolver 설정
- Controller/Service/Repository/VO 만들기
- JSP 만들기
: 웹 애플리케이션의 초기 설정 파일
(src/main/webapp/WEB-INF/web.xml)
/로 받게 되면, 전체 웹 요청을 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>
: Spring MVC의 내부 설정 파일
(src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml)
component-scan: 자동으로 Bean을 등록한다. (Controller, Service 등)<?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>
(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;
}
}
- web.xml: Spring과 MyBatis 연동을 위한 설정 파일 로드
- action-mybatis.xml: DB 및 MyBatis 관련 설정 정의
- jdbc.properties: DB 연결 정보를 담은 외부 설정 파일
- modelConfig.xml: MyBatis 전역 설정 파일로, TypeAlias 정의
- member.xml: 실제 DB와의 상호작용 수행하는 SQL 쿼리 정의
<!-- 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>
(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>
(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
(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>
(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>