(스프링,마이바티스,오라클연동 게시판실습2)스프링프레임워크MVC5, 마이바티스3.5, 오라클12.2 로그인, 게시판(페이징), Spring MVC5, MyBatis3.5, Oracle12.2, Login, Board Example
http://ojc.asia/bbs/board.php?bo_table=LecSpring&wr_id=852
(스프링,마이바티스,오라클연동 게시판실습2)스프링프레임워크MVC5, 마이바티스3.5, 오라클12.2 로그인, 게시판(페이징), Spring MVC5, MyBatis3.5, Oracle12.2, Login, Board Example
http://ojc.asia/bbs/board.php?bo_table=LecSpring&wr_id=852
(스프링,마이바티스,오라클연동 게시판실습2)스프링프레임워크MVC5, 마이바티스3.5, 오라클12.2 로그인, 게시판(페이징), Spring MVC5, MyBatis3.5, Oracle12.2, Login, Board Example
(스프링,마이바티스,오라클연동 게시판실습1)스프링프레임워크MVC5, 마이바티스3.5, 오라클12.2 로그인, 게시판(페이징), Spring MVC5, MyBatis3.5, Oracle12.2, Login, Board Example
스프링, 마이바티스, 오라클 연동 게시판실습 영상 첫번째 입니다. 자바웹 개발자가 되시고자 하시는 분들에게 도움이 되었으면 좋겠습니다. STS에서 Lombok 설치하는 부분은 두번째 영상에 설명되어 있습니다. ^^
스프링프레임워크MVC5, 마이바티스3.5, 오라클12.2 로그인, 게시판(페이징) 실습, Spring MVC5, MyBatis3.5, Oracle12.2, Login, Board Example
http://ojc.asia/bbs/write.php?w=u&bo_table=LecSpring&wr_id=849&page=
n 실습환경
JDK1.8
STS 4.7.1
Spring-Webmvc 5.2.3
MyBatis 3.5
mybatis-spring 2.0
Lombok 1.16.16
Servlet API 3.1.0
Apache Tomcat 9
Oracle 12.2
n 실행화면
n 프로젝트 구조
n DB 스키마(Oracle12.2에 scott 이라는 계정을 만들어 실행)
-- 아래는 오라클 12C 이상에서 작성된 스크립트 입니다.
DROP TABLE XUSER;
CREATE TABLE XUSER (
EMAIL VARCHAR2(100) NOT NULL PRIMARY KEY,
PASSWORD VARCHAR2(100) DEFAULT '1234'
);
DROP TABLE XBOARD;
CREATE TABLE XBOARD (
ID NUMBER(10,0) GENERATED BY DEFAULT AS IDENTITY,
WRITER VARCHAR2(100) DEFAULT NULL,
TITLE VARCHAR2(255) DEFAULT NULL,
CONTENT VARCHAR2(4000) DEFAULT NULL,
REG_DATE DATE DEFAULT NULL,
HIT_COUNT NUMBER(10,0) DEFAULT 0
);
INSERT INTO XUSER(EMAIL) VALUES('e1@google.com');
INSERT INTO XUSER(EMAIL) VALUES('e2@naver.com');
INSERT INTO XUSER(EMAIL) VALUES('e3@daum.com');
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e1@google.com', 'TITLE1', '내용1', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e2@naver.com', 'TITLE2', '내용2', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e1@google.com', 'TITLE3', '내용3', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e3@daum.com', 'TITLE4', '내용4', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e1@google.com', 'TITLE5', '내용5', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e2@naver.com', 'TITLE6', '내용6', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e3@daum.com', 'TITLE7', '내용7', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e2@naver.com', 'TITLE8', '내용8', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e1@google.com', 'TITLE9', '내용9', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e3@daum.com', 'TITLE10', '내용10', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e1@google.com', 'TITLE11', '내용11', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e2@naver.com', 'TITLE12', '내용12', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e1@google.com', 'TITLE13', '내용13', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e3@daum.com', 'TITLE14', '내용14', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e1@google.com', 'TITLE15', '내용15', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e2@naver.com', 'TITLE16', '내용16', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e3@daum.com', 'TITLE17', '내용17', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e2@naver.com', 'TITLE18', '내용18', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e1@google.com', 'TITLE19', '내용19', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e3@daum.com', 'TITLE20', '내용20', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e1@google.com', 'TITLE21', '내용21', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e2@naver.com', 'TITLE22', '내용22', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e1@google.com', 'TITLE23', '내용23', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e3@daum.com', 'TITLE24', '내용24', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e1@google.com', 'TITLE25', '내용25', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e2@naver.com', 'TITLE26', '내용26', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e3@daum.com', 'TITLE27', '내용27', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e2@naver.com', 'TITLE28', '내용28', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e1@google.com', 'TITLE29', '내용29', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e3@daum.com', 'TITLE30', '내용30', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e1@google.com', 'TITLE31', '내용31', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e2@naver.com', 'TITLE32', '내용32', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e1@google.com', 'TITLE33', '내용33', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e3@daum.com', 'TITLE34', '내용34', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e1@google.com', 'TITLE35', '내용35', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e2@naver.com', 'TITLE36', '내용36', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e3@daum.com', 'TITLE37', '내용37', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e2@naver.com', 'TITLE38', '내용38', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e1@google.com', 'TITLE39', '내용39', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e3@daum.com', 'TITLE40', '내용40', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e1@google.com', 'TITLE41', '내용41', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e2@naver.com', 'TITLE42', '내용42', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e1@google.com', 'TITLE43', '내용43', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e3@daum.com', 'TITLE44', '내용44', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e1@google.com', 'TITLE45', '내용45', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e2@naver.com', 'TITLE46', '내용46', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e3@daum.com', 'TITLE47', '내용47', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e2@naver.com', 'TITLE48', '내용48', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e1@google.com', 'TITLE49', '내용49', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e3@daum.com', 'TITLE50', '내용50', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e1@google.com', 'TITLE51', '내용51', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e2@naver.com', 'TITLE52', '내용52', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e1@google.com', 'TITLE53', '내용53', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e3@daum.com', 'TITLE54', '내용54', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e1@google.com', 'TITLE55', '내용55', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e2@naver.com', 'TITLE56', '내용56', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e3@daum.com', 'TITLE57', '내용57', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e2@naver.com', 'TITLE58', '내용58', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e1@google.com', 'TITLE59', '내용59', SYSDATE, 0);
INSERT INTO XBOARD( WRITER, TITLE, CONTENT, REG_DATE, HIT_COUNT) VALUES('e3@daum.com', 'TITLE60', '내용60', SYSDATE, 0);
COMMIT;
n 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>board2</groupId>
<artifactId>board2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<springframework-version>5.2.3.RELEASE</springframework-version>
<oracle.version>12.2.0.1</oracle.version>
<mybatis.spring.version>2.0.5</mybatis.spring.version>
<mybatis.version>3.5.5</mybatis.version>
<jstl.version>1.2</jstl.version>
<servlets.version>3.1.0</servlets.version>
<jsp.version>2.3.1</jsp.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${springframework-version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.16</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.oracle.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>${oracle.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis.spring.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlets.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>${jsp.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>oracle</id>
<name>ORACLE JDBC Repository</name>
<url>https://maven.xwiki.org/externals/</url>
</repository>
</repositories>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.3</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
</configuration>
</plugin>
</plugins>
</build>
</project>
n resources/jdbc.properties
# 오라클 접속 설정
jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1521:orcl
jdbc.username=scott
jdbc.password=tiger
n WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0">
<display-name>board2</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<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>
<error-page>
<error-code>404</error-code>
<location>/404.html</location>
</error-page>
<filter>
<filter-name>encoding-filter</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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding-filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
n WEB-INF/spring/root-Context.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:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<!-- web.xml에 정의된 ConterxtLoaderListener가 로딩하는
자바빈(부모컨텍스트)을 정의
DispatcherServlet이 로딩하는 자바빈은 자식 컨텍스트임 -->
<context:property-placeholder location="classpath:jdbc.properties" />
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:/mybatis/mybatis-config.xml" />
<property name="mapperLocations" value="classpath:/mybatis/mapper/**/*.xml" />
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage"
value="ojc.board.repository,ojc.user.repository" />
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"
destroy-method="clearCache">
<constructor-arg name="sqlSessionFactory" ref="SqlSessionFactory" />
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
n WEB-INF/spring/appServlet/servlet-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 디스패처 서블릿을 위한 설정 파일
정의된 자바빈을 디스패처 서블릿이 관리하는 컨텍스트에 로딩한다 -->
<!-- Spring MVC 컴포넌트들을 디폴트 설정을 통해 활성화.
Spring MVC @Controller에 요청을 보내 처리하기 위한
HandlerMapping과 HandlerAdapter를 빈으로 등록.
컨트롤러(@Controller)에서는 @RequestMapping, @ExceptionHandler
등과 같은 어노테이션을 통해 해당 기능을 사용할 수 있도록 한다. -->
<annotation-driven />
<!-- @Component, @Repository, @Service, @Controller
어노테이션을 가진 자바빈들을 스캐닝하기 위한 기본 패키지 경로 -->
<context:component-scan base-package="ojc" />
<resources mapping="/resources/**" location="/resources/" />
<!-- ViewResilver : 접두어, 접미어로 컨트롤러가 리턴하는 뷰의 이름을 해석 -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<!-- 로그인 여부를 확인하기 위한 인터셉터
게시판쪽으로 들어오는 요청은 로그인이 되지 않았다면
로그인 화면으로 보낸다. -->
<interceptors>
<interceptor>
<mapping path="/boards/**" />
<beans:bean class="ojc.web.interceptor.LoginInterceptor" />
</interceptor>
</interceptors>
</beans:beans>
n ojc.board.dto.Page.java
package ojc.board.dto;
import lombok.Data;
/**
* -------------------------------------
* STS에서 Lombok을 사용하기 위해서는
* -------------------------------------
* 1. pom.xml에 lombok dependency를 추가하고
* 2. .m2 아래 lombok-1.16.16.jar를 복사후 lombok.jar로 이름 변경
* 3. SpringToolSuite4.ini 파일의 맨아래에 -javaagent:lombok.jar 추가
* 4. STS 다시 시작
* @author jclee
*
* 페이징을 위한 클래스
*/
@Data
public class Pager {
private int page; // current page
private int size; // rows per page
private int bsize; // pages per block
private int rows; // total elements
private int pages; // total pages
private int blocks; // total blocks
private int block; // current block
private int bspage; // current block start page
private int bepage; // current block end page
public Pager(int page, int size, int bsize, int rows) {
//현재페이지
this.page = page;
//한페이지당 게시물개수
this.size = size;
//블럭당페이지사이즈(기본5로 되어 있음)
//페이지5개씩 한블럭에 표시되고 넘어가면 >> 표시가 나옴
this.bsize = bsize;
//총게시물건수
this.rows = rows;
//총페이지
pages = (int) Math.ceil((double) this.rows / this.size);
//총블럭
blocks = (int) Math.ceil((double) pages / this.bsize);
//현재블럭
block = (int) Math.ceil((double) this.page / this.bsize);
//현재블럭종료페이지
bepage = block * this.bsize;
//현재페이지시작페이지
bspage = bepage - this.bsize + 1;
}
// 두번째 페이지이고 한페이지에 10개씩 이라면 10을 리턴
public static int seekOffset(int page, int size) {
if (page > 0) {
return (page - 1) * size;
}
return 0;
}
// 두번째 페이지이고 한페이지에 10개씩 이라면 11을 리턴
public static int seekStart(int page, int size) {
return ((page - 1) * size) + 1;
}
// 두번째 페이지이고 한페이지에 10개씩 이라면 20을 리턴
public static int seekEnd(int page, int size) {
return page * size;
}
}
n ojc.board.model.Board.java
package ojc.board.model;
import java.util.Date;
import lombok.Data;
/**
* -------------------------------------
* STS에서 Lombok을 사용하기 위해서는
* -------------------------------------
* 1. pom.xml에 lombok dependency를 추가하고
* 2. .m2 아래 lombok-1.16.16.jar를 복사후 lombok.jar로 이름 변경
* 3. SpringToolSuite4.ini 파일의 맨아래에 -javaagent:lombok.jar 추가
* 4. STS 다시 시작
* @author jclee
*
* 오라클쪽의 XBOARD 테이블에 대응하는 모델 클래스
*/
@Data
public class Board {
private long id; //게시물ID
private String writer; //작성자
private String title; //제목
private String content; //본문내용
private Date regDate; //등록일시
private long hitCount; //조회수
}
n ojc.board.repository.BoardMapper.java
package ojc.board.repository;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import ojc.board.model.Board;
/**
* 매퍼 클래스
* board-mapper.xml의 namespace에 기술됨
* @author jclee
*
*/
@Mapper
public interface BoardMapper {
public int insert(Board board);
public int update(Board board);
public int delete(long id);
@Select("SELECT COUNT(*) FROM xboard")
public int count();
@Select("SELECT * FROM xboard ORDER BY id DESC")
public List<Board> selectAll();
public Board selectById(long id);
// 페이지 나누기 쿼리 : page : 현재페이지, size:페이지당 게시물개수
public List<Board> selectByLimit(@Param("page") int page, @Param("size") int size);
//조회수 증가 쿼리,본인이 쓴 글은 조회수를 증가 안하기 위해 글쓴이(requester)를 넘김
public int increment(@Param("id") long id, @Param("requester") String requester);
}
n ojc.login.dto.Login.java
package ojc.login.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* -------------------------------------
* STS에서 Lombok을 사용하기 위해서는
* -------------------------------------
* 1. pom.xml에 lombok dependency를 추가하고
* 2. .m2 아래 lombok-1.16.16.jar를 복사후 lombok.jar로 이름 변경
* 3. SpringToolSuite4.ini 파일의 맨아래에 -javaagent:lombok.jar 추가
* 4. STS 다시 시작
*
* @author jclee
* 로그인에서 사용되는 DTO
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Login {
private String email;
private String password;
private String error; //오류 메시지 셋팅위한 것 추가됨
}
n ojc.login.service.LoginService.java
package ojc.login.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import ojc.login.dto.Login;
import ojc.user.model.User;
import ojc.user.repository.UserMapper;
/**
* 로그인 서비스
* 사용자 인증
* @author jclee
*
*/
@Service
public class LoginService {
@Autowired
private UserMapper userMapper;
public void authenticate(Login login) {
User user = userMapper.selectByEmail(login.getEmail());
if (user == null) {
login.setError("Email does not exist.");
} else {
if (!user.getPassword().equals(login.getPassword())) {
login.setError("Password is not correct.");
} else {
login.setError(null);
}
}
}
}
n ojc.user.model.User.java
package ojc.user.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* -------------------------------------
* STS에서 Lombok을 사용하기 위해서는
* -------------------------------------
* 1. pom.xml에 lombok dependency를 추가하고
* 2. .m2 아래 lombok-1.16.16.jar를 복사후 lombok.jar로 이름 변경
* 3. SpringToolSuite4.ini 파일의 맨아래에 -javaagent:lombok.jar 추가
* 4. STS 다시 시작
* @author jclee
*
* 오라클쪽의 XUSER 테이블에 대응되는 모델 클래스
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private String email;
private String password;
}
n UserMapper.java
package ojc.user.repository;
import java.util.List;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.ResultType;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import ojc.user.model.User;
/**
* 매퍼 클래스
* board쪽고 달리 loign쪽은 매퍼 XML 파일 없이 이 자바 매퍼에서 쿼리 처리 다함
* @return
*/
@Mapper
public interface UserMapper {
@Insert("INSERT INTO xuser(email, password) VALUES(#{email}, #{password})")
public int insert(User user);
@Update("UPDATE xuser SET password = #{password} WHERE email = #{email}")
public int update(User user);
@Delete("DELETE FROM xuser WHERE email = #{email}")
public int delete(String email);
@Select("SELECT COUNT(*) FROM xuser")
public int count();
@Select("SELECT * FROM xuser ORDER BY email ASC")
@ResultType(User.class)
public List<User> selectAll();
@Select("SELECT * FROM xuser WHERE email = #{email}")
// 선언해 놓으면 다른 메소드에서 @ResultMap("userResultMap") 선언으로 이용할 수 있다.
@Results(id = "userResultMap", value = {
@Result(property = "email", column = "email"),
@Result(property = "password", column = "password") })
public User selectByEmail(String email);
}
n Ojc.web.controller.BoardController.java
package ojc.web.controller;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
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.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import ojc.board.dto.Pager;
import ojc.board.model.Board;
import ojc.board.repository.BoardMapper;
import ojc.user.model.User;
/**
* 게시판 요청 처리를 위한 컨트롤러
* @author jclee
*
*/
@Controller
@RequestMapping("/boards")
public class BoardController {
@Autowired
private BoardMapper boardMapper;
/**
* 게시판 리스트 보기
* @param page : 조회를 원하는 페이지
* @param size : 한페이지당 보여지는 게시물 건수
* @param bsize : 하나의 페이지 블럭에 포함되는 페이지 수(본 예제에서는 5개의 페이지를 보인다)
* @return
*/
@GetMapping()
public ModelAndView getBoardsView(
@RequestParam(name="page", required=false, defaultValue="1") int page,
@RequestParam(name="size", required=false, defaultValue="10") int size,
@RequestParam(name="bsize", required=false, defaultValue="5") int bsize) {
ModelAndView mav = new ModelAndView("board_list");
mav.addObject("boards", boardMapper.selectByLimit(page, size));
mav.addObject("pager", new Pager(page, size, bsize, boardMapper.count()));
return mav;
}
/**
* 게시물 상세보기
* @param id
* @param session
* @param model
* @return
*/
@GetMapping("/view/{id}")
public String getBoardView(@PathVariable long id, HttpSession session, Model model) {
User user = (User) session.getAttribute("user");
if (user == null) {
return session.getServletContext().getContextPath() + "/login";
}
boardMapper.increment(id, user.getEmail());
model.addAttribute("board", boardMapper.selectById(id));
return "board_view";
}
/**
* 글쓰기 화면 board_write.jsp 로딩
* @param session
* @param model
* @return
*/
@GetMapping("/write")
public String getInsertView(HttpSession session, Model model) {
User user = (User) session.getAttribute("user");
if (user == null) {
return session.getServletContext().getContextPath() + "/login";
}
model.addAttribute("user", user);
return "board_write";
}
/**
* 글쓰고 저장 하기
* XBOARD 테이블에 INSERT
* @param board
* @param session
* @param model
* @return
*/
@PostMapping("/write")
public String postInsert(Board board, HttpSession session, Model model) {
User user = (User) session.getAttribute("user");
if (user != null && board != null) {
if (user.getEmail().equals(board.getWriter())) {
boardMapper.insert(board);
return "redirect:/boards";
}
}
return session.getServletContext().getContextPath() + "/boards";
}
/**
* 수정화면 board_update.jsp 로딩
* @param id
* @param session
* @param model
* @return
*/
@GetMapping("/update/{id}")
public String getUpdateView(@PathVariable long id, HttpSession session, Model model) {
User user = (User) session.getAttribute("user");
Board board = boardMapper.selectById(id);
if (user != null && board != null) {
if (user.getEmail().equals(board.getWriter())) {
model.addAttribute("board", board);
return "board_update";
}
}
return session.getServletContext().getContextPath() + "/boards";
}
/**
* 수정후 저장하기 XBOARD 테이블 UPDATE 쿼리 실행
* @param board
* @param session
* @param model
* @return
*/
@PostMapping("/update")
public String postUpdate(Board board, HttpSession session, Model model) {
User user = (User) session.getAttribute("user");
if (user != null && board != null) {
if (user.getEmail().equals(board.getWriter())) {
boardMapper.update(board);
return "redirect:/boards/view/" + board.getId();
}
}
return session.getServletContext().getContextPath() + "/boards";
}
/**
* 게시물 삭제
* @param id : 게시물 ID
* @param session
* @param model
* @return
*/
@GetMapping("/delete/{id}")
public String getDelete(@PathVariable long id, HttpSession session, Model model) {
User user = (User) session.getAttribute("user");
if (user != null) {
Board board = boardMapper.selectById(id);
if (user.getEmail().equals(board.getWriter())) {
boardMapper.delete(id);
return "redirect:/boards";
}
}
return session.getServletContext().getContextPath() + "/boards";
}
}
n ojc.web.controller.ControllerExceptionHandler.java
package ojc.web.controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
@ControllerAdvice
public class ControllerExceptionHandler {
/**
* 컨트롤러에서 오류가 발생하면 error.jsp 로딩
*/
@ExceptionHandler(Exception.class)
public ModelAndView handleError(Exception e) {
ModelAndView mav = new ModelAndView("error/error");
mav.addObject("errorMsg", e.getMessage());
return mav;
}
}
n ojc.web.controller.HomeController.java
package ojc.web.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* 최초 localhost:8080 으로 요청이 오는 경우 처리
* @author jclee
*
*/
@Controller
@RequestMapping("/")
public class HomeController {
@GetMapping
public String getHomeView(HttpServletRequest request) {
return "home";
}
@GetMapping("/404.html")
public String get404View() {
return "error/404";
}
@GetMapping("/throw")
public String testControllerAdvice() {
throw new RuntimeException("Error Test In Controller.");
}
}
n ojc.web.controller.LoginController.java
package ojc.web.controller;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
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 ojc.login.dto.Login;
import ojc.login.service.LoginService;
import ojc.user.model.User;
/**
* 로그인 처리용 컨트롤러
* @author jclee
*
*/
@Controller
public class LoginController {
@Autowired
private LoginService loginService;
@ModelAttribute("active")
public String active(){
return "login";
}
@GetMapping("/login")
public String getLoginView() {
return "login";
}
/**
* 로그인 처리
* @param login
* @param model
* @param session
* @return
*/
@PostMapping("/login")
public String postLogin(Login login, Model model, HttpSession session) {
loginService.authenticate(login);
if (login.getError() != null) {
model.addAttribute("error", login.getError());
model.addAttribute("login", login);
return "login";
} else {
User user = new User(login.getEmail(), login.getPassword());
session.setAttribute("user", user);
return "redirect:/boards";
}
}
@GetMapping("/logout")
public String getLogout(HttpSession session) {
session.invalidate();
return "login";
}
}
n ojc.web.controller.UserController.java
package ojc.web.controller;
import java.util.List;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import ojc.user.model.User;
import ojc.user.repository.UserMapper;
/**
* 사용자 등록처리 컨트롤러
* @author jclee
*
*/
@Controller
@RequestMapping("/users")
public class UserController {
@Autowired
private UserMapper userMapper;
@GetMapping
@ResponseBody
public Object getUsersView() {
List<User> users = userMapper.selectAll();
return users;
}
@PostMapping("/enroll")
public String postUser(User user, Model model, HttpSession session, RedirectAttributes redirectAttributes) {
// 클라이언트 단 또는 서버 단에서 데이터 밸리데이션 체크를 적용하는 것을 권장한다.
User duplicatedUser = userMapper.selectByEmail(user.getEmail());
if (duplicatedUser == null) {
userMapper.insert(user);
redirectAttributes.addFlashAttribute("result", "OK");
} else {
redirectAttributes.addFlashAttribute("result", "FAIL");
redirectAttributes.addFlashAttribute("error", "Fail: Email is duplicated.");
}
return "redirect:/login";
}
}
n ojc.web.interceptor.LoginInterceptor.java
package ojc.web.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import ojc.user.model.User;
/**
* /board**로 진입시 로그인 여부를 체크하기 위한 인터셉터
* 로그인이 안되어 있는 경우 로그인 화면(/login) 으로 보냄
* @author jclee
*
*/
@Component
public class LoginInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
HttpSession session = request.getSession();
User user = (User) session.getAttribute("user");
if (user == null) {
String url = session.getServletContext().getContextPath() + "/login";
response.sendRedirect(url);
System.out.println("LoginInterceptor # preHandle() : NO PASS");
return false;
}
System.out.println("LoginInterceptor # preHandle() : PASS");
return true;
}
}
n resources/mybatis/mybatis-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>
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="mapUnderscoreToCamelCase" value="true" />
<setting name="defaultFetchSize" value="100" />
<setting name="defaultStatementTimeout" value="30" />
</settings>
<typeAliases>
<!-- 보통 VO객체여러개이고 한 패키지내에 존재할 때 package 사용.
아래 패키지 아래의 클래스들이 mapper xml에서 type으로 사용됨-->
<package name="ojc.board.model" />
<package name="ojc.user.model" />
</typeAliases>
</configuration>
n resources/mybatis/mapper/board-mapper.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="ojc.board.repository.BoardMapper">
<resultMap type="Board" id="boardResultMap">
<result property="id" column="ID" />
<result property="writer" column="WRITER" />
<result property="title" column="TITLE" />
<result property="content" column="CONTENT" />
<result property="regDate" column="REG_DATE" />
<result property="hitCount" column="HIT_COUNT" />
</resultMap>
<insert id="insert" parameterType="Board">
INSERT INTO xboard(writer, title, content, reg_date, hit_count)
VALUES(#{writer}, #{title}, #{content}, SYSDATE, 0)
</insert>
<update id="update" parameterType="Board">
UPDATE xboard SET title=#{title}, content=#{content} WHERE id=#{id}
</update>
<delete id="delete" parameterType="long">
DELETE FROM xboard WHERE id=#{id}
</delete>
<select id="selectById" parameterType="long" resultMap="boardResultMap">
SELECT * FROM xboard WHERE id=#{id}
</select>
<select id="selectByLimit" resultType="Board">
<bind name="start" value="@ojc.board.dto.Pager@seekStart(page, size)"/>
<bind name="end" value="@ojc.board.dto.Pager@seekEnd(page, size)"/>
<!-- SELECT * FROM (
SELECT ROWNUM AS rnum, b.*
FROM (
SELECT * FROM xboard
ORDER BY id DESC
) b
WHERE ROWNUM <= #{end}
) WHERE rnum >= #{start} -->
-- ORACLE12.1 이상
-- 9999페이지까지는 SKIP하고 그 다음 10000번째 페이지의 10개 추출
SELECT *
FROM xboard
ORDER BY id DESC
OFFSET TO_NUMBER(#{start}) - 1 ROWS FETCH NEXT 10 ROWS ONLY
</select>
<update id="increment">
UPDATE xboard SET hit_count=hit_count+1 WHERE id=#{id} and writer!=#{requester}
</update>
</mapper>
n WEB-INF/views/error/error.jsp
n WEB-INF/views/error/404.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 http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Board</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<style type="text/css">
.bs-example {
margin: 20px;
}
</style>
</head>
<body>
<c:import url="../nav_top.jsp"></c:import>
<div class="bs-example">
<h1>404 NOT FOUND</h1>
</div>
</body>
</html>
n WEB-INF/views/board_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 http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Board</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<style type="text/css">
.bs-example {
margin: 20px;
}
.pagination {
margin: 0px !important;
}
</style>
</head>
<body>
<c:import url="nav_top.jsp"></c:import>
<div class="bs-example">
<h2>Board</h2>
<table class="table table-condensed table-hover table-striped">
<thead>
<tr>
<th class="col-xs-1 col-sm-1 col-md-1 col-lg-1">No</th>
<th class="col-xs-6 col-sm-6 col-md-6 col-lg-6">Title</th>
<th class="col-xs-2 col-sm-2 col-md-2 col-lg-2">Writer</th>
<th class="col-xs-2 col-sm-2 col-md-2 col-lg-2">Date</th>
<th class="col-xs-1 col-sm-1 col-md-1 col-lg-1">Hits</th>
</tr>
</thead>
<tbody>
<c:forEach items="#{boards }" var="board">
<tr>
<td>${board.id }</td>
<td><a href="<c:url value='/boards/view/${board.id }'/>">${board.title }</a></td>
<td>${board.writer }</td>
<td><fmt:formatDate pattern="MM-dd hh:mm" value="${board.regDate }" /></td>
<td>${board.hitCount }</td>
</tr>
</c:forEach>
</tbody>
</table>
<div class="row">
<div class="col-xs-8 col-sm-8 col-md-8 col-lg-8">
<ul class="pagination">
<c:set var="target" value="boards" />
<!-- 게시물이 없는 경우 -->
<c:if test="${pager.rows==0 }">
<li class="active"><a href="#">1</a></li>
</c:if>
<!-- 게시물이 있는 경우 -->
<c:if test="${pager.rows > 0 }">
<!-- common 변수에 한페이지당 레코드건수&블럭당 페이지수 저장 -->
<c:set var="common"
value="size=${pager.size }&bsize=${pager.bsize }" />
<!-- 블럭시작페이지가 블럭당 페이지수 보다 큰 경우
예를들면 6번째 페이지를 보는 경우
Home 및 이전 << 셋팅. -->
<c:if test="${pager.bspage > pager.bsize }">
<c:set var="home" value="page=1&${common }" />
<c:set var="prev" value="page=${pager.bspage-1 }&${common }" />
<li><a href="${target }?${home }">Home</a></li>
<li><a href='<c:url value="${target }?${prev }"/>'>«</a></li>
</c:if>
<!-- 5개의 페이지 번호를 표시 -->
<c:forEach var="pno"
begin="${pager.bspage }"
end="${pager.bepage }">
<c:if test="${pno==pager.page }">
<li class="active"><a href="#">${pno }</a></li>
</c:if>
<c:if test="${pno!=pager.page }">
<c:if test="${pno <= pager.pages }">
<c:set var="page" value="page=${pno }&${common }" />
<li><a href='<c:url value="${target }?${page }"/>'>${pno }</a></li>
</c:if>
</c:if>
</c:forEach>
<!-- 블럭시작페이지가 전체 페이지수 보다 작은 경우
예를들면 전체 페이지수가 6인데 1~5번째 페이지를 보는 경우
Last 및 이후 >> 셋팅. -->
<c:if test="${pager.bepage < pager.pages }">
<c:set var="next" value="page=${pager.bepage+1 }&${common }" />
<c:set var="last" value="page=${pager.pages }&${common }" />
<li><a href='<c:url value="${target }?${next }"/>'>»</a></li>
<li><a href="${target }?${last }">Last</a></li>
</c:if>
</c:if>
</ul>
</div>
<div class="col-xs-4 col-sm-4 col-md-4 col-lg-4">
<span class="pull-right"> <a href="<c:url value='/boards/write'/>" class="btn btn-primary">Write</a>
</span>
</div>
</div>
</div>
</body>
</html>
n WEB-INF/views/board_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 http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Board</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<style type="text/css">
.bs-example {
margin-bottom: 20px;
margin-left: 20px;
margin-right: 40px;
margin-top: 20px;
}
</style>
</head>
<body>
<c:import url="nav_top.jsp"></c:import>
<div class="bs-example">
<form class="form-horizontal" action="<c:url value='/boards/update'/>" method="post">
<input type="hidden" name="id" value="${board.id }">
<div class="form-group">
<label for="title" class="control-label col-xs-2">Title</label>
<div class="col-xs-10">
<input type="text" class="form-control" id="title" name="title" placeholder="Title" required
value="${board.title }">
</div>
</div>
<div class="form-group">
<label for="writer" class="control-label col-xs-2">Writer</label>
<div class="col-xs-10">
<input type="text" class="form-control" id="writer" name="writer" placeholder="Writer" required
value="${board.writer }" readonly="readonly">
</div>
</div>
<div class="form-group">
<label for="content" class="control-label col-xs-2">Content</label>
<div class="col-xs-10">
<textarea class="form-control" rows="20" id="content" name="content" placeholder="Content" required>${board.content }</textarea>
</div>
</div>
<div class="form-group">
<label for="regDate" class="control-label col-xs-2">Date</label>
<div class="col-xs-10">
<input type="text" class="form-control" id="regDate" placeholder="Date" required
value="<fmt:formatDate pattern="yyyy-MM-dd hh:mm:ss" value="${board.regDate }" />" readonly="readonly">
</div>
</div>
<div class="form-group">
<div class="col-xs-offset-2 col-xs-10">
<a href="<c:url value='/boards'/>" class="btn btn-primary">List</a>
<button type="submit" class="btn btn-primary">Update</button>
</div>
</div>
</form>
</div>
</body>
</html>
n WEB-INF/views/board_view.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 http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Board</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<style type="text/css">
.bs-example {
margin-bottom: 20px;
margin-left: 20px;
margin-right: 40px;
margin-top: 20px;
}
</style>
</head>
<body>
<c:import url="nav_top.jsp"></c:import>
<div class="bs-example">
<form class="form-horizontal" action="/examples/actions/confirmation.php" method="post">
<div class="form-group">
<label for="title" class="control-label col-xs-2">Title</label>
<div class="col-xs-10">
<input type="text" class="form-control" id="title" name="title" placeholder="Title" required
value="${board.title }" readonly="readonly">
</div>
</div>
<div class="form-group">
<label for="writer" class="control-label col-xs-2">Writer</label>
<div class="col-xs-10">
<input type="text" class="form-control" id="writer" name="writer" placeholder="Writer" required
value="${board.writer }" readonly="readonly">
</div>
</div>
<div class="form-group">
<label for="content" class="control-label col-xs-2">Content</label>
<div class="col-xs-10">
<textarea class="form-control" rows="20" id="content" name="content" placeholder="Content" required
readonly="readonly">${board.content }</textarea>
</div>
</div>
<div class="form-group">
<label for="regDate" class="control-label col-xs-2">Date</label>
<div class="col-xs-10">
<input type="text" class="form-control" id="regDate" name="regDate" placeholder="Date" required
value="<fmt:formatDate pattern="yyyy-MM-dd hh:mm:ss" value="${board.regDate }" />" readonly="readonly">
</div>
</div>
<div class="form-group">
<div class="col-xs-offset-2 col-xs-10">
<a href="<c:url value='/boards'/>" class="btn btn-primary">List</a>
<c:if test="${not empty user }">
<c:if test="${user.email == board.writer }">
<a href="<c:url value='/boards/delete/${board.id }'/>" class="btn btn-primary">Delete</a>
<a href="<c:url value='/boards/update/${board.id }'/>" class="btn btn-primary">Update</a>
</c:if>
</c:if>
</div>
</div>
</form>
</div>
</body>
</html>
n WEB-INF/views/board_writer.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 http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Board</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<style type="text/css">
.bs-example {
margin-bottom: 20px;
margin-left: 20px;
margin-right: 40px;
margin-top: 20px;
}
</style>
</head>
<body>
<c:import url="nav_top.jsp"></c:import>
<div class="bs-example">
<form class="form-horizontal" action="<c:url value='/boards/write'/>" method="post">
<div class="form-group">
<label for="title" class="control-label col-xs-2">Title</label>
<div class="col-xs-10">
<input type="text" class="form-control" id="title" name="title" placeholder="Title" required>
</div>
</div>
<div class="form-group">
<label for="writer" class="control-label col-xs-2">Writer</label>
<div class="col-xs-10">
<input type="text" class="form-control" id="writer" name="writer" placeholder="Writer" required
value="${user.email }" readonly="readonly">
</div>
</div>
<div class="form-group">
<label for="content" class="control-label col-xs-2">Content</label>
<div class="col-xs-10">
<textarea class="form-control" rows="20" id="content" name="content" placeholder="Content" required></textarea>
</div>
</div>
<div class="form-group">
<div class="col-xs-offset-2 col-xs-10">
<a href="<c:url value='/boards'/>" class="btn btn-primary">List</a>
<button type="submit" class="btn btn-primary">Save</button>
</div>
</div>
</form>
</div>
</body>
</html>
n WEB-INF/views/home.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">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Board</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<style type="text/css">
.bs-example {
margin: 20px;
}
.logo-small {
color: #f4511e;
font-size: 50px;
}
footer .glyphicon {
font-size: 20px;
margin-bottom: 20px;
color: #f4511e;
}
</style>
</head>
<body id="myPage">
<c:import url="nav_top.jsp"></c:import>
<br>
<br>
<br>
<div id="services" class="container-fluid text-center">
<h2>스프링MVC5, 마이바티스3.5, 오라클12 연동 게시판</h2>
<h4>Spring Framework5 + MyBatis3.5 + Oracle12</h4>
<br>
<div class="row slideanim">
<div class="col-sm-4">
<span class="glyphicon glyphicon-off logo-small"></span>
<h4>
<c:if test="${not empty user }">
<a href="logout">LOGOUT</a>
</c:if>
<c:if test="${empty user }">
<a href="login">LOGIN</a>
</c:if>
</h4>
<p>로그인</p>
</div>
<div class="col-sm-4">
<span class="glyphicon glyphicon-heart logo-small"></span>
<h4><a href="boards">BOARD</a></h4>
<p>스프링,마이바티스 게시판</p>
</div>
<div class="col-sm-4">
<span class="glyphicon glyphicon-lock logo-small"></span>
<h4>YOUR TURN</h4>
<p>Lorem ipsum dolor sit amet..</p>
</div>
</div>
</div>
<br>
<br>
<br>
<footer class="container-fluid text-center">
<a href="#myPage" title="To Top"><span class="glyphicon glyphicon-chevron-up"></span></a>
<p>Made By <a href="#" title="#">have a nice day!</a></p>
</footer>
</body>
n </html>WEB-INF/views/login.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 http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Board</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<style type="text/css">
@import url(https://fonts.googleapis.com/css?family=Roboto:300);
.login-page {
width: 360px;
padding: 8% 0 0;
margin: auto;
}
.form {
position: relative;
z-index: 1;
background: #FFFFFF;
max-width: 360px;
margin: 0 auto 100px;
padding: 45px;
text-align: center;
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24);
}
.form input {
font-family: "Roboto", sans-serif;
outline: 0;
background: #f2f2f2;
width: 100%;
border: 0;
margin: 0 0 15px;
padding: 15px;
box-sizing: border-box;
font-size: 14px;
}
.form button {
font-family: "Roboto", sans-serif;
text-transform: uppercase;
outline: 0;
background: #4CAF50;
width: 100%;
border: 0;
padding: 15px;
color: #FFFFFF;
font-size: 14px;
-webkit-transition: all 0.3 ease;
transition: all 0.3 ease;
cursor: pointer;
}
.form button:hover, .form button:active, .form button:focus {
background: #43A047;
}
.form .message {
margin: 15px 0 0;
color: #b3b3b3;
font-size: 12px;
}
.form .message a {
color: #4CAF50;
text-decoration: none;
}
.form .register-form {
display: none;
}
.container {
position: relative;
z-index: 1;
max-width: 300px;
margin: 0 auto;
}
.container:before, .container:after {
content: "";
display: block;
clear: both;
}
.container .info {
margin: 50px auto;
text-align: center;
}
.container .info h1 {
margin: 0 0 15px;
padding: 0;
font-size: 36px;
font-weight: 300;
color: #1a1a1a;
}
.container .info span {
color: #4d4d4d;
font-size: 12px;
}
.container .info span a {
color: #000000;
text-decoration: none;
}
.container .info span .fa {
color: #EF3B3A;
}
</style>
<script type="text/javascript">
$(function() {
$('.message a').click(function() {
$('form').animate({height : "toggle", opacity : "toggle"}, "slow");
$('#result').css('display','none');
});
var result = "${result}";
if(result){
if(result === 'OK'){
$("#myModal").modal('show');
} else {
$('form').animate({height : "toggle", opacity : "toggle"}, "fast");
}
}
});
</script>
</head>
<body>
<c:import url="nav_top.jsp"></c:import>
<div class="login-page">
<div class="form">
<form class="register-form" action="<c:url value='/users/enroll'/>" method="post">
<input type="text" id="email" name="email" placeholder="Email" />
<input type="password" id="password" name="password" placeholder="Password" />
<button type="submit">create</button>
<p class="message">Already registered? <a href="#">Sign In</a></p>
</form>
<form class="login-form" action="<c:url value='/login'/>" method="post">
<input type="text" id="email" name="email" placeholder="Email" value="${login.email }"/>
<input type="password" id="password" name="password" placeholder="Password" />
<button type="submit">login</button>
<p class="message">Not registered? <a href="#">Create an account</a></p>
</form>
<c:if test="${not empty error }">
<br>
<span class="label label-danger" id="result">${error }</span>
</c:if>
</div>
</div>
<div id="myModal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Completed Membership</h4>
</div>
<div class="modal-body">
<p>Your registration has been successfully completed.</p>
<p class="text-warning">
<small>Please click the OK button and try logging in.</small>
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">OK</button>
</div>
</div>
</div>
</div>
</body>
</html>
n WEB-INF/view/nav_top.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<nav class="navbar navbar-default">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="<c:url value='/'/>">Home</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="<c:url value='/boards'/>">Board</a></li>
<li><a href="#">Another action</a></li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<c:if test="${not empty user }">
<li><a href="#"><span class="badge">${user.email }</span></a></li>
</c:if>
<li class="${active=='login'?'active':'' }">
<c:if test="${not empty user }">
<a href="<c:url value='/logout'/>">Logout</a>
</c:if>
<c:if test="${empty user }">
<a href="<c:url value='/login'/>">Login</a>
</c:if>
</li>
<li class="${active=='board'?'active':'' }"><a href="<c:url value='/boards'/>">Board</a></li>
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
<!-- /.container-fluid -->
</nav>
<script type="text/javascript">
// 화면이 갱신되면 효과를 잃어 버린다.
$('.nav li').click(function(e) {
$('.nav li').removeClass('active');
$(this).addClass('active');
});
</script>
(C#교육동영상)C# ADO.NET 실습 ODP.NET/ODAC 설치 오라클 함수 호출 실습, C#학원, WPF학원, 닷넷학원, 자바학원 https://www.youtube.com/watch?v=qIPU85yAlzc&list=PLxU-i...