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>net.developia</groupId>
<artifactId>spring01</artifactId>
<name>spring01</name>
<packaging>war</packaging>
<version>1.0.0-BUILD-SNAPSHOT</version>
<properties>
<java-version>11</java-version>
<org.springframework-version>5.0.7.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>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</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.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.16.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.lazyluke/log4jdbc-remix -->
<dependency>
<groupId>org.lazyluke</groupId>
<artifactId>log4jdbc-remix</artifactId>
<version>0.2.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.oracle.database.jdbc/ojdbc11 -->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc11</artifactId>
<version>21.11.0.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<additionalProjectnatures>
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
</additionalProjectnatures>
<additionalBuildcommands>
<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
</additionalBuildcommands>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>11</source>
<target>11</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>org.test.int1.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
ArticleDetail.java
package net.developia.spring01.article.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
import lombok.AllArgsConstructor;
import net.developia.spring01.article.dto.ArticleDTO;
import net.developia.spring01.article.service.ArticleService;
@Controller
@AllArgsConstructor
public class ArticleDetail {
@Autowired
ArticleService service;
@GetMapping("/article/detail")
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
throws Exception {
long no = Long.parseLong(request.getParameter("no"));
try {
ArticleDTO dto = service.getDetail(no);
return new ModelAndView("article/detail","dto",dto);
} catch (Exception e) {
ModelAndView mav = new ModelAndView("/WEB-INF/views/article/result.jsp");
mav.addObject("msg", e.getMessage());
mav.addObject("url", "list");
return mav;
}
}
}
ArticleInsert.java
package net.developia.spring01.article.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
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.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
import net.developia.spring01.article.dto.ArticleDTO;
import net.developia.spring01.article.service.ArticleService;
@Controller
@RequestMapping("/article")
public class ArticleInsert {
@Autowired
ArticleService service;
@GetMapping("/insert")
public ModelAndView insert(HttpServletRequest request, HttpServletResponse response) {
return new ModelAndView("article/insert");
}
@PostMapping("/insertAction")
public ModelAndView insertAction(HttpServletRequest request, HttpServletResponse response) {
String name = request.getParameter("name");
String title = request.getParameter("title");
String password = request.getParameter("password");
String content = request.getParameter("content");
ArticleDTO articleDTO = new ArticleDTO();
articleDTO.setName(name);
articleDTO.setTitle(title);
articleDTO.setPassword(password);
articleDTO.setContent(content);
try {
service.insertArticle(articleDTO);
return new ModelAndView("redirect:list");
} catch (Exception e) {
ModelAndView mav = new ModelAndView("article/result");
mav.addObject("msg", "게시물 입력 실패\\n입력 폼으로 되돌아갑니다.");
mav.addObject("url", "javascript:history.back();");
return mav;
}
}
}
ArticleInsertAction.java
package net.developia.spring01.article.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
import lombok.AllArgsConstructor;
import lombok.extern.java.Log;
import net.developia.spring01.article.dto.ArticleDTO;
import net.developia.spring01.article.service.ArticleService;
@Controller
@Log
@AllArgsConstructor
public class ArticleInsertAction extends AbstractController {
@Autowired
ArticleService service;
@Override
@PostMapping
public ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) {
String name = request.getParameter("name");
String title = request.getParameter("title");
String password = request.getParameter("password");
String content = request.getParameter("content");
ArticleDTO articleDTO = new ArticleDTO();
articleDTO.setName(name);
articleDTO.setTitle(title);
articleDTO.setPassword(password);
articleDTO.setContent(content);
try {
service.insertArticle(articleDTO);
return new ModelAndView("redirect:list");
} catch (Exception e) {
ModelAndView mav = new ModelAndView("article/result");
mav.addObject("msg", "게시물 입력 실패\\n입력 폼으로 되돌아갑니다.");
mav.addObject("url", "javascript:history.back();");
return mav;
}
}
}
Article.java
package net.developia.spring01.article.controller;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
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.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.developia.spring01.article.dto.ArticleDTO;
import net.developia.spring01.article.service.ArticleService;
@Controller
@Slf4j
@AllArgsConstructor
public class ArticleList extends AbstractController {
//ArticleService service = ArticleService.getInstance();
@Autowired
ArticleService service;
@RequestMapping(value="/article/list",
method= {RequestMethod.GET, RequestMethod.POST})
@Override
public ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) {
try {
List<ArticleDTO> list = service.getArticleList();
return new ModelAndView("article/list", "list", list);
} catch (Exception e) {
ModelAndView mav = new ModelAndView("/WEB-INF/views/article/result.jsp");
mav.addObject("msg", "게시물 리스트 출력 실패");
mav.addObject("url", "../");
return mav;
}
}
}
ArticleDAO.java
package net.developia.spring01.article.dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Repository;
import lombok.extern.java.Log;
import net.developia.spring01.article.dto.ArticleDTO;
@Log
@Repository
public class ArticleDAO {
public ArticleDAO() {
try {
Class.forName("net.sf.log4jdbc.DriverSpy");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
private Connection getConnection() throws SQLException {
return DriverManager.getConnection(
"jdbc:log4jdbc:oracle:thin:@localhost:1521/xepdb1", "ace","ace");
}
public void insertArticle(ArticleDTO articleDTO) throws SQLException {
String sql =
"insert into article(no, title, name, content, password)" +
"values(seq_article.nextval, ?, ?, ?, ?)";
try(Connection conn = getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, articleDTO.getTitle());
pstmt.setString(2, articleDTO.getName());
pstmt.setString(3, articleDTO.getContent());
pstmt.setString(4, articleDTO.getPassword());
pstmt.executeQuery();
}
}
public List<ArticleDTO> getArticleList() throws SQLException {
String sql =
"SELECT no,title,name,regdate,readcount " +
"FROM article " +
"ORDER BY no DESC ";
List<ArticleDTO> list = new ArrayList<>();
try(Connection conn = getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery()) {
while(rs.next()) {
ArticleDTO dto = new ArticleDTO();
dto.setNo(rs.getLong("no"));
dto.setTitle(rs.getString("title"));
dto.setName(rs.getString("name"));
dto.setRegdate(rs.getDate("regdate"));
dto.setReadcount(rs.getInt("readcount"));
list.add(dto);
}
return list;
}
}
public ArticleDTO getDetail(long no) throws SQLException {
String sql =
"SELECT no,title,name,regdate,readcount,content " +
"FROM article " +
"WHERE no=? ";
ArticleDTO dto = null;
try(Connection conn = getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)){
pstmt.setLong(1, no);
try(ResultSet rs = pstmt.executeQuery()) {
if (rs.next()) {
dto = new ArticleDTO();
dto.setNo(rs.getLong("no"));
dto.setTitle(rs.getString("title"));
dto.setName(rs.getString("name"));
dto.setRegdate(rs.getDate("regdate"));
dto.setReadcount(rs.getInt("readcount"));
dto.setContent(rs.getString("content"));
}
return dto;
}
}
}
}
ArticleDTO.java
package net.developia.spring01.article.dto;
import java.io.Serializable;
import java.util.Date;
import org.apache.commons.codec.digest.DigestUtils;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class ArticleDTO implements Serializable {
private long no;
private String title;
private String name;
private String password;
private String content;
private Date regdate;
private int readcount;
public void setPassword(String password) {
this.password = DigestUtils.sha512Hex(password);
}
}
ArticleService.java
package net.developia.spring01.article.service;
import java.sql.SQLException;
import java.util.List;
import org.springframework.stereotype.Service;
import lombok.extern.java.Log;
import net.developia.spring01.article.dao.ArticleDAO;
import net.developia.spring01.article.dto.ArticleDTO;
@Log
@Service
public class ArticleService {
private ArticleDAO dao;
public ArticleService(ArticleDAO dao) {
this.dao = dao;
}
public void insertArticle(ArticleDTO articleDTO) throws SQLException {
try {
dao.insertArticle(articleDTO);
} catch (SQLException e) {
log.info(e.getMessage());
throw e;
}
}
public List<ArticleDTO> getArticleList() throws Exception {
try {
return dao.getArticleList();
} catch (Exception e) {
log.info(e.getMessage());
throw e;
}
}
public ArticleDTO getDetail(long no) throws Exception {
try {
ArticleDTO dto = dao.getDetail(no);
if (dto == null) throw new RuntimeException(no + "번 게시물이 존재하지 않습니다.");
return dto;
} catch (Exception e) {
log.info(e.getMessage());
throw e;
}
}
}
article_style.css
@charset "UTF-8";
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 20px;
}
table {
width: 50%;
margin: 20px auto;
border-collapse: collapse;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
border-radius: 5px;
}
caption {
font-size: 1.5em;
font-weight: bold;
padding: 10px;
background-color: #007bff;
color: white;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
th, td {
padding: 10px;
text-align: left;
border-bottom: 1px solid #ddd;
}
th {
background-color: #f2f2f2;
}
a {
text-decoration: none;
color: #007bff;
margin-right: 10px;
}
a:hover {
text-decoration: underline;
}
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 https://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<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>
<context:component-scan base-package="net.developia.spring01.article" />
<!--
<beans:bean name="/game/ready" class="net.developia.spring01.mvc.ReadyController" />
<beans:bean name="/game/result" class="net.developia.spring01.mvc.ResultController" />
<beans:bean name="/hello" class="net.developia.spring01.SpringMVC" />
-->
<!--
<beans:bean name="articleDao" class="net.developia.spring01.article.dao.ArticleDAO" />
<beans:bean name="articleService" class="net.developia.spring01.article.service.ArticleService">
<beans:constructor-arg ref="articleDao" />
</beans:bean>
<beans:bean name="/article/insert" class="net.developia.spring01.article.controller.ArticleInsert" />
<beans:bean name="/article/list" class="net.developia.spring01.article.controller.ArticleList">
<beans:constructor-arg ref="articleService" />
</beans:bean>
<beans:bean name="/article/detail" class="net.developia.spring01.article.controller.ArticleDetail">
<beans:constructor-arg ref="articleService" />
</beans:bean>
<beans:bean name="/article/insertAction" class="net.developia.spring01.article.controller.ArticleInsertAction">
<beans:constructor-arg ref="articleService" />
</beans:bean>
-->
</beans:beans>
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"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
</beans>
article/detail.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" %>
<c:set var="myContextPath" value="${pageContext.request.contextPath}" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="${myContextPath}/resources/css/article_style.css">
</head>
<body>
<img src="<c:url value="/resources/img/detail_icon.jpg" />" width="20" />
<img src="${myContextPath}/resources/img/detail_icon.jpg" width="20" />
<table>
<caption>게시물 상세보기</caption>
<tr>
<th>글번호</th>
<td>${dto.no}</td>
</tr>
<tr>
<th>제목</th>
<td>${dto.title}</td>
</tr>
<tr>
<th>이름</th>
<td>${dto.name}</td>
</tr>
<tr>
<th>내용</th>
<td>${dto.content}</td>
</tr>
<tr>
<th>작성일</th>
<td><fmt:formatDate value="${dto.regdate}" pattern="yyyy-MM-dd HH:mm:ss"/></td>
</tr>
<tr>
<th>조회수</th>
<td>${dto.readcount}</td>
</tr>
</table><br/>
<a href="update?no=${dto.no}">수정</a> |
<a href="delete?no=${dto.no}">삭제</a> |
<a href="list">리스트</a>
</body>
</html>
article/insert.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:set var="app" value=""/>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="article_styles.css">
</head>
<body>
<form name="myform" method="post" action="insertAction">
<table>
<caption>게시물 글쓰기</caption>
<tr>
<th>제목</th>
<td><input type="text" name="title" autofocus required /></td>
</tr>
<tr>
<th>이름</th>
<td><input type="text" name="name" required /></td>
</tr>
<tr>
<th>비밀번호</th>
<td><input type="password" name="password" required /></td>
</tr>
<tr>
<th>내용</th>
<td><textarea name="content" rows="5" cols="40"></textarea></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="완료" />
</td>
</tr>
</table>
</form>
</body>
</html>
article/list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- 구글 폰트 -->
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+KR" rel="stylesheet">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link rel="stylesheet" href="../css/site.css">
<link rel="icon" type="image/png" sizes="16x16" href="/webdev/kitty.png">
<title>Insert title here</title>
</head>
<body>
<br/>
<div class="container">
<div class="jumbotron"><h1>게시물 리스트</h1></div>
<div style="text-align: right">1/1000</div>
<table border="1" class="table">
<thead class="thead-dark">
<tr>
<th scope="col">번호</th>
<th scope="col">제목</th>
<th scope="col">작성자</th>
<th scope="col">작성일</th>
<th scope="col">조회수</th>
</tr>
</thead>
<c:forEach items="${list}" var="article">
<tr>
<th scope="row">${article.no}</th>
<td><a href="detail?no=${article.no}">${article.title}</a></td>
<td>${article.name}</td>
<td>${article.regdate}</td>
<td>${article.readcount}</td>
</tr>
</c:forEach>
</table>
<br/>
<button type="button" class="btn btn-primary" onclick="javascript:location.href='insert'">글쓰기</button>
</div>
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>
result.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<script type="text/javascript">
alert('${msg}');
location.href='${url}';
</script>
</body>
</html>
web.xml
<?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">
<filter>
<filter-name>character encoding</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>character encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 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>
</web-app>
http://localhost:8080/spring01/article/insert
http://localhost:8080/spring01/article/list
http://localhost:8080/spring01/article/detail?no=11
[참고자료]