이번에는 Spring MVC 패턴을 이용하여 게시판을 만들어보도록 하겠습니다.
우선 로직과 파일의 폴더 구성은 아래와 같습니다.
작업 순서도
1. DB작성
2. 프로젝트 생성
3. pom.xml, web.xml 수정
1. 테이블, 시퀀스 작성 후 테스트 데이터 입력
select * from tab;
create table mvc_board(
bno number primary key,
writer varchar2(20) not null,
title varchar2(100) not null,
content varchar2(1000) not null,
write_date DATE default SYSDATE,
hit int default 0);
create sequence mvc_board_seq;
insert into mvc_board(
bno, writer, title, content)
values (mvc_board_seq.nextval,
'kim', '제목1', '내용1입니다');
commit;
2. 프로젝트 생성
변경할 코드는 아래에서 참조한다.
server.xml 수정
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
--><!-- Note: A "Server" is not itself a "Container", so you may not
define subcomponents such as "Valves" at this level.
Documentation at /docs/config/server.html
--><Server port="8006" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener"/>
<!-- Security listener. Documentation at /docs/config/listeners.html
<Listener className="org.apache.catalina.security.SecurityListener" />
-->
<!--APR library loader. Documentation at /docs/apr.html -->
<Listener SSLEngine="on" className="org.apache.catalina.core.AprLifecycleListener"/>
<!-- Prevent memory leaks due to use of particular java/javax APIs-->
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>
<!-- Global JNDI resources
Documentation at /docs/jndi-resources-howto.html
-->
<GlobalNamingResources>
<!-- Editable user database that can also be used by
UserDatabaseRealm to authenticate users
-->
<Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
</GlobalNamingResources>
<!-- A "Service" is a collection of one or more "Connectors" that share
a single "Container" Note: A "Service" is not itself a "Container",
so you may not define subcomponents such as "Valves" at this level.
Documentation at /docs/config/service.html
-->
<Service name="Catalina">
<!--The connectors can use a shared executor, you can define one or more named thread pools-->
<!--
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="150" minSpareThreads="4"/>
-->
<!-- A "Connector" represents an endpoint by which requests are received
and responses are returned. Documentation at :
Java HTTP Connector: /docs/config/http.html
Java AJP Connector: /docs/config/ajp.html
APR (HTTP/AJP) Connector: /docs/apr.html
Define a non-SSL/TLS HTTP/1.1 Connector on port 8080
-->
<Connector connectionTimeout="20000" port="8081" protocol="HTTP/1.1" redirectPort="8443"/>
<!-- A "Connector" using the shared thread pool-->
<!--
<Connector executor="tomcatThreadPool"
port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
-->
<!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443
This connector uses the NIO implementation. The default
SSLImplementation will depend on the presence of the APR/native
library and the useOpenSSL attribute of the
AprLifecycleListener.
Either JSSE or OpenSSL style configuration may be used regardless of
the SSLImplementation selected. JSSE style configuration is used below.
-->
<!--
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true">
<SSLHostConfig>
<Certificate certificateKeystoreFile="conf/localhost-rsa.jks"
type="RSA" />
</SSLHostConfig>
</Connector>
-->
<!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2
This connector uses the APR/native implementation which always uses
OpenSSL for TLS.
Either JSSE or OpenSSL style configuration may be used. OpenSSL style
configuration is used below.
-->
<!--
<Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"
maxThreads="150" SSLEnabled="true" >
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
<SSLHostConfig>
<Certificate certificateKeyFile="conf/localhost-rsa-key.pem"
certificateFile="conf/localhost-rsa-cert.pem"
certificateChainFile="conf/localhost-rsa-chain.pem"
type="RSA" />
</SSLHostConfig>
</Connector>
-->
<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector port="8010" protocol="AJP/1.3" redirectPort="8443"/>
<!-- An Engine represents the entry point (within Catalina) that processes
every request. The Engine implementation for Tomcat stand alone
analyzes the HTTP headers included with the request, and passes them
on to the appropriate Host (virtual host).
Documentation at /docs/config/engine.html -->
<!-- You should set jvmRoute to support load-balancing via AJP ie :
<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
-->
<Engine defaultHost="localhost" name="Catalina">
<!--For clustering, please take a look at documentation at:
/docs/cluster-howto.html (simple how to)
/docs/config/cluster.html (reference documentation) -->
<!--
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
-->
<!-- Use the LockOutRealm to prevent attempts to guess user passwords
via a brute-force attack -->
<Realm className="org.apache.catalina.realm.LockOutRealm">
<!-- This Realm uses the UserDatabase configured in the global JNDI
resources under the key "UserDatabase". Any edits
that are performed against this UserDatabase are immediately
available for use by the Realm. -->
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
</Realm>
<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
<!-- SingleSignOn valve, share authentication between web applications
Documentation at: /docs/config/valve.html -->
<!--
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-->
<!-- Access log processes all example.
Documentation at: /docs/config/valve.html
Note: The pattern used is equivalent to using pattern="common" -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" pattern="%h %l %u %t "%r" %s %b" prefix="localhost_access_log" suffix=".txt"/>
<!-- <Context docBase="test1" path="/test1" reloadable="true" source="org.eclipse.jst.jee.server:test1"/>
<Context docBase="MVC_Board" path="/MVC_Board" reloadable="true" source="org.eclipse.jst.jee.server:MVC_Board"/>
<Context docBase="exam01" path="/exam01" reloadable="true" source="org.eclipse.jst.jee.server:exam01"/> -->
<Context docBase="SpringMVCBoard01" path="/springboard" reloadable="true" source="org.eclipse.jst.jee.server:SpringMVCBoard01">
<!-- driver, xe 수정
<Resource name="jdbc/myoracle" auth="Container"
type="javax.sql.DataSource" driverClassName="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:@192.168.0.78:1521:xe"
username="mvc" password="1234" maxTotal="20" maxIdle="10"
maxWaitMillis="-1"/> -->
</Context></Host>
</Engine>
</Service>
</Server>
혹은 context.xml 수정
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
--><!-- The contents of this file will be loaded for each web application --><Context>
<!-- Default set of monitored resources. If one of these changes, the -->
<!-- web application will be reloaded. -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<!-- driver, xe 수정 -->
<Resource name="jdbc/myoracleDB" auth="Container"
type="javax.sql.DataSource" driverClassName="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:@192.168.0.78:1521:xe"
username="mvc" password="1234" maxTotal="20" maxIdle="10"
maxWaitMillis="-1"/>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
</Context>
3. 이클립스 - 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 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lje</groupId>
<artifactId>springboard</artifactId>
<name>SpringMVCBoard01</name>
<packaging>war</packaging>
<version>1.0.0-BUILD-SNAPSHOT</version>
<properties>
<java-version>1.8</java-version>
<org.springframework-version>5.1.9.RELEASE</org.springframework-version>
<org.aspectj-version>1.6.10</org.aspectj-version>
<org.slf4j-version>1.6.6</org.slf4j-version>
</properties>
<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>
<!-- 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.12</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.9.RELEASE</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.7.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</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>1.8</source>
<target>1.8</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.xml 수정 (2) Maven Repository 이용
1) spring-test context
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.9.RELEASE</version>
<scope>test</scope>
</dependency>
2) Spring JDBC
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
3) dbcp
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.7.0</version>
</dependency>
4) mysql connector J
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency>
자동으로 Maven Repository로 연결이 되는 mysql과 달리 오라클은 유료 프로그램이기 때문에 직접 연결을 해 주어야 한다. Build Path를 눌러 Java Build Path > Add External JARs 그리고 Deployment Assembly > Java Build Path Entiries 를 눌러 두 가지를 추가해준다.
web.xml 수정 : <webapp></webapp>에 Character Encoding Filter 삽입
<?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>
<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>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
4. 패키지 작성
com.exam.spring_board.command / com.exam.spring_board.controller
com.exam.spring_board.dao / com.exam.spring_board.dto
DAO
BoardDao.java
package com.lje.springboard.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import com.lje.springboard.dto.Board;
import com.mysql.cj.xdevapi.PreparableStatement;
public class BoardDao {
private BoardDao() { }
private static BoardDao dao = new BoardDao();
public static BoardDao getInstance() { return dao; }
public Connection getConnection() { // 커넥트풀
Connection conn = null;
try {
Context initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:/comp/env");
DataSource ds = (DataSource) envContext.lookup("jdbc/myoracleDB");
conn = ds.getConnection();
// etc.
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
public List<Board> selectAll() {
List<Board> list = new ArrayList<Board>();
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
String sql = "select * from mvc_board";
try {
conn = getConnection();
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
while (rs.next()) {
Board board = new Board();
board.setBno(rs.getInt("bno"));
board.setWriter(rs.getString("writer"));
board.setTitle(rs.getString("title"));
board.setWrite_date(rs.getTimestamp("write_date"));
board.setHit(rs.getInt("hit"));
list.add(board);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
closeDB(conn, ps, rs);
}
return list;
}
//조회수 증가
public void updateHit(int bno) {
Connection conn = null;
PreparedStatement ps = null;
String sql = "update mvc_board set hit=hit+1 where bno=?";
try {
conn = getConnection();
ps = conn.prepareStatement(sql);
ps.setInt(1, bno);
int n = ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
closeDB(conn, ps);
}
}
public Board selectOne(int bno) {
Board board = null;
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
String sql = "select * from mvc_board where bno=?";
try {
conn = getConnection();
ps = conn.prepareStatement(sql);
ps.setInt(1, bno);
rs = ps.executeQuery();
while (rs.next()) {
board = new Board();
board.setBno(rs.getInt("bno"));
board.setWriter(rs.getString("writer"));
board.setTitle(rs.getString("title"));
board.setContent(rs.getString("content"));
board.setWrite_date(rs.getTimestamp("write_date"));
board.setHit(rs.getInt("hit"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
closeDB(conn, ps, rs);
}
return board;
}
public void insert(Board board) {
Connection conn = null;
PreparedStatement ps = null;
String sql = "insert into mvc_board(bno, writer, title, content) "
+ "values (mvc_board_seq.nextval, ?,?,?)";
try {
conn = getConnection();
ps = conn.prepareStatement(sql);
ps.setString(1, board.getWriter());
ps.setString(2, board.getTitle());
ps.setString(3, board.getContent());
int n = ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
closeDB(conn, ps);
}
}
public void update(Board board) {
Connection conn = null;
PreparedStatement ps = null;
String sql = "update mvc_board set writer=?, title=?, content=? "
+ "where bno=?";
try {
conn = getConnection();
ps = conn.prepareStatement(sql);
ps.setString(1, board.getWriter());
ps.setString(2, board.getTitle());
ps.setString(3, board.getContent());
ps.setInt(4, board.getBno());
int n = ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
closeDB(conn, ps);
}
}
public void delete(int bno) {
Connection conn = null;
PreparedStatement ps = null;
String sql = "delete from mvc_board where bno=?";
try {
conn = getConnection();
ps = conn.prepareStatement(sql);
ps.setInt(1, bno);
int n = ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
closeDB(conn, ps);
}
}
private void closeDB(Connection conn, PreparedStatement ps, ResultSet rs) {
try {
if (rs != null)
rs.close();
if (ps != null)
ps.close();
if (conn != null)
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private void closeDB(Connection conn, PreparedStatement ps) {
try {
if (ps != null)
ps.close();
if (conn != null)
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
DTO
Board.java
package com.lje.springboard.dto;
import java.sql.Timestamp;
public class Board {
private int bno;
private String writer;
private String title;
private String content;
private Timestamp write_date;
private int hit;
public int getBno() {
return bno;
}
public void setBno(int bno) {
this.bno = bno;
}
public String getWriter() {
return writer;
}
public void setWriter(String writer) {
this.writer = writer;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Timestamp getWrite_date() {
return write_date;
}
public void setWrite_date(Timestamp write_date) {
this.write_date = write_date;
}
public int getHit() {
return hit;
}
public void setHit(int hit) {
this.hit = hit;
}
@Override
public String toString() {
return "Board [bno=" + bno + ", writer=" + writer + ", title=" + title + ", content=" + content
+ ", write_date=" + write_date + ", hit=" + hit + "]";
}
}
SERVICE
BoardService.java
package com.lje.springboard.service;
import java.util.List;
import com.lje.springboard.dto.Board;
public interface BoardService {
public List<Board> listAll();
public void insert (Board board);
public Board read(int bno);
public void modify(Board board);
public void delete(int bno);
}
BoardServiceImpl.java (인터페이스)
인터페이스 생성 시 add로 BoardService를 추가해주면 자동으로 코드가 작성됩니다.
1) 싱글톤 방식
package com.lje.springboard.service;
import java.util.List;
import com.lje.springboard.dao.BoardDao;
import com.lje.springboard.dto.Board;
public class BoardServiceImpl implements BoardService {
@Override
public List<Board> listAll() {
// TODO Auto-generated method stub
return BoardDao.getInstance().selectAll();
}
@Override
public void insert(Board board) {
BoardDao.getInstance().insert(board);
}
@Override
public Board read(int bno) {
// 조회 시 조회수 증가
BoardDao dao = BoardDao.getInstance();
dao.updateHit(bno);
return dao.selectOne(bno);
}
@Override
public void modify(Board board) {
BoardDao.getInstance().update(board);
}
@Override
public void delete(int bno) {
BoardDao.getInstance().delete(bno);
}
}
2) 어노테이션을 쓴다면 (지금사용안함)
package com.lje.springboard.service;
import java.util.List;
import com.lje.springboard.dao.BoardDao;
import com.lje.springboard.dto.Board;
public class BoardServiceImpl implements BoardService {
BoardDao dao = null;
public BoardServiceImpl() {
dao = new BoardDao();
}
@Override
public List<Board> listAll() throws Exception {
// TODO Auto-generated method stub
return dao.selectAll();
}
@Override
public void insert(Board board) throws Exception {
dao.insert(board);
}
@Override
public read(int bno) throws Exception {
// TODO Auto-generated method stub
return dao.selectOne(bno);
}
@Override
public void modify(Board board) throws Exception {
dao.update(board);
}
@Override
public void delete(int bno) throws Exception {
dao.delete(bno);
}
}
이 경우 BoardDao.java도 수정
package com.lje.springboard.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import com.lje.springboard.dto.Board;
import com.mysql.cj.xdevapi.PreparableStatement;
public class BoardDao {
/*
* private BoardDao() { }
*
* private static BoardDao dao = new BoardDao();
*
* public static BoardDao getInstance() { return dao; }
*/
public Connection getConnection() { // 커넥트풀
Connection conn = null;
try {
Context initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:/comp/env");
DataSource ds = (DataSource) envContext.lookup("jdbc/myoracleDB");
conn = ds.getConnection();
// etc.
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
public List<Board> selectAll() {
List<Board> list = new ArrayList<Board>();
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
String sql = "select * from mvc_board";
try {
conn = getConnection();
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
while (rs.next()) {
Board board = new Board();
board.setBno(rs.getInt("bno"));
board.setWriter(rs.getString("writer"));
board.setTitle(rs.getString("title"));
board.setWrite_date(rs.getTimestamp("write_date"));
board.setHit(rs.getInt("hit"));
list.add(board);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
closeDB(conn, ps, rs);
}
return list;
}
public Board selectOne(int bno) {
Board board = null;
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
String sql = "select * from mvc_board where bno=?";
try {
conn = getConnection();
ps = conn.prepareStatement(sql);
ps.setInt(1, bno);
rs = ps.executeQuery();
while (rs.next()) {
board = new Board();
board.setBno(rs.getInt("bno"));
board.setWriter(rs.getString("writer"));
board.setTitle(rs.getString("title"));
board.setWrite_date(rs.getTimestamp("write_date"));
board.setHit(rs.getInt("hit"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
closeDB(conn, ps, rs);
}
return board;
}
public void insert(Board board) {
Connection conn = null;
PreparedStatement ps = null;
String sql = "insert into mvc_board(bno, writer, title, content) "
+ "values (mvc_board_seq.nextval, ?,?,?)";
try {
conn = getConnection();
ps = conn.prepareStatement(sql);
ps.setString(1, board.getWriter());
ps.setString(2, board.getTitle());
ps.setString(3, board.getContent());
int n = ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
closeDB(conn, ps);
}
}
public void update(Board board) {
Connection conn = null;
PreparedStatement ps = null;
String sql = "update mvc_board set writer=?, title=?, content=? "
+ "where bno=?";
try {
conn = getConnection();
ps = conn.prepareStatement(sql);
ps.setString(1, board.getWriter());
ps.setString(2, board.getTitle());
ps.setString(3, board.getContent());
ps.setInt(4, board.getBno());
int n = ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
closeDB(conn, ps);
}
}
public void delete(int bno) {
Connection conn = null;
PreparedStatement ps = null;
String sql = "delete from mvc_board where bno=?";
try {
conn = getConnection();
ps = conn.prepareStatement(sql);
ps.setInt(1, bno);
int n = ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
closeDB(conn, ps);
}
}
private void closeDB(Connection conn, PreparedStatement ps, ResultSet rs) {
try {
if (rs != null)
rs.close();
if (ps != null)
ps.close();
if (conn != null)
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private void closeDB(Connection conn, PreparedStatement ps) {
try {
if (ps != null)
ps.close();
if (conn != null)
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
CONTROLLER
BoardController.java
package com.lje.springboard.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.lje.springboard.dto.Board;
import com.lje.springboard.service.BoardService;
import com.lje.springboard.service.BoardServiceImpl;
@Controller
@RequestMapping("/board")
public class BoardController {
BoardService service;
@RequestMapping("/list")
public String list(Model model) {
service = new BoardServiceImpl();
model.addAttribute("list", service.listAll());
return "board/list";
}
@RequestMapping("/read")
public String read(@RequestParam("bno") int bno, Model model)
throws Exception{
service = new BoardServiceImpl();
model.addAttribute("board", service.read(bno));
return "board/update";
}
@GetMapping("write")
public String writeForm() {
return "board/write";
}
@PostMapping("write")
public String write(@ModelAttribute("board") Board board) {
service = new BoardServiceImpl();
System.out.println(board); //작업테스트
service.insert(board);
return "redirect:list";
}
@RequestMapping("update")
public String modify(@ModelAttribute("board") Board board) {
service = new BoardServiceImpl();
service.modify(board);
return "redirect:list";
}
@RequestMapping("delete")
public String delete(@RequestParam("bno") int bno) {
service = new BoardServiceImpl();
service.delete(bno);
return "board/view";
}
}
VIEW (JSP) : list.jsp / write.jsp ...
중간 실행해서 체크해볼 때는 폴더 안에 만들었으니 /board/를 빼먹지 않는다. http://localhost:8081/springboard/board/list
list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<table>
<tr>
<td>번호</td>
<td>제목</td>
<td>작성자</td>
<td>날짜</td>
<td>조회수</td>
</tr>
<c:forEach items="${list }" var="board">
<tr>
<td>${board.bno }</td>
<td><a href="read?bno=${board.bno}">${board.title }</a></td>
<td>${board.writer }</td>
<td>${board.write_date }</td>
<td>${board.hit }</td>
</tr>
</c:forEach>
</table>
</body>
</html>
write.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="write" method="POST">
<table>
<tr>
<td>작성자</td>
<td><input type="text" name="writer"></td>
</tr>
<tr>
<td>제목</td>
<td><input type="text" name="title"></td>
</tr>
<tr>
<td>내용</td>
<td><textarea rows="7" cols="50" name="content"></textarea></td>
</tr>
<tr>
<td colspan=2 align="center">
<input type="submit" value="저장">
<input type="reset" value="재작성">
</td>
</tr>
</table>
</form>
</body>
</html>
update.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>update.jsp</title>
</head>
<body>
<form action="update" method="POST">
<table border=1>
<tr>
<td>번호</td>
<td><input type="text" name="bno" readonly value="${board.bno }"></td>
</tr>
<tr>
<td>작성자</td>
<td><input type="text" name="writer" value="${board.writer }"></td>
</tr>
<tr>
<td>제목</td>
<td><input type="text" name="title" value="${board.title }"></td>
</tr>
<tr>
<td>내용</td>
<td><textarea rows="7" cols="50" name="content">${board.content }</textarea></td>
</tr>
<tr>
<td>작성일</td>
<td>${board.write_date }</td>
</tr>
<tr>
<td>조회수</td>
<td>${board.hit }</td>
</tr>
<tr>
<td colspan=2 align="center">
<input type="submit" value="저장">
<input type="reset" value="재작성">
<input type="reset" value="삭제" onclick="location.href='delete?bno=${board.bno}'">
<input type="reset" value="목록보기" onclick="location.href='list'">
</td>
</tr>
</table>
</form>
</body>
</html>
'Frameworks > Spring' 카테고리의 다른 글
lombok : setter, getter를 만들어주는 repository (0) | 2019.08.29 |
---|---|
Spring mybatis를 이용하여 게시판 만들기 (0) | 2019.08.28 |
Spring MVC 개요, 구조, Resourse 폴더, 컨트롤러 구현 (전통적인 3버전 방법) (0) | 2019.08.27 |
CRUD MVC 패턴 총정리 : 게시판만들기 (0) | 2019.08.26 |
스프링 프레임워크 Spring Framework (2) Spring 개발 환경 설정 (0) | 2019.08.23 |