3.x에서는 resources의 xml로 설정하는 부분이 많이 줄었고 이러한 설정 파일들이 .java 파일로 대체 되었다.
pom.xml
cglib와 mybatis,servlet, taglib, jstl-api
log4j -> logback 로변경
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.0.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>0.9.26</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-dbcp/commons-dbcp -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.taglibs/taglibs-standard-impl -->
<dependency>
<groupId>org.apache.taglibs</groupId>
<artifactId>taglibs-standard-impl</artifactId>
<version>1.2.5</version>
<scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
Servlet 3.0 부터는 Java로 web.xml 환경설정 하는 부분이 가능.
ServletContainerInitializer 클래스를 implements 해서 onStartUp에 초기설정관련소스를 추가하여 작업이 가능하다.
spring 에서 제공하는 라이브러리 (spring-web) 를보면 내부적으로 사용가능하게 이미 SpringServletContainerInitalizer를 제공하고 있다.public class SpringServletContainerInitializer implements ServletContainerInitializer{}
package example.initializer;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.DispatcherServlet;
import example.configuration.ApplicationConfiguration;
import example.configuration.DispatcherConfiguration;
// servlet 3.0부터는 인터페이스만 구현하면 기존 web.xml에 구현되었던 것들이 구현됨.
public class ExampleInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
// applicationConfiguration 등록
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(ApplicationConfiguration.class);
servletContext.addListener(new ContextLoaderListener(rootContext));
// DispatcherConfiguration 등록
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
applicationContext.register(DispatcherConfiguration.class);
// servlet 등록
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher",
new DispatcherServlet(applicationContext));
System.out.println("dispatcher : " + dispatcher);
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
// utf8 필터 등록
FilterRegistration.Dynamic filter = servletContext.addFilter("characterEncodingFilter",
CharacterEncodingFilter.class);
filter.setInitParameter("encoding", "UTF-8");
filter.setInitParameter("forceEncoding", "true");
filter.addMappingForUrlPatterns(null, false, "/*");
}
}
example.configuration
DatabaseConfiguration
- @Configuration 어노테이션은 기존에 xml에 빈설정하는 부분을 자바에서 할수있도록 새롭게 추가된 기능이다.
- @Bean 어노테이션은 메소드가 실행되고 리턴된 객체가 spring(메모리)에 등록된다.
- DataSource를 생성하고 리턴 한다.
Mybatis에서는 Mapper로 Dao가대체된형태이며, mapper를 스캔대상을 설정하는 부분이다.
configurer.setBasePackage : 기본패키지경로를 example.mapper 로설정
Factory에서 사용할 데이터소스를 setMapper가 동작할때 실제 사용될 쿼리 (xml) 파일경로를 set
해당정보로 xml 파싱및빌드 된 후 리턴한다.
package example.configuration;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
@Configuration
public class DatabaseConfiguration {
final Logger logger = LoggerFactory.getLogger(getClass());
/**
* DataSource bean 등록
* @return
*/
@Bean
public DataSource dataSource() {
MysqlDataSource dataSource = new MysqlDataSource();
dataSource.setUser("root");
dataSource.setPassword("1234");
dataSource.setPort(3307);
dataSource.setDatabaseName("profile");
dataSource.setUrl("jdbc:mysql://localhost:3307/profile");
return dataSource;
}
/**
* mapper 스캐너 빈 등록
* @return
*/
@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
//mybatis에서 제공하는 클래스 : 해당 클래스가 있는 곳을 스캔함.
MapperScannerConfigurer configurer = new MapperScannerConfigurer();
configurer.setBasePackage("example.mapper");
return configurer;
}
/**
* SqlSessionFactory 빈 등록 : board.xml로 연동됨.
* @return
* @throws Exception
*/
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource());
factoryBean
.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources("classpath:/config/mapper/**.xml"));
return factoryBean.getObject();
}
}
example.configuration
ApplicationConfiguration.java
@Import : value에 [] 배열로 설정을 선언 할 수 있음 (설정의 종류마다 클래스로 관리에좋음)
@ComponentScan
basePackage : 스캔 대상 패키지,
includeFilters : 불러올 어노테이션 클래스 필터
package example.configuration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import(value = DatabaseConfiguration.class)
public class ApplicationConfiguration {
}
example.configuration
DispatcherCOnfiguration.java
dispatcher-servlet.xml 에 처리 하던 부분이 java로 가능 하다.
ViewResolver를 등록 해준다. (jsp 렌더링)
@EnableWebMvc : DelegatingWebMvcConfiguration 클래스를 불러와서 해당클래스에 구현된 기능들이 동작하게 한다
package example.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "example")
public class DispatcherConfiguration {
/**
* JSP ViewResolver
* @return
*
*/
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver resolver=new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
package example.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import example.service.BoardService;
@Controller
public class BoardController {
//slf4j 제공한걸로 바꿈
final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
//boardService가 인스턴스되서 자동으로 주입된다.
private BoardService boardService;
/**
* 게시물 목록 조회 및 화면
* @param model
* @return
*/
@RequestMapping(value="/board/list", method = { RequestMethod.GET })
public String list(ModelMap model) { // 객체를 인스턴스해서 ModelMap 주입시켜줌
// 파라미터에 HttpServletRequest넣고
// request.getMethod().equals("GET")
// 게시물 목록 조회를 boardService에 호출하고 결과값을 boarList key값으로 request에 저장한다.
model.addAttribute("boardList", boardService.selectBoardList());
// jsp를 호출
return "/board/list";
}
}
BoardDao -> BoardMapper 변경
example.dao -> example.mapper 로패키지변경
BoardDao -> BoardMapper 로변경
class -> interface로 변경
mapper를 사용하게되면 실제 구현체소스가 필요가없다
boardmapper.interface
package example.mapper;
import java.util.List;
public interface BoardMapper {
List<Board> selectBoardList();
Board selectBoard(int boardSeq);
void insertBoard(Board board);
void deleteBoard(int boardSeq);
void updateBoard(Board board);
}
boardService 변경
DAO -> Mapper로 변경
package example.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import example.mapper.Board;
import example.mapper.BoardMapper;
@Service
public class BoardService {
@Autowired
private BoardMapper boardMapper; //boardMapper주입
/**
* 게시물 목록 조회후 리턴
*
* @return
*
*/
public List<Board> selectBoardList() {
return boardMapper.selectBoardList(); //boardMapper.으로 변경
}
}
board.xml
sqlmap → mapper로 변경
namespace : mapper에 실제 연결할 인터페이스 패키지 + 파일명 (BoardMapper)class → type로 변경됨
<?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="example.mapper.BoardMapper">
<!-- 결과 맵 -->
<resultMap id="selectBoardListResultMap" type="example.mapper.Board">
<result column="BOARD_SEQ" property="boardSeq" />
<result column="BOARD_TYPE" property="boardType" />
<result column="TITLE" property="title" />
<result column="USER_NAME" property="userName" />
<result column="REG_DATE" property="regDate" />
</resultMap>
<!-- 상세 조회 결과 맵 -->
<resultMap id="selectBoardResultMap" type="example.mapper.Board">
<result column="BOARD_SEQ" property="boardSeq" />
<result column="BOARD_TYPE" property="boardType" />
<result column="TITLE" property="title" />
<result column="CONTENTS" property="contents" />
<result column="REG_DATE" property="regDate" />
<result column="USER_NAME" property="userName" />
</resultMap>
<!-- 게시물 목록 쿼리 -->
<select id="selectBoardList" resultMap="selectBoardListResultMap">
SELECT BOARD_SEQ, BOARD_TYPE, TITLE, REG_DATE, USER_NAME
FROM T_BOARD
ORDER BY REG_DATE DESC
</select>
<!-- 게시물 목록 쿼리 -->
<select id="selectBoard" resultMap="selectBoardResultMap">
SELECT BOARD_SEQ, BOARD_TYPE, TITLE, CONTENTS, REG_DATE, USER_NAME
FROM T_BOARD
WHERE BOARD_SEQ = #boardSeq#
</select>
<!-- 게시물 등록 쿼리 -->
<insert id="insertBoard" parameterType="example.mapper.Board">
INSERT INTO T_BOARD
(
BOARD_TYPE,
TITLE,
CONTENTS,
REG_DATE,
USER_NAME
)
VALUES
(
#boardType#,
#title#,
#contents#,
NOW(),
#userName#
)
</insert>
<!-- 게시물 업데이트 쿼리 -->
<insert id="updateBoard" parameterType="example.mapper.Board">
UPDATE T_BOARD SET
BOARD_TYPE = #boardType#,
TITLE = #title#,
CONTENTS = #contents#,
REG_DATE = NOW(),
USER_NAME = #userName#
WHERE BOARD_SEQ = #boardSeq#
</insert>
<!-- 게시물 삭제 쿼리 -->
<delete id="deleteBoard" parameterType="int">
DELETE FROM T_BOARD
WHERE BOARD_SEQ = #boardSeq#
</delete>
</mapper>