Spring Lagacy Project, Spring MVC, MyBatis 인텔리제이에서 세팅하기
스프링 레거시 프로젝트
스프링 레거시 프로젝트를 수업에서 eclipse와 비슷한 Spring sts로 생성하였으나, 인텔리제이 환경에서 작업을 해보고 싶어 처음부터 세팅해보았다.
쉽게 스프링으로 만드는 방법도 있는 것 같지만, 현재 인텔리제이 무료 버전 (Community Version)을 사용하고 있어, 하나하나 손수 세팅해주어야 한다고 하여 후에 프로젝트 세팅을 위해 기록으로 남겨보았다.
1. Maven 프로젝트 새로 만들기
Project -> 새로 만들기 -> Maven 프로젝트를 선택해준다.
중간에 Archetype을 maven-webapp으로 설정해주어야 한다.
나는 현재 배우고 있는 과정의 버전이 11이기 때문에 11로 하였다. 대부분 17로 하는 것을 추천한다.
이름, 위치는 자유이고, 그룹 아이디는 도메인, 버전은 나중에 고쳐줄 것이기 때문에 기본으로 하였다.
2. pom.xml
기본 설정을 해 줄 차례이다.
내가 설정한 프로젝트 정보는 아래와 같다.
<?xml version="1.0" encoding="UTF-8"?>
<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>kr.co</groupId>
<artifactId>mvcproject</artifactId>
<name>mvcproject Maven Webapp</name>
<packaging>war</packaging>
<version>1.0.0-BUILD-SNAPSHOT</version>
<properties>
<java-version>11</java-version>
<org.springframework-version>5.2.25.RELEASE</org.springframework-version>
<org.aspectj-version>1.9.24</org.aspectj-version>
<org.slf4j-version>1.6.6</org.slf4j-version>
</properties>
<url>http://maven.apache.org</url>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.24</version>
<scope>runtime</scope>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>
<!-- @Inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.38</version>
</dependency>
<!-- Hikari CP -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>6.3.0</version>
</dependency>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.19</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.1.2</version>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc10</artifactId>
<version>19.27.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.25.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.25.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<additionalProjectnatures>
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
</additionalProjectnatures>
<additionalBuildcommands>
<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
</additionalBuildcommands>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>11</source>
<target>11</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>org.test.int1.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
조금 길긴 한데, 대부분 받은 pom을 복사해서 썼고, 중요한 부분만 분석해 보았다.
<project> 상단
groupId, name, modelVersion 등 처음 maven 설정 시에 세팅해주었던 내용들이 있다.
<packaging> war </packaging>
이 부분이 있어야 war파일을 내보내, 나의 톰캣으로 서버를 연결할 수 있다고 한다.
<properties>
java 버전, 스프링 프레임워크 버전, aspectJ(AOP), 로그 라이브러리 등의 버전이 기재되어 있다.
<dependencies>
각종 외부 라이브러리들을 넣을 수 있는 곳이다. 여기서 mybatis와 hikari, lombok등을 사용하기 위해 넣었다.
라이브러리들은 아래 주소에서 다운로드 받았다.
<configuration>
컨피규레이션안의 source, target을 11로 해주었다.
3. Web.xml 설정
다음으로 web.xml을 설정해주었다.
XML 방식과 Java 방식이 있지만, Java 방식을 택했다.
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- <!– The definition of the Root Spring Container shared by all Servlets and Filters –>-->
<!-- <context-param>-->
<!-- <param-name>contextConfigLocation</param-name>-->
<!-- <param-value>/WEB-INF/spring/root-context.xml</param-value>-->
<!-- </context-param>-->
<!-- <!– Creates the Spring Container shared by all Servlets and Filters –>-->
<!-- <listener>-->
<!-- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>-->
<!-- </listener>-->
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- java 방식 -->
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>spring.MvcConfig</param-value>
</init-param>
<!-- XML 방식
<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>
<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>/*</url-pattern>
</filter-mapping>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
서블릿 태그 내의 정보가 Java 방식이고, 주석 처리된 부분은 Xml 방식이다. xml 방식의 경우 추가로 경로에 해당하는 xml 파일이 필요하다. 하나 유의할 점은 contextConfigLocation 부분에 Config로 사용할 java 파일의 경로를 넣어주어야 한다. 나의 경우 spring 폴더 아래 MvcConfig로 설정해주었다,
마지막으로, 한글 깨짐을 방지하기 위해 UTF-8 인코딩 필터를 넣어주었다.
MvcConfig 설정
이곳에서 MyBatis를 포함하여 SpringMVC의 Config파일을 java코드 형식으로 설정해 줄 것이다.
먼저, Configuration으로 쓸 것을 선언하기 위한 어노테이션 @Configuration, 스프링 부트의 자동 설정을 꺼주기 위한 @EnableWebMvc, 해당 패키지를 기준으로 아래의 등록된 모든 Bean객체들을 스캔해줄 @ComponentScan 어노테이션을 달아주었다.
package spring;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.sql.DataSource;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "spring")
public class MvcConfig implements WebMvcConfigurer {
// 뷰리졸버 - 컨트롤러에서 포워딩할 경로(앞/뒤) 설정
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/WEB-INF/views/", ".jsp");
}
// HikariCP
@Bean
public DataSource dataSource() {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setDriverClassName("oracle.jdbc.OracleDriver");
dataSource.setJdbcUrl("jdbc:oracle:thin:@localhost:1521:orcl");
dataSource.setUsername("system");
dataSource.setPassword("test1234");
return dataSource;
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer config) {
config.enable();
}
// MyBatis
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean ssf = new SqlSessionFactoryBean();
ssf.setDataSource(dataSource()); // 의존성주입 (DI)
// MyBatis 설정 객체 생성
org.apache.ibatis.session.Configuration myBatisConfig = new org.apache.ibatis.session.Configuration();
myBatisConfig.setMapUnderscoreToCamelCase(true); // <-- db컬럼 명을 java의 카멜 케이스로 변환 설정
ssf.setConfiguration(myBatisConfig);
// mapper파일 위치 설정
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
ssf.addMapperLocations(resolver.getResources("classpath:/mapper/**/*.xml"));
return ssf.getObject();
}
// DAO에 주입될 객체
// sql실행하려고
@Bean
public SqlSessionTemplate sst() throws Exception {
return new SqlSessionTemplate(sqlSessionFactory()); // 의존성주입(생성자방식)
}
}
함수 설명
1. configureViewResolvers
// 뷰리졸버 - 컨트롤러에서 포워딩할 경로(앞/뒤) 설정
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/WEB-INF/views/", ".jsp");
}
view의 경로를 설정해주는 함수이다. prefix로는 폴더 경로, suffix로는 확장자를 적어주었다.
이렇게하면, jsp확장자를 뷰 리졸버가 해당 폴더 내에서 매치시켜준다.
view를 따로 관리하기 위해 jsp파일을 모아둘, views 폴더를 webapp 폴더 아래에 만들어주어야 한다.
2. dataSource
// HikariCP
@Bean
public DataSource dataSource() {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setDriverClassName("oracle.jdbc.OracleDriver");
dataSource.setJdbcUrl("jdbc:oracle:thin:@localhost:1521:orcl");
dataSource.setUsername("system");
dataSource.setPassword("test1234");
return dataSource;
}
내 오라클 db정보를 넣을 데이터소스 객체를 선언해준다.
dataSource 란?
- DataSource는 DB 커넥션을 얻는 객체
- Spring에서는 주로 HikariCP가 기본
- 실무에서는 반드시 커넥션 풀(DataSource 구현체)을 사용해야 성능이 좋음
- Spring Boot는 application.yml만 설정하면 자동 구성됨
커넥션 풀 동작 개념
- 초기화 시점에 N개의 커넥션을 생성
- 클라이언트가 getConnection() 하면 기존 커넥션에서 하나 반환
- 작업 후 close()를 호출하면 커넥션이 닫히지 않고 풀에 반환
- 일정 수 이상 요청 시 → 대기하거나 예외 발생
3. configureDefaultServletHandling
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer config) {
config.enable();
}
기본적으로 DispatcherServlet은 모든 요청을 가로채기 때문에, /resources/**, /static/** 같은 경로의 정적 리소스도 컨트롤러에서 처리하려고 시도한다.
하지만 우리는 보통 정적 리소스는 Spring이 아닌 톰캣 기본 서블릿이 처리하게 하고 싶기 때문에 이 함수를 사용해야 한다.
4. MyBatis
// MyBatis
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean ssf = new SqlSessionFactoryBean();
ssf.setDataSource(dataSource()); // 의존성주입 (DI)
// MyBatis 설정 객체 생성
org.apache.ibatis.session.Configuration myBatisConfig = new org.apache.ibatis.session.Configuration();
myBatisConfig.setMapUnderscoreToCamelCase(true); // <-- db컬럼 명을 java의 카멜 케이스로 변환 설정
ssf.setConfiguration(myBatisConfig);
// mapper파일 위치 설정
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
ssf.addMapperLocations(resolver.getResources("classpath:/mapper/**/*.xml"));
return ssf.getObject();
}
mybatis를 이용하여 쿼리를 연결해 줄 경로를 밝혀주고, db에서 스네이크 케이스를 java코드 상의 카멜 케이스로 매핑 시켜주기 위해 옵션을 주었다. 앞으로 myBatis로 사용할 쿼리는 이곳에 적힌 파일명으로 매칭시켜주면 된다. getResource로 리소스 폴더를 가져온 뒤, mapper 폴더 하위 폴더 아래의 xml을 자동으로 찾아 쿼리를 실행해준다.
5. DAO 주입
// DAO에 주입될 객체
// sql실행하려고
@Bean
public SqlSessionTemplate sst() throws Exception {
return new SqlSessionTemplate(sqlSessionFactory()); // 의존성주입(생성자방식)
}
마지막으로 생성자 방식의 의존성 주입으로 위에서만든 함수를 넣어준다.
테스트
all 이라는 경로에 파라미터를 넣어 내 db의 멤버의 이름을 띄워줄 것이다.
resource -> mapper -> member -> member.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="member">
<select id="all" resultType="spring.MemberVO">
SELECT * FROM USERS
</select>
</mapper>
VO 객체와 연결, id는 all로 설정 후 태그 내에 쿼리문 작성 select 태그로 지정, 네임 스페이스는 member로 설정
webapp -> WEB-INF -> views -> member -> all.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<c:forEach var="a" items="${list }">
${a.userName }
</c:forEach>
</body>
</html>
VO 상의 카멜케이스 변수이름으로 접근, jstl 라이브러리 사용
src -> main -> java -> spring -> MemberController.java
package spring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MemberController {
@Autowired
private MemberDAO dao;
@GetMapping("/member/all")
public void all(Model model) {
model.addAttribute("list", dao.all());
System.out.println(dao.all());
}
}
list로 주입 받은 dao에서 /member/all로 들어온 요청을 처리하여 세팅해준 뒤 jsp로 쏴주기
src -> main -> java -> spring -> MemberDao.java
package spring;
import java.util.List;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
public class MemberDAO {
@Autowired
private SqlSessionTemplate sst; // 자동주입
public List<MemberVO> all() {
return sst.selectList("member.all");
}
}
sst 주입, memberVO를 가져온다. 매개변수는 이전에 mybatis 파일의 네임 스페이스의 아이디를 넣어주면 된다
src -> main -> java -> spring -> MemberVO.java
db컬럼명이 스네이크 케이스 였으므로, 카멜 케이스로 만든 VO를 만들어주었다. Lombok을 이용하면 코드가 확 줄어든다.
package spring;
import java.sql.Date;
import lombok.Data;
@Data
public class MemberVO {
private String userId;
private String userName;
private String loginId;
private String password;
private String email;
}
모든 설정이 끝났다. 이제 톰캣 실행 후 접속 !! 하기전에
톰캣 설정
구성 편집 or Project -> BuildConfiguration에서 나의 Tomcat으로 설정해주어야 한다.
나는 처음에 Tomcat server가 없어서 File -> Setting의 Plugin에서 찾아보았으나, 이름이 바뀐 것 같아 Smart Tomcat으로 받아주었다.
Tomcat server 부분을 나의 톰캣으로 불러와주면 된다.
이후 빌드해보면.................
화면이 잘 나오는 것을 볼 수 있다.!!