Chapter#01 : [Spring] IntelliJ를 사용한 Spring Project 생성 및 설정(Maven)
Chapter#02 : [Spring] Spring MVC 패턴 적용하기
Chapter#03 : [Spring] Component-Scan을 사용하는 Annotation 기반 설정
Chapter#04 : [Spring] MyBatis를 사용한 DataBase 연동 - MySQL
컴포넌트의 개념
· 물리적이고 대체 가능한 시슽메의 부분으로써 제공하는 일련의 인터페이스를 준수하는 구현 패키지다.
· 인터페이스를 통해서 서비스를 제공하는 소프트웨어 패키지다.
· 특별한 기능을 수행하고 미리 구현되고, 미리 테스트된 독립적이고, 재사용 가능한 소프퉤어 단위이다.
컴포넌트는 하나 또는 여러개의 클래스로 구현될 수 있다.
공통 컴포넌트란 건축물의 창문이나 조명 등과 같이 정보시스템을 구축할 때 여러 기관이
공통적으로 활용하기 위하여 재사용이 가능하도록 개발한 컴포넌트 소프트웨어를 의미한다.
공통 컴포넌트는 기술 위주의 컴포넌트가 아닌 기능 위주의 컴포넌트로 개발되었다.
스프링 프레임워크에서 제공하는 공통 컴포넌트의 아키텍처를 알아보자.
레이어는 프레젠테이션 레이어( Presentation Layer ), 비즈니스 레이어( Business Layer ), 인티그레이션 레이어( Integration Layer ), 데이터 엑세스 레이어( Data Access Layer )러 구성된다.
· 프레젠테이션 레이어는 DispatcherServlet과 Controller, JSP 등으로 구성된다.
· 비즈니스 레이어는 Service 인터페이스와 ServiceImpl 클래스 등으로 구성된다.
· 데이터 액세스 레이어는 DAO 클래스로 구성되어 있으며,
각 레이어 간에 전송되는 VO 클래스는 레이어의 중앙에 위치한다.
개발 프레임워크 기반 공통 서비스는 개발 프레임워크의 개발 환경을 고려해서 모델( Model ), 뷰( View ), 컨트롤러( Controller )를 분리해서 개발되었다.
또한 데이터 처리 계층 및 SQL의 분리를 통해서 데이터 베이스 변동에 유연하게 대응할 수 있게 설계되었다.
공통 컴포넌트 구성
이제 공통 컴포넌트에서 제공하는 클래스들의 클래스 다이어그램과 시퀀스 다이어그램을 살펴보자.
UML( Unified Modeling Language )로 작성된 클래스 다이어그램에서는 클래스들의 포함 관계, 상속 관계, 의존 관계 등을 확인 할 수 있다.
UML 클래스 다이어그램에서 연관관계( association )는 한 클래스가 다른 클래스를 멤버 변수로 포함하는 포함 관계를 의미하고, 의존 관계( dependency )는 함수 호출 관계를 의미한다. implements는 클래스가 인터페이스를 구현하는 관계를 나타낸다.
다은은 UML 시퀀스 다이어그램을 나타낸다. 맨 위에 있는 사각형 박스는 객체를 의미한다.
화살표는 메시지 혹은 함수 호출을 의미한다.
User는 맨 처음 DiapatcherServlet 클래스 요청을 보낸다.
이는 FrontController로 동작함을 보여준다.
시퀀스 다이어그램을 통해서 시간의 흐름에 따른 객체의 상호작용을 확인할 수 있다.
즉 어떤 객체가 어떤 요청에 대해 어떤 함수를 어떤 순서로 호출하는지를 알 수 있다.
공통 컴포넌트를 적용함으로써 표준을 준수하고 유연성을 확보하며 재사용성이 극대화된다는 장점이 있다.
#01. (Sample) MySQL 실습용 Table 및 Data 만들기
CREATE TABLE 'example_board' (
'example_number' INT(11) NOT NULL AUTO_INCREMENT
, 'example_id' VARCHAR(20) NOT NULL
, 'example_name' VARCHAR(30) NOT NULL
, 'example_title' VARCHAR(50) NOT NULL
, 'example_info' TEXT DEFAULT NULL
, 'example_date' TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP()
, PRIMARY KEY ('example_number')
);
INSERT INTO example_board
(example_number, example_id, example_name, example_title, example_info, example_date)
VALUES(1, 'captain', '캡틴 아메리카', 'First Avenger', '캡틴 아메리카의 ''캡틴''은 초창기 코믹스에서는 말 그대로 미국의 대장이라는 뉘앙스로 쓰였으나,<br/>시간이 흘러 캡틴이라는 말에는 어벤져스의 넘버 원이라는 의미도 포함되었다.', '2011-07-28 00:00:00.000');
INSERT INTO example_board
(example_number, example_id, example_name, example_title, example_info, example_date)
VALUES(2, 'ironman', '아이언 맨', 'I Am Iron Man', '억만장자 천재 발명가인 토니 스타크가 심장에 치명적인 상처를 입은 자신의 목숨을 지키며<br/>동시에 세계를 지킬 강화 슈트를 제작하고 과학의 결정체로 만들어진 슈트를 입고<br/>아이언맨이 되어 범죄와 싸워나간다.', '2008-04-30 00:00:00.000');
INSERT INTO example_board
(example_number, example_id, example_name, example_title, example_info, example_date)
VALUES(3, 'thor', '토르', 'God of Thunder', '지구를 비롯한 아홉 왕국의 평화와 생명을 수호하는 천둥의 신.<br/>올 파더 오딘과 프리가의 맏아들이다. ', '2011-04-28 00:00:00.000');
#2. Maven Artifact 추가하기
1) Srpign JDBC, Spring Transaction 라이브러리 추가
Maven Dependecy에 spring-jdbc 라이브러리와 spring-tx 라이브러리를 추가한다.
pom.xml
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
~~ 이 하 생 략 ~~
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<org.springframework-version>5.2.3.RELEASE</org.springframework-version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework-version}</version>
</dependency>
</dependencies>
~~ 이 하 생 략 ~~
</project>
프로젝트 Library에 추가한 spring-jdbc, spring-tx 아티팩트를 추가한다.
2) MySQL 라이브러리 추가
Maven Dependecy에 mysql-connector-java 라이브러리와 protobuf-java 라이브러리를 추가한다.
pom.xml
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
~~ 이 하 생 략 ~~
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.31</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.19.4</version>
</dependency>
</dependencies>
~~ 이 하 생 략 ~~
</project>
프로젝트 Library에 추가한 mysql-connector-java , protobuf-java 아티팩트를 추가한다.
3) MyBatis 라이브러리 추가
Maven Dependecy에 mybatis와 mybatis-spring 라이브러리를 추가한다.
pom.xml
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
~~ 이 하 생 략 ~~
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
</dependencies>
~~ 이 하 생 략 ~~
</project>
프로젝트 Library에 추가한 mybatis, mybatis-spring 아티팩트를 추가한다.
4) Jackson 라이브러리 추가
Maven Dependecy에 jackson-core, jackson-annotations, jackson-databind 라이브러리를 추가한다..
pom.xml
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
~~ 이 하 생 략 ~~
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.12.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.12.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.3</version>
</dependency>
</dependencies>
~~ 이 하 생 략 ~~
</project>
프로젝트 Library에 추가한 jackson-core, jackson-annotations, jackson-databind 아티팩트를 추가한다.
pom.xml
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.spring.example</groupId>
<artifactId>spring_example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring_example</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<org.springframework-version>5.2.3.RELEASE</org.springframework-version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.31</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.12.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.12.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.3</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.19.4</version>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
#3. DataBase Connection 설정하기
1) DataBase 접속정보를 가지는 properties 파일 생성하기
프로젝트의 resource 디렉토리에서 마우스 우클릭하여 config 디렉토리를 먼저 생성한다.
생성한 config 디렉토리에 database.properties 파일을 생성한다.
database.properties 파일을 생성하였으면 아래와 같이 접속정보를 추가하였준다.
database.properties
jdbc.drvier = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://IP주소:PORT번호/DataBase명칭
jdbc.username = mysql_사용자_계정
jdbc.password = mysql_사용자_비밀번호
2) DataBase 연결을 담당하는 context-datasource.xml 생성
프로젝트 resource 디렉토리 아래에있는 spring 디렉토리를 선택하고 context-datasource.xml 파일을 생성한다.
context-datasource.xml 파일이 생성되었으면 아래와같이 DataBase 접속 설정을 잡아준다.
context-datasource.xml
<?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/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
<!-- MySQL DataSource -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
</beans>
3) DB와 MyBatis 연동하는 context-mapper.xml 생성
프로젝트 resource 디렉토리 아래에있는 spring 디렉토리를 선택하고 context-mapper.xml 파일을 생성한다.
context-mapper.xml 파일이 생성되었으면 연동 설정을 잡아준다.
DB연동에 필요한 SqlSessionFactoryBean 클래스에 대해 id가 sqlSession인 bean을 등록한다.
context-mapper.xml
<?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">
<!-- Spring과 MyBatis 연동 설정 -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:/sqlmap/sql-mapper-config.xml"/>
<property name="mapperLocations" value="classpath:sqlmap/mappings/*-mapping.xml"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="org.spring.example.service.impl"/>
</bean>
</beans>
dataSource | context-datasource.xml 파일에 있는 id가 dataSource인 bean을 참조하여 MyBatis와 DB 연동 |
configLoaction | MyBatis 설정이 담겨있는 xml 파일이 위치한 경로를 잡아준다. |
mapperLocations | DB에 보낼 쿼리가 담겨있는 MyBatis의 xml 파일들이 위치한 경로를 잡아준다. |
4) SQL Session Factory Bean( SqlSessionFactoryBean.java ) 생성
프로젝트에 util이라는 Package를 추가한다.
util 패키지의 추가가 완료되면 SqlSessionFactoryBean.java 파일을 생성한다.
위와 같이 SqlSessionFactoryBean.java 파일이 생성되었다면 아래 코드를 입력하여 준다.
SqlSessionFactoryBean.java
package org.spring.example.util;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.Reader;
public class SqlSessionFactoryBean {
private static SqlSessionFactory sessionFactory = null;
static {
try {
if(sessionFactory == null) {
Reader reader = Resources.getResourceAsReader("sql-mapper-config");
sessionFactory = new SqlSessionFactoryBuilder().build(reader);
}
} catch(Exception e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSessionInstance() {
return sessionFactory.openSession();
}
}
5) sql-mapper-config.xml 생성
프로젝트의 resource 디렉토리에서 마우스 우클릭하여 sqlmap 디렉토리를 생성한다.
다음으로 sqlmap 디렉토리에 sql-mapper-config.xml 파일을 생성한다.
위와 같이 sql-mapper-config.xml 파일이 생성되었다면 아래 코드를 입력하여 준다.
sql-mapper-config.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="org.spring.example.service.ExampleVO" alias="example"/>
</typeAliases>
</configuration>
6) example-mapping.xml 생성
resource 디렉토리에서 생성한 sqlmap 디렉토리에 다시 마우스 우클릭하여 mappings 디렉토리를 생성한다.
다음으로 mappings 디렉토리에 example-mapping 파일을 생성한다.
위와 같이 example-mapping.xml 파일이 생성되었다면 아래 코드를 입력하여 준다.
example-mapping.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="org.spring.example.service.impl.ExampleMapper">
<resultMap id="exampleResult" type="example">
<id property="exampleNumber" column="example_number"/>
<result property="exampleId" column="example_id"/>
<result property="exampleName" column="example_name"/>
<result property="exampleTitle" column="example_title"/>
<result property="exampleInfo" column="example_info"/>
<result property="exampleDate" column="example_date" jdbcType="DATE" javaType="java.sql.Date"/>
</resultMap>
<select id="selectExample" resultMap="exampleResult">
SELECT example_number, example_id, example_name, example_title, example_info, example_date FROM example_board WHERE 1 = 1
<if test="exampleNumber!=null and !exampleNumber.equals('')">
AND example_number = #{exampleNumber}
</if>
</select>
<select id="selectCountExample" resultType="int">
SELECT COUNT(example_number) AS countNumber FROM example_board WHERE 1 = 1
<if test="exampleId!=null and !exampleId.equals('')">
AND example_id = #{exampleId}
</if>
</select>
<select id="selectListExample" parameterType="int" resultMap="exampleResult">
SELECT example_number, example_id, example_name, example_title, example_info, example_date
FROM example_board WHERE 1 = 1
ORDER BY example_number DESC
LIMIT ${startRow}, ${limitRow}
</select>
<insert id="insertExample" useGeneratedKeys="true" keyProperty="exampleNumber" parameterType="example">
INSERT into example_board(example_id, example_name, example_title, example_info)
VALUE(#{exampleId}, #{exampleName}, #{exampleTitle}, #{exampleInfo})
</insert>
<update id="updateExample">
UPDATE example_board SET
example_name = #{exampleName}
, example_title = #{exampleTitle}
, example_info = #{exampleInfo}
, example_date = #{exampleDate}
WHERE 1 = 1
AND example_number = #{exampleNumber}
AND example_id = #{exampleId}
</update>
<delete id="deleteExample">
DELETE FROM example_board WHERE 1 = 1
AND example_number = #{exampleNumber};
</delete>
</mapper>
#4. Data Access Layer 만들기
1) ExampleMapper Interface 생성
프로젝트 service 패키지에 impl 이라는 Package를 하나 추가한다.
생성한 impl 패키지에 ExampleMapper.java 인스턴스 파일을 생성한다.
ExampleMapper.java 인스턴스가 생성이 완료되었으면 아래 코드를 추가한다.
ExampleMapper.java
package org.spring.example.service.impl;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.spring.example.service.ExampleVO;
import java.util.List;
@Mapper
public interface ExampleMapper {
ExampleVO selectExample(ExampleVO vo) throws Exception;
int selectCountExample(ExampleVO vo) throws Exception;
List<ExampleVO> selectListExample(ExampleVO vo, @Param("startRow") int startRow, @Param("limitRow") int limitRow) throws Exception;
int insertExample(ExampleVO vo) throws Exception;
int updateExample(ExampleVO vo) throws Exception;
int deleteExample(ExampleVO vo) throws Exception;
}
2) ExampleRowMapper Class 생성
impl 패키지에 ExampleRowMapper.java 클래스 파일을 생성한다.
ExampleRowMapper.java 클래스가 생성이 완료되었으면 아래 코드를 추가한다.
ExampleRowMapper.java
package org.spring.example.service.impl;
import org.spring.example.service.ExampleVO;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
public class ExampleRowMapper implements RowMapper<ExampleVO> {
public ExampleVO mapRow(ResultSet rs, int rowNum) throws SQLException {
ExampleVO example = new ExampleVO();
example.setExampleNumber(rs.getInt("example_number"));
example.setExampleId(rs.getString("example_id"));
example.setExampleName(rs.getString("example_name"));
example.setExampleTitle(rs.getString("example_title"));
example.setExampleInfo(rs.getString("example_info"));
example.setExampleDate(rs.getDate("example_date"));
return example;
}
}
3) ExampleDao Interface 생성
프로젝트 service 패키지에 ExampleDao.java Interface 파일을 생성한다.
ExampleDao.java 인터페이스가 생성이 완료되었으면 아래 코드를 추가한다.
ExampleDao.java
package org.spring.example.service;
import java.util.List;
public interface ExampleDAO {
ExampleVO selectExample(ExampleVO vo) throws Exception;
int selectCountExample(ExampleVO vo) throws Exception;
List<ExampleVO> selectListExample(ExampleVO vo, int startRow, int limitRow) throws Exception;
int insertExample(ExampleVO vo) throws Exception;
int updateExample(ExampleVO vo) throws Exception;
int deleteExample(ExampleVO vo) throws Exception;
}
4) ExampleDAOMyBatis Class 생성
impl 패키지에 ExampleDAOMyBatis.java 클래스 파일을 생성한다.
ExampleDAOMyBatis.java 클래스가 생성이 완료되었으면 아래 코드를 추가한다.
ExampleDAOMyBatis.java
package org.spring.example.service.impl;
import org.spring.example.service.ExampleDAO;
import org.spring.example.service.ExampleVO;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
import java.util.List;
@Repository("exampleDaoMyBatis")
public class ExampleDAOMyBatis implements ExampleDAO {
@Resource(name="exampleMapper")
private ExampleMapper mybatis;
public ExampleDAOMyBatis() {
System.out.println("===> ExampleDAOMyBatis 생성");
}
public ExampleVO selectExample(ExampleVO vo) throws Exception {
System.out.println("===> MyBatis로 selectExample() 기능 처리");
return (ExampleVO) mybatis.selectExample(vo);
}
public int selectCountExample(ExampleVO vo) throws Exception {
System.out.println("===> MyBatis로 selectCountExample() 기능 처리");
return mybatis.selectCountExample(vo);
}
public List<ExampleVO> selectListExample(ExampleVO vo, int startRow, int limitRow) throws Exception {
System.out.println("===> MyBatis로 selectListExample() 기능 처리");
return mybatis.selectListExample(vo, startRow, limitRow);
}
public int insertExample(ExampleVO vo) throws Exception {
System.out.println("===> MyBatis로 insertExample() 기능 처리");
return mybatis.insertExample(vo);
}
public int updateExample(ExampleVO vo) throws Exception {
System.out.println("===> MyBatis로 updateExample() 기능 처리");
return mybatis.updateExample(vo);
}
public int deleteExample(ExampleVO vo) throws Exception {
System.out.println("===> MyBatis로 deleteExample() 기능 처리");
return mybatis.deleteExample(vo);
}
}
#5. Buisiness Layer 만들기
1) ExampleService Interface 생성
프로젝트 service 패키지에 ExampleService.java Interface 파일을 생성한다.
ExampleService.java 인터페이스 파일의 생성이 완료되었으면 아래 코드를 추가한다.
ExampleService.java
package org.spring.example.service;
import java.util.List;
public interface ExampleService {
/* @brief 사용자 정보 등록*/
ExampleVO selectExample(ExampleVO vo) throws Exception;
int selectCountExample(ExampleVO vo) throws Exception;
List<ExampleVO> selectListExample(ExampleVO vo, int startRow, int limitRow) throws Exception;
/* @brief 사용자 정보 등록*/
int insertExample(ExampleVO vo) throws Exception;
/* @brief 사용자 정보 수정 */
int updateExample(ExampleVO vo) throws Exception;
/* @brief 사용자 삭제 */
int deleteExample(ExampleVO vo) throws Exception;
}
2) ExampleServiceImpl Class 생성
프로젝트 service 패키지에 ExampleServiceImpl.java Class 파일을 생성한다.
ExampleServiceImpl.java
package org.spring.example.service.impl;
import org.spring.example.service.ExampleDAO;
import org.spring.example.service.ExampleService;
import org.spring.example.service.ExampleVO;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service("exampleService")
public class ExampleServiceImpl implements ExampleService {
// @Page 409
@Resource(name="exampleDaoMyBatis")
private ExampleDAO exampleDAO;
public ExampleVO selectExample(ExampleVO vo) throws Exception {
return exampleDAO.selectExample(vo);
}
public int selectCountExample(ExampleVO vo) throws Exception {
return exampleDAO.selectCountExample(vo);
}
public List<ExampleVO> selectListExample(ExampleVO vo, int startRow, int limitRow) throws Exception {
return exampleDAO.selectListExample(vo, startRow, limitRow);
}
public int insertExample(ExampleVO vo) throws Exception {
return exampleDAO.insertExample(vo);
}
public int updateExample(ExampleVO vo) throws Exception {
return exampleDAO.updateExample(vo);
}
public int deleteExample(ExampleVO vo) throws Exception {
return exampleDAO.deleteExample(vo);
}
}
#6. Pressentation Layer 만들기
1) 게시판 리스트 - exampleList.jsp
exampleList.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<html>
<head>
<title>게시판 리스트</title>
</head>
<style type="text/css">
table, thead, tbody, tfoot { border:1px solid #000000;border-collapse:collapse; }
tfoot { text-align:right; }
th, td { border:1px solid #000000;padding:10px; }
tbody > tr > td { cursor:pointer;cursor:hand; }
tbody > tr > td:first-child { text-align:center; }
button { cursor:pointer;cursor:hand; }
ul.pagination { list-style:none;margin:0;padding:0; }
li.pagination-btn { margin-right:5px;margin-left:5px;border:0;float:left;}
li.active { font-weight:bold; }
a.pagination-link { color:#000000;text-decoration:none; }
</style>
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function() {
document.getElementById("btnWrite").addEventListener("click", function() {
window.location.href = "./exampleWrite.do";
});
document.getElementsByClassName("")
});
function exampleMovePage(page) {
window.location.href = "exampleList.do?page=" + page;
}
</script>
<body>
<h1>${headTitle}</h1>
<table>
<thead>
<tr>
<th>번호</th>
<th>제목</th>
<th>이름</th>
<th>날짜</th>
</tr>
</thead>
<tbody>
<c:forEach var="example" items="${exampleList}">
<tr onClick="window.location.href='/SpringExample_war_exploded/exampleInfo.do?number=${example.exampleNumber}'">
<td>${example.exampleNumber}</td>
<td>${example.exampleTitle}</td>
<td>${example.exampleName}(${example.exampleId})</td>
<td><fmt:formatDate value="${example.exampleDate}" pattern="yyyy-MM-dd"/></td>
</tr>
</c:forEach>
</tbody>
<tfoot>
<tr>
<td colspan="4">
<button id="btnWrite" type="button">새 글쓰기</button>
</td>
</tr>
</tfoot>
</table>
<br/>
${examplePagination}
</body>
</html>
2) 게시글 상세보기 - exampleInfo.jsp
exampleInfo.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<html>
<head>
<title>${exampleTitle}</title>
</head>
<style type="text/css">
table, thead, tbody { border: 1px solid #000000;border-collapse:collapse; }
th, td { border:1px solid #000000;padding:10px; }
tfoot { text-align:right; }
</style>
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function() {
document.getElementById("btnList").addEventListener("click", function() {
history.back();
});
document.getElementById("btnRemove").addEventListener("click", function() {
if(confirm("해당 글을 삭제하시겠습니까?") == true) {
window.location.href = "./exampleRemove.do?number=" + getParameter("number");
}
});
document.getElementById("btnRevise").addEventListener("click", function() {
window.location.href = "./exampleRevise.do?number=" + getParameter("number");
});
});
var getParameter = function(param) {
let returnValue;
let url = location.href;
let parameters = (url.slice(url.indexOf("?") + 1, url.length)).split("&");
for(let i = 0; i < parameters.length; i++) {
let varName = parameters[i].split("=")[0];
if(varName.toUpperCase() == param.toUpperCase()) {
returnValue = parameters[i].split("=")[1];
return decodeURIComponent(returnValue);
}
}
}
</script>
<body>
<h3>${exampleName} : ${exampleTitle}</h3>
<table>
<tbody>
</tbody>
<tr>
<th>제목</th>
<td>${exampleTitle}</td>
</tr>
<tr>
<th>이름</th>
<td>${exampleName}(${exampleId})</td>
</tr>
<tr>
<th>개봉일</th>
<td>${exampleDate}</td>
</tr>
<tr>
<th>내용</th>
<td>${exampleInfo}</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2">
<button id="btnList" type="button">리스트</button>
<button id="btnRemove" type="button">글삭제</button>
<button id="btnRevise" type="button">글수정</button>
</td>
</tr>
</tfoot>
</table>
</body>
</html>
3) 게시글 작성 - exampWrite.jsp
exampWrite.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<html>
<head>
<title>${exampleTitle}</title>
</head>
<style type="text/css">
table, thead, tbody, tfoot { border:1px solid #000000;border-collapse:collapse; }
tfoot { text-align:right; }
th, td { border:1px solid #000000;padding:10px; }
</style>
<script src="http://code.jquery.com/jquery-1.12.4.js"></script>
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function() {
document.getElementById("btnVerification").addEventListener("click", function() {
duplicateCheckId();
});
document.getElementById("btnList").addEventListener("click", function() {
history.back();
});
document.getElementById("btnRegistry").addEventListener("click", function() {
submitRegistryExample();
});
});
function duplicateCheckId() {
jQuery.ajax({
url : "./verificationDuplicateId.do"
, type : "POST"
, data : {
"exampleId" : document.getElementsByName("exampleId")[0].value
}
, success:function(json) {
if(json.result == "success") {
alert(json.message);
document.getElementsByName("exampleName")[0].focus();
document.getElementById("verificationId").value = "true";
} else {
alert(json.message);
document.getElementsByName("exampleId")[0].value = "";
document.getElementsByName("exampleId")[0].focus();
}
}
});
}
function submitRegistryExample() {
if(document.getElementById("verificationId").value == "false") {
alert("ID 중복체크를 진행하지 않았습니다.\nID를 중복체크해 주세요.");
document.getElementById("btnVerification").focus();
return false;
}
if(document.getElementsByName("exampleName")[0].value.replace(/\s/gi, "") == "") {
alert("이름을 입력하지 않았습니다.\n이름을 입력해 주세요.");
document.getElementsByName("exampleName")[0].focus();
return false;
}
if(document.getElementsByName("exampleTitle")[0].value.replace(/\s/gi, "") == "") {
alert("제목을 입력하지 않았습니다.\n제목을 입력해 주세요.");
document.getElementsByName("exampleTitle")[0].focus();
return false;
}
if(document.getElementsByName("exampleDate")[0].value.replace(/\s/gi, "") == "") {
alert("날짜를 입력하지 않았습니다.\n날짜를 입력해 주세요.");
document.getElementsByName("exampleDate")[0].focus();
return false;
}
document.getElementById("formWriteExample").method = "POST";
document.getElementById("formWriteExample").action = "./exampleRegistryWrite.do";
document.getElementById("formWriteExample").submit();
}
</script>
<body>
<h3>신규 글 등록</h3>
<input type="hidden" id="verificationId" value="false"/>
<form id="formWriteExample">
<table>
<tbody>
<tr>
<th>ID</th>
<td>
<input type="text" name="exampleId" value=""/>
<button id="btnVerification" type="button">중복확인</button>
</td>
</tr>
<tr>
<th>이름</th>
<td>
<input type="text" name="exampleName" value=""/>
</td>
</tr>
<tr>
<th>제목</th>
<td>
<input type="text" name="exampleTitle" value=""/>
</td>
</tr>
<tr>
<th>날짜</th>
<td>
<input type="date" name="exampleDate" value=""/>
</td>
</tr>
<tr>
<th>내용</th>
<td><textarea name="exampleInfo"></textarea></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2">
<button id="btnList" type="button">리스트</button>
<button id="btnRegistry" type="button">글등록</button>
</td>
</tr>
</tfoot>
</table>
</form>
</body>
</html>
4) 게시글 수정 - exampleRevise.jsp
exampleRevise.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<html>
<head>
<title>${exampleTitle}</title>
</head>
<style type="text/css">
table, thead, tbody, tfoot { border:1px solid #000000;border-collapse:collapse; }
tfoot { text-align:right; }
th, td { border:1px solid #000000;padding:10px; }
.fakeDisabled { cursor:default;background-color:#F8F8F8;color:#545454;border-color:#D6D6D6; }
</style>
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function() {
document.getElementById("btnModify").addEventListener("click", function() {
submitModifyExample();
});
});
function submitModifyExample() {
if(document.getElementsByName("exampleName")[0].value.replace(/\s/gi, "") == "") {
alert("이름을 입력하지 않았습니다.\n이름을 입력해 주세요.");
document.getElementsByName("exampleName")[0].focus();
return false;
}
if(document.getElementsByName("exampleTitle")[0].value.replace(/\s/gi, "") == "") {
alert("제목을 입력하지 않았습니다.\n제목을 입력해 주세요.");
document.getElementsByName("exampleTitle")[0].focus();
return false;
}
if(document.getElementsByName("exampleDate")[0].value.replace(/\s/gi, "") == "") {
alert("날짜를 입력하지 않았습니다.\n날짜를 입력해 주세요.");
document.getElementsByName("exampleDate")[0].focus();
return false;
}
document.getElementById("formWriteExample").method = "POST";
document.getElementById("formWriteExample").action = "./exampleModifyWrite.do";
document.getElementById("formWriteExample").submit();
}
</script>
<body>
<h3>신규 글 등록</h3>
<input type="hidden" id="verificationId" value="false"/>
<form id="formWriteExample">
<input type="hidden" name="exampleNumber" value="${exampleNumber}"/>
<table>
<tbody>
<tr>
<th>ID</th>
<td>
<input type="text" class="fakeDisabled" name="exampleId" value="${exampleId}" readonly/>
</td>
</tr>
<tr>
<th>이름</th>
<td>
<input type="text" name="exampleName" value="${exampleName}"/>
</td>
</tr>
<tr>
<th>제목</th>
<td>
<input type="text" name="exampleTitle" value="${exampleTitle}"/>
</td>
</tr>
<tr>
<th>날짜</th>
<td>
<input type="date" name="exampleDate" value="${exampleDate}"/>
</td>
</tr>
<tr>
<th>내용</th>
<td><textarea name="exampleInfo">"${exampleInfo}"</textarea></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2">
<button id="btnModify" type="button">글수정</button>
</td>
</tr>
</tfoot>
</table>
</form>
</body>
</html>
5) 최초 페이지 - index.jsp
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<jsp:forward page="/example.do"/>
#?. VO 클래스에 toString 메서드 추가
이전에 생성한 ExampleVO 클래스에 toString 메서드를 추가하여 준다.
ExampleVO 클래스 가장 아래에 마우스를 우클릭하여 Generate 메뉴에서 toString( ) 을 선택한다.
그럼 먼저 생성한 변수들이 리스트로 나열되는데 전부 선택하고 OK 버튼을 클릭한다.
그럼 위와 같이 toString( ) 메서드가 생성된다.
ExampleVO.java
package org.spring.example.service;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
public class ExampleVO {
private int exampleNumber;
private String exampleId;
private String exampleName;
private String exampleTitle;
private String exampleInfo;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date exampleDate;
public int getExampleNumber() { return exampleNumber; }
public void setExampleNumber(int exampleNumber) {
this.exampleNumber = exampleNumber;
}
public String getExampleId() { return exampleId; }
public void setExampleId(String exampleId) {
this.exampleId = exampleId;
}
public String getExampleName() {
return exampleName;
}
public void setExampleName(String exampleName) {
this.exampleName = exampleName;
}
public String getExampleTitle() {
return exampleTitle;
}
public void setExampleTitle(String exampleTitle) {
this.exampleTitle = exampleTitle;
}
public String getExampleInfo() {
return exampleInfo;
}
public void setExampleInfo(String exampleInfo) {
this.exampleInfo = exampleInfo;
}
public Date getExampleDate() {
return exampleDate;
}
public void setExampleDate(Date exampleDate) {
this.exampleDate = exampleDate;
}
@Override
public String toString() {
return "ExampleVO { "
+ "exampleNumber=" + exampleNumber
+ ", exampleId=\'" + exampleId + "\'"
+ ", exampleName=\'" + exampleName + "\'"
+ ", exampleTitle=\'" + exampleTitle + "\'"
+ ", exampleInfo=\'" + exampleInfo + "\'"
+ ", exampleDate=" + exampleDate
+ " }";
}
}
#?. Controller 수정
ExampleController.java
package org.spring.example.controller;
import org.spring.example.service.ExampleService;
import org.spring.example.service.ExampleVO;
import org.spring.example.util.OutputPagination;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
@Controller
public class ExampleController {
@Resource(name="exampleService")
private ExampleService exampleService;
Map<String, String> resultMap = new HashMap<String, String>();
@RequestMapping(value = "/example.do", method = RequestMethod.GET)
public String ExampleMain() {
return "example";
}
@RequestMapping(value = "/exampleInfo.do", method = RequestMethod.GET)
public String exampleInfo(ExampleVO vo, HttpServletRequest request, Model model) throws Exception {
if(request.getParameter("number").isEmpty() == false) {
vo.setExampleNumber(Integer.parseInt(request.getParameter("number")));
ExampleVO exampleVO = exampleService.selectExample(vo);
model.addAttribute("exampleId", exampleVO.getExampleId());
model.addAttribute("exampleName", exampleVO.getExampleName());
model.addAttribute("exampleTitle", exampleVO.getExampleTitle());
model.addAttribute("exampleInfo", exampleVO.getExampleInfo());
model.addAttribute("exampleDate", exampleVO.getExampleDate());
}
return "exampleInfo";
}
@RequestMapping(value = "/exampleList.do")
public String exampleList(ExampleVO vo, HttpServletRequest request, Model model) throws Exception {
int totalRow = exampleService.selectCountExample(vo); // 해당 테이블의 전체 갯수
int choicePage = 0; // 선택 페이지
int startRow = 0; // MySQL LIMIT 시작점
int limitRow = 10; // MySQL LIMIT 종료점( 출력될 가로(row)의 개수를 지정 )
if(request.getParameter("page") != null && request.getParameter("page").length() > 0) {
choicePage = Integer.parseInt(request.getParameter("page"));
startRow = (choicePage - 1) * limitRow;
} else {
choicePage = 1;
startRow = 0;
}
model.addAttribute("exampleList", exampleService.selectListExample(vo, startRow, limitRow));
model.addAttribute("examplePagination", OutputPagination.outputServletPagination(choicePage, limitRow, totalRow, "exampleMovePage"));
return "exampleList";
}
@RequestMapping(value = "/exampleWrite.do")
public String exampleWrite() throws Exception {
return "exampleWrite";
}
@RequestMapping(value = "/exampleRevise.do", method = RequestMethod.GET)
public String exampleRevision(ExampleVO vo, HttpServletRequest request, Model model) throws Exception {
vo.setExampleNumber(Integer.parseInt(request.getParameter("number")));
ExampleVO exampleVO = exampleService.selectExample(vo);
// System.out.println( "exampleVO.toString() : " + exampleVO.toString());
model.addAttribute("exampleNumber", request.getParameter("number"));
model.addAttribute("exampleId", exampleVO.getExampleId());
model.addAttribute("exampleName", exampleVO.getExampleName());
model.addAttribute("exampleTitle", exampleVO.getExampleTitle());
model.addAttribute("exampleInfo", exampleVO.getExampleInfo());
model.addAttribute("exampleDate", exampleVO.getExampleDate());
return "exampleRevise";
}
@ResponseBody
@RequestMapping(value = "/verificationDuplicateId.do", method = RequestMethod.POST)
public Map verificationDuplicateId(ExampleVO vo, HttpServletRequest request ) throws Exception {
if(request.getParameter( "exampleId" ).isEmpty() == false) {
vo.setExampleId(request.getParameter("exampleId"));
} else {
vo.setExampleId(null);
}
int resultCount = exampleService.selectCountExample(vo);
// System.out.println( "exampleVO.toString() : " + exampleVO.toString());
if(resultCount > 0) {
resultMap.put("result", "fail");
resultMap.put("message", request.getParameter( "exampleId" ) + "는\n이미 사용중인 아이디 입니다.");
} else {
resultMap.put("result", "success");
resultMap.put("message", "사용가능한 아이디 입니다.");
}
return resultMap;
}
@ResponseBody
@RequestMapping(value = "/exampleRegistryWrite.do", method = RequestMethod.POST)
public void exampleRegistryWrite(ExampleVO vo, HttpServletRequest request, HttpServletResponse response) throws Exception {
if(request.getParameter("exampleId").isEmpty() == false) {
vo.setExampleId(request.getParameter("exampleId"));
}
if(request.getParameter("exampleName").isEmpty() == false) {
vo.setExampleName(request.getParameter("exampleName"));
}
if(request.getParameter("exampleTitle").isEmpty() == false) {
vo.setExampleTitle(request.getParameter("exampleTitle"));
}
if(request.getParameter("exampleInfo").isEmpty() == false) {
vo.setExampleInfo(request.getParameter("exampleInfo"));
}
if(request.getParameter("exampleDate").isEmpty() == false) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
vo.setExampleDate(formatter.parse(request.getParameter("exampleDate")));
}
int resultNumber = exampleService.insertExample(vo);
// System.out.println( "exampleVO.toString() : " + vo.toString());
if(resultNumber > 0) {
response.sendRedirect("./exampleList.do");
} else {
// 참고 : https://redcoder.tistory.com/195
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
out.println("<script type='text/javascript'>alert('해당 글을 등록하는데 실패하였습니다.');</script>");
out.flush();
}
}
@ResponseBody
@RequestMapping(value = "/exampleModifyWrite.do", method = RequestMethod.POST)
public void exampleModifyWrite(ExampleVO vo, HttpServletRequest request, HttpServletResponse response) throws Exception {
if(request.getParameter("exampleNumber").isEmpty() == false) {
vo.setExampleNumber(Integer.parseInt(request.getParameter("exampleNumber")));
}
if(request.getParameter("exampleId").isEmpty() == false) {
vo.setExampleId(request.getParameter("exampleId"));
}
if(request.getParameter("exampleName").isEmpty() == false) {
vo.setExampleName(request.getParameter("exampleName"));
}
if(request.getParameter("exampleTitle").isEmpty() == false) {
vo.setExampleTitle(request.getParameter("exampleTitle"));
}
if(request.getParameter("exampleInfo").isEmpty() == false) {
vo.setExampleInfo(request.getParameter("exampleInfo"));
}
if(request.getParameter("exampleDate").isEmpty() == false) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
vo.setExampleDate(formatter.parse(request.getParameter("exampleDate")));
}
int resultNumber = exampleService.updateExample(vo);
// System.out.println( "exampleVO.toString() : " + vo.toString());
if(resultNumber > 0) {
response.sendRedirect("./exampleInfo.do?number=" + vo.getExampleNumber());
} else {
// 참고 : https://redcoder.tistory.com/195
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
out.println("<script type='text/javascript'>alert('해당 글을 수정하는데 실패하였습니다.');</script>");
out.flush();
}
}
@RequestMapping(value = "/exampleRemove.do", method = RequestMethod.GET)
public void exampleRemove(ExampleVO vo, HttpServletRequest request, HttpServletResponse response) throws Exception {
if(request.getParameter("number").isEmpty() == false) {
vo.setExampleNumber(Integer.parseInt(request.getParameter("number")));
}
int resultNumber = exampleService.deleteExample(vo);
if(resultNumber > 0) {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
out.println("<script type='text/javascript'>");
out.println("alert('해당 글이 삭제되었습니다.');");
out.println("window.location.href='./exampleList.do';");
out.println("</script>");
out.flush();
} else {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
out.println("<script type='text/javascript'>alert('해당 글을 삭제하는데 실패하였습니다.');</script>");
out.flush();
}
}
}
#?. 페이지 네비게이션 제작하기
util 패키지에 페이징( Paging ) 기능을 만들기위한 OutputPagination.java 클래스 파일을 생성한다.
파일이 생성되면 OutputPagination.java 클래스 파일에 아래와 같이 코드를 추가한다.
OutputPagination.java
package org.spring.example.util;
public class OutputPagination {
public static String outputServletPagination(int choicePage, int limitRow, int totalRow, String executionFunction) {
int totalPage = (int)((totalRow - 1) / limitRow);
int lastPage = 0;
int prevPage = (int)((choicePage - 1) / 5) * 5;
if((prevPage + 4) > totalPage) {
lastPage = totalPage;
} else {
lastPage = prevPage + 4;
}
String pagination = "<ul class='pagination'>";
if(prevPage == 0) {
pagination += "<li class='pagination-btn'><a class='pagination-link' href='javascript:;'>첫페이지</a></li>";
pagination += "<li class='pagination-btn'><a class='pagination-link' href='javascript:;'><<</a></li>";
} else {
pagination += String.format("<li class='pagination-btn'><a class='pagination-link' href='javascript:;' onClick='%s(%s);'>첫페이지</a></li>", executionFunction, 1);
pagination += String.format("<li class='pagination-btn'><a class='pagination-link' href='javascript:;' onClick='%s(%s);'><<</a></li>", executionFunction, prevPage);
}
// 페이징 INDEX를 출력한다.
for(int pageNum = prevPage; pageNum <= lastPage; pageNum++) {
int disPage = pageNum + 1;
if(disPage == choicePage) {
pagination += String.format("<li class='pagination-btn active'><a class='pagination-link' href='javascript:;'>%s</a></li>", disPage);
} else {
pagination += String.format("<li class='pagination-btn'><a class='pagination-link' href='javascript:;' onClick=\"%s(%s);\">%s</a></li>", executionFunction, disPage, disPage);
}
}
if(lastPage != totalPage) {
int nextPage = prevPage + 6;
pagination += String.format("<li class='pagination-btn'><a class='pagination-link' href='javascript:;' onClick='%s(%s);'>>></a></li>", executionFunction, nextPage);
pagination += String.format("<li class='pagination-btn'><a class='pagination-link' href='javascript:;' onClick='%s(%s);'>끝페이지</a></li>", executionFunction, totalPage + 1);
} else {
pagination += "<li class='pagination-btn'><a class='pagination-link' href='javascript:;'>>></a></li>";
pagination += "<li class='pagination-btn'><a class='pagination-link' href='javascript:;'>끝페이지</a></li>";
}
String returnNav = pagination + "</ul>";
return returnNav;
}
}
#?. 인코딩 설정을 위한 filter, filer-mapping 설정
web.xml
<?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_4_0.xsd"
version="4.0">
~~ 이 하 생 략 ~~
<filter>
<filter-name>characterEncoding</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>characterEncoding</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
~~ 이 하 생 략 ~~
</web-app>
#?. 실행 결과 확인
'Spring Web > Spring Framework' 카테고리의 다른 글
[Spring] IntelliJ를 사용한 Spring Project 생성(Gradle) (1) | 2023.06.13 |
---|---|
[Spring] src/main/resources 경로 폴더 형태로 노출 (2) | 2023.03.30 |
[Spring] Component-Scan을 사용하는 Annotation 기반 설정 (0) | 2022.12.09 |
[Spring] Spring MVC 패턴 적용 (0) | 2022.12.08 |
[Spring] IntelliJ를 사용한 Spring Project 생성 및 설정(Maven) (2) | 2022.11.29 |