스프링
JDBCTemplate 연습 3 ( 방명록 ) Service
스프링 설정 클래스 ( AppCtx )
package config;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import guestbook.dao.MessageDao;
import guestbook.service.DeleteMessageService;
import guestbook.service.GetMessageListService;
import guestbook.service.WriteMessageService;
@Configuration
public class AppCtx {
@Bean(destroyMethod = "close") // 빈이 소멸될 때 커넥션 풀을 닫도록 설정
public DataSource dataSource() {
DataSource ds = new DataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/guestbook?"
+"useSSL=true&useUnicode=true&characterEncoding=utf8");
ds.setUsername("jspexam");
ds.setPassword("jsppw");
ds.setInitialSize(2); // 초기 커넥션 개수 지정
ds.setMaxActive(10); // 최대 커넥션 개수 지정
return ds;
}
@Bean
public MessageDao messageDao() {
return new MessageDao(dataSource());
}
@Bean
public DeleteMessageService deleteMessageService() {
return new DeleteMessageService();
}
@Bean
public GetMessageListService getMessageListService() {
return new GetMessageListService();
}
@Bean
public WriteMessageService writeMessageService() {
return new WriteMessageService();
}
}
DAO ( 주석 처린 된 곳은 JDBC )
package guestbook.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import guestbook.model.Message;
public class MessageDao {
private JdbcTemplate jdbcTemplate;
public MessageDao(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
private Message makeMessageFromResultSet(ResultSet rs) throws SQLException {
Message message = new Message();
message.setId(rs.getInt("message_id"));
message.setGuestName(rs.getString("guest_name"));
message.setPassword(rs.getString("password"));
message.setMessage(rs.getString("message"));
return message;
}
public int insert(Message message) {
String sql = "insert into guestbook_message " +
"(guest_name, password, message) values (?, ?, ?)";
return jdbcTemplate.update(sql,
message.getGuestName(),
message.getPassword(),
message.getMessage()
);
}
// public int insert(Connection conn, Message message) throws SQLException {
// PreparedStatement pstmt = null;
// try {
// pstmt = conn.prepareStatement(
// "insert into guestbook_message " +
// "(guest_name, password, message) values (?, ?, ?)");
// pstmt.setString(1, message.getGuestName());
// pstmt.setString(2, message.getPassword());
// pstmt.setString(3, message.getMessage());
// return pstmt.executeUpdate();
// } finally {
// JdbcUtil.close(pstmt);
// }
// }
public Message select(int messageId) {
String sql = "select * from guestbook_message where message_id = ?";
return jdbcTemplate.queryForObject(sql,
(ResultSet rs, int rowNum) -> {
return makeMessageFromResultSet(rs);
} ,messageId);
}
// public Message select(Connection conn, int messageId) throws SQLException {
// PreparedStatement pstmt = null;
// ResultSet rs = null;
// try {
// pstmt = conn.prepareStatement(
// "select * from guestbook_message where message_id = ?");
// pstmt.setInt(1, messageId);
// rs = pstmt.executeQuery();
// if (rs.next()) {
// return makeMessageFromResultSet(rs);
// } else {
// return null;
// }
// } finally {
// JdbcUtil.close(rs);
// JdbcUtil.close(pstmt);
// }
// }
public int selectCount() {
String sql = "select count(*) from guestbook_message";
Integer count = jdbcTemplate.queryForObject(sql, Integer.class);
return count;
}
// public int selectCount(Connection conn) throws SQLException {
// Statement stmt = null;
// ResultSet rs = null;
// try {
// stmt = conn.createStatement();
// rs = stmt.executeQuery("select count(*) from guestbook_message");
// rs.next();
// return rs.getInt(1);
// } finally {
// JdbcUtil.close(rs);
// JdbcUtil.close(stmt);
// }
// }
public List<Message> selectList(int firstRow, int endRow){
String sql = "select * from guestbook_message " +
"order by message_id desc limit ?, ?";
List<Message> result = jdbcTemplate.query(sql,
(rs, rowNum) -> makeMessageFromResultSet(rs),
firstRow - 1,
endRow - firstRow + 1);
return result;
}
// public List<Message> selectList(Connection conn, int firstRow, int endRow)
// throws SQLException {
// PreparedStatement pstmt = null;
// ResultSet rs = null;
// try {
// pstmt = conn.prepareStatement(
// "select * from guestbook_message " +
// "order by message_id desc limit ?, ?");
// pstmt.setInt(1, firstRow - 1);
// pstmt.setInt(2, endRow - firstRow + 1);
// rs = pstmt.executeQuery();
// if (rs.next()) {
// List<Message> messageList = new ArrayList<Message>();
// do {
// messageList.add(makeMessageFromResultSet(rs));
// } while (rs.next());
// return messageList;
// } else {
// return Collections.emptyList();
// }
// } finally {
// JdbcUtil.close(rs);
// JdbcUtil.close(pstmt);
// }
// }
public int delete1(int messageId) {
String sql = "delete from guestbook_message where message_id = ?";
return jdbcTemplate.update(sql, messageId);
}
// public int delete(Connection conn, int messageId) throws SQLException {
// PreparedStatement pstmt = null;
// try {
// pstmt = conn.prepareStatement(
// "delete from guestbook_message where message_id = ?");
// pstmt.setInt(1, messageId);
// return pstmt.executeUpdate();
// } finally {
// JdbcUtil.close(pstmt);
// }
// }
}
DeleteMessageService ( ID값, passwrd 값 비교 후 맞으면 게시물 삭제 )
package guestbook.service;
import org.springframework.beans.factory.annotation.Autowired;
import guestbook.dao.MessageDao;
import guestbook.model.Message;
public class DeleteMessageService {
// 싱글톤
// private static DeleteMessageService instance = new DeleteMessageService();
//
// public static DeleteMessageService getInstance() {
// return instance;
// }
//
// private DeleteMessageService() {
// }
@Autowired
private MessageDao messageDao;
public void deleteMessage(int messageId, String password) {
Message message = messageDao.select(messageId);
if (message == null) {
throw new MessageNotFoundException("메시지 없음");
}
if (!message.matchPassword(password)) {
throw new InvalidPassowrdException("bad password");
}
messageDao.delete1(messageId);
}
}
결과 테스트 ( 9 id값 가진 게시물 패스워드 맞으면 삭제 )
public class MainTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx =
new AnnotationConfigApplicationContext(AppCtx.class);
DeleteMessageService ds = ctx.getBean("deleteMessageService",DeleteMessageService.class);
ds.deleteMessage(9, "111");
}
}
GetMessageListService ( 방명록 메시지를 페이지 단위로 조회 ) 페이징
package guestbook.service;
import java.util.Collections;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import guestbook.dao.MessageDao;
import guestbook.model.Message;
public class GetMessageListService {
@Autowired
private MessageDao messageDao;
// 한 페이지에 표시될 메시지 수
private static final int MESSAGE_COUNT_PER_PAGE = 3;
public MessageListView getMessageList(int pageNumber) {
int currentPageNumber = pageNumber; // 요청받은 페이지 번호
// 전체 메시지의 수를 가져옴
int messageTotalCount = messageDao.selectCount();
List<Message> messageList = null;
int firstRow = 0;
int endRow = 0;
if (messageTotalCount > 0) {
// 요청한 페이지의 첫 번째 메시지와 마지막 메시지의 인덱스를 계산
firstRow = (pageNumber - 1) * MESSAGE_COUNT_PER_PAGE + 1;
endRow = firstRow + MESSAGE_COUNT_PER_PAGE - 1;
// 메시지를 firstRow부터 endRow까지 조회하여 리스트로 가져옴
messageList = messageDao.selectList(firstRow, endRow);
} else {
// 전체 메시지가 없는 경우 (빈 리스트)
currentPageNumber = 0;
messageList = Collections.emptyList();
}
// 조회된 메시지 리스트와 페이징에 필요한 정보들을 MessageListView 객체로 생성하여 반환
return new MessageListView(
messageList, // 조회된 메시지 리스트
messageTotalCount, // 전체 메시지 수
currentPageNumber, // 현재 페이지 번호
MESSAGE_COUNT_PER_PAGE, // 한 페이지에 표시될 메시지 수
firstRow, // 현재 페이지의 첫 번째 메시지 인덱스
endRow // 현재 페이지의 마지막 메시지 인덱스
);
}
}
결과 테스트 ( MessageListView mlv = gs.getMessageList(1);은 1페이지 출력 )
public class MainTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx =
new AnnotationConfigApplicationContext(AppCtx.class);
// 페이지 읽어오기
GetMessageListService gs = ctx.getBean("getMessageListService", GetMessageListService.class);
MessageListView mlv = gs.getMessageList(1);
List<Message> list = mlv.getMessageList();
for(Message msg : list) {
System.out.println(msg);
}
}
}
WriteMessageService ( 추가 )
package guestbook.service;
import org.springframework.beans.factory.annotation.Autowired;
import guestbook.dao.MessageDao;
import guestbook.model.Message;
public class WriteMessageService {
@Autowired
private MessageDao messageDao;
public void write(Message message) {
messageDao.insert(message);
}
}
결과 테스트
public class MainTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx =
new AnnotationConfigApplicationContext(AppCtx.class);
// 페이지 읽어오기
WriteMessageService ws = ctx.getBean("writeMessageService", WriteMessageService.class);
Message message = new Message("홍금보", "123", "홍홍홍");
ws.write(message);
}
}
커맨드 핸들러 ( CommandHandler )_방명록_JSP 실습
1. CommandHandler.java ( 인터페이스 ), ControllerUsingURI.java ( 서블릿 ) 환경 설정
( 코드 그대로 사용 )
CommandHandler.java
package command;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface CommandHandler {
public String process(HttpServletRequest req, HttpServletResponse res) throws Exception;
}
ControllerUsingURI.java
package command;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import config.AppCtx;
public class ControllerUsingURI extends HttpServlet {
// 어디서든 사용할 수 있게 설정
//public static ApplicationContext ctx;
// @Autowired
// BoardService boardService;
ApplicationContext ctx;
// <커맨드, 핸들러인스턴스> 매핑 정보 저장
private Map<String, String> commandHandlerMap =
new HashMap<>();
// 서블릿 초기화 메서드
public void init() throws ServletException {
ctx = new AnnotationConfigApplicationContext(AppCtx.class);
// configFile 초기화 파라미터를 읽어온다.
// 이 값을 이용해서 설정 파일 경로를 구한다.
String configFile = getInitParameter("configFile");
System.out.println(configFile);
Properties prop = new Properties();
String configFilePath = getServletContext().getRealPath(configFile);
System.out.println(configFilePath);
// 설정 파일로부터 매핑 정보를 읽어와 Properties 객체에 저장한다.
// Properties는 (이름, 값) 목록을 갖는 클래스로서,
// 이 경우에는 프로퍼티 이름을 커맨드 이름으로 사용하고
// 값을 클래스 이름으로 사용한다.
try (FileReader fis = new FileReader(configFilePath)) { // 파일 읽기
// 설정 파일을 읽어서 Properties 객체에 로드 ( 맵에 보관 )
prop.load(fis);
} catch (IOException e) {
throw new ServletException(e);
}
// Properties에 저장된 각 프로퍼티의 키에 대해 다음 작업을 반복한다.
Iterator keyIter = prop.keySet().iterator();
while (keyIter.hasNext()) {
// 1. 프로퍼티 이름을 커맨드 이름으로 사용한다.
String command = (String) keyIter.next();
// 2. 커맨드 이름에 해당하는 핸들러 클래스 이름을 Properties에서 구한다.
String handlerClassName = prop.getProperty(command);
commandHandlerMap.put(command, handlerClassName);
// try {
// // 3. 핸들러 클래스 이름을 이용해서 Class 객체를 구한다.
// Class<?> handlerClass = Class.forName(handlerClassName);
// // 4. Class로부터 핸들러 객체를 생성한다.
// CommandHandler handlerInstance =
// (CommandHandler) handlerClass.newInstance();
// // 5. commandHandlerMap에 (커맨드, 핸들러 객체)에 대한 매핑 정보를 저장한다.
// commandHandlerMap.put(command, handlerInstance);
// } catch (ClassNotFoundException | InstantiationException
// | IllegalAccessException e) {
// throw new ServletException(e);
// }
}
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
process(request, response);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
process(request, response);
}
// 클라이언트로부터 들어오는 HTTP 요청에 대해 처리를 수행
// 그에 맞는 핸들러를 호출하여 요청을 처리하고 결과를 뷰 페이지에 전달
private void process(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// 클라이언트가 요청한 URI를 가져온다.
String command = request.getRequestURI();
// 요청된 URI가 웹 어플리케이션의 Context Path(컨텍스트 경로)로 시작한다면,
// Context Path 부분을 제거하여 실제로 처리할 명령어를 추출
// 예)/hello.do 추출
if (command.indexOf(request.getContextPath()) == 0) {
command = command.substring(request.getContextPath().length());
}
System.out.println(command);
// 추출된 명령어를 사용하여 commandHandlerMap에서 해당 커맨드에 대응하는 핸들러를 가져온다.
// commandHandlerMap은 init() 메서드에서 설정 파일로부터 읽어온 커맨드와 핸들러 클래스를 매핑한 맵
// CommandHandler handler = commandHandlerMap.get(command);
// // 만약 해당 명령어에 대응하는 핸들러가 없다면, 기본적으로 NullHandler를 사용
// if (handler == null) {
// handler = new NullHandler();
// }
// 찾아낸 핸들러를 사용하여 실제 요청 처리를 수행
// 핸들러의 process() 메서드를 호출하여 요청 처리 결과로 뷰 페이지의 경로를 가져온다.
// 최종적으로 클라이언트에게 보여질 JSP 페이지의 위치를 나타낸다.
String handler = commandHandlerMap.get(command);
System.out.println(handler);
// 인터페이스 다형성
CommandHandler helloHandler = ctx.getBean(handler, CommandHandler.class);
String viewPage = null;
try {
viewPage = helloHandler.process(request, response);
} catch (Throwable e) {
throw new ServletException(e);
}
// 만약 뷰 페이지 경로가 존재한다면, RequestDispatcher를 사용하여 해당 뷰 페이지로 포워딩
// 즉, 요청된 작업의 처리 결과를 클라이언트에게 보여줄 JSP 페이지로 이동하게 된다.
if (viewPage != null) {
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPage);
dispatcher.forward(request, response);
}
}
}
2. web.xml 파일 : 서블릿 name, class, mapping 설정 확인
<?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_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>ControllerUsingURI</servlet-name>
<servlet-class>command.ControllerUsingURI</servlet-class>
<init-param>
<param-name>configFile</param-name>
<param-value>
/WEB-INF/commandHandlerURI.properties
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ControllerUsingURI</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
3. Handler.java 파일 작성
ListHandler
package command;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import guestbook.service.GetMessageListService;
import guestbook.service.MessageListView;
public class ListHandler implements CommandHandler {
@Autowired
private GetMessageListService getMessageListService;
@Override
public String process(HttpServletRequest req, HttpServletResponse res) throws Exception {
String pageNumberStr = req.getParameter("page");
int pageNumber = 1;
if (pageNumberStr != null) {
pageNumber = Integer.parseInt(pageNumberStr);
}
MessageListView viewData =
getMessageListService.getMessageList(pageNumber);
req.setAttribute("viewData", viewData);
return "/WEB-INF/view/list.jsp";
}
}
WriteMessageHandler
package command;
import java.io.UnsupportedEncodingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import guestbook.model.Message;
import guestbook.service.WriteMessageService;
public class WriteMessageHandler implements CommandHandler {
@Autowired
private WriteMessageService writeMessageService;
@Override
public String process(HttpServletRequest req, HttpServletResponse res) throws UnsupportedEncodingException {
req.setCharacterEncoding("utf-8");
String guestName = req.getParameter("guestName");
String password = req.getParameter("password");
String message = req.getParameter("message");
Message msg = new Message(guestName, password, message);
writeMessageService.write(msg);
return "/WEB-INF/view/writeMessage.jsp";
}
}
ConfirmDeletionHandler ( 삭제 여부 비밀번호로 확인만 하는 페이지 )
package command;
import java.io.UnsupportedEncodingException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import guestbook.service.DeleteMessageService;
public class ConfirmDeletionHandler implements CommandHandler {
@Autowired
private DeleteMessageService deleteMessageService;
@Override
public String process(HttpServletRequest req, HttpServletResponse res) throws UnsupportedEncodingException {
String messageId = req.getParameter("messageId");
req.setAttribute("messageId", messageId);
return "/WEB-INF/view/confirmDeletion.jsp";
}
}
DeleteMessageHandler ( 실제로 삭제 처리 하는 곳 )
package command;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import guestbook.service.DeleteMessageService;
import guestbook.service.InvalidPassowrdException;
public class DeleteMessageHandler implements CommandHandler {
@Autowired
private DeleteMessageService deleteMessageService;
@Override
public String process(HttpServletRequest req, HttpServletResponse res) {
int messageId = Integer.parseInt(req.getParameter("messageId"));
String password = req.getParameter("password");
String invalidPassowrd = "no";
try {
deleteMessageService.deleteMessage(messageId, password);
} catch(InvalidPassowrdException ex) {
invalidPassowrd = "yes";
}
req.setAttribute("invalidPassowrd", invalidPassowrd);
return "/WEB-INF/view/deleteMessage.jsp";
}
}
4. 스프링 설정 클래스 @Bean 등록 ( 핸들러에서 Service 사용, 핸들러도 @Bean 등록 )
package config;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import command.ConfirmDeletionHandler;
import command.DeleteMessageHandler;
import command.ListHandler;
import command.WriteMessageHandler;
import guestbook.dao.MessageDao;
import guestbook.service.DeleteMessageService;
import guestbook.service.GetMessageListService;
import guestbook.service.WriteMessageService;
@Configuration
public class AppCtx {
@Bean(destroyMethod = "close") // 빈이 소멸될 때 커넥션 풀을 닫도록 설정
public DataSource dataSource() {
DataSource ds = new DataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/guestbook?"
+"useSSL=true&useUnicode=true&characterEncoding=utf8");
ds.setUsername("jspexam");
ds.setPassword("jsppw");
ds.setInitialSize(2); // 초기 커넥션 개수 지정
ds.setMaxActive(10); // 최대 커넥션 개수 지정
return ds;
}
@Bean
public MessageDao messageDao() {
return new MessageDao(dataSource());
}
@Bean
public DeleteMessageService deleteMessageService() {
return new DeleteMessageService();
}
@Bean
public GetMessageListService getMessageListService() {
return new GetMessageListService();
}
@Bean
public WriteMessageService writeMessageService() {
return new WriteMessageService();
}
@Bean
public ListHandler listHandler() {
return new ListHandler();
}
@Bean
public WriteMessageHandler writeMessageHandler() {
return new WriteMessageHandler();
}
@Bean
public ConfirmDeletionHandler confirmDeletionHandler() {
return new ConfirmDeletionHandler();
}
@Bean
public DeleteMessageHandler deleteMessageHandler() {
return new DeleteMessageHandler();
}
}
5. commandHandlerURI.properties : /hello.do=helloHandler ( 주소 지정 및 @Bean 변수명 )
/hello.do=helloHandler
/list.do=listHandler
/writeMessage.do=writeMessageHandler
/confirmDeletion.do=confirmDeletionHandler
/deleteMessage.do=deleteMessageHandler
6. JSP에서 자바 코드 없이 작성 ( jstl : 가능 ) / ( 경로 WEB-INF => view디렉터리 )
List.jsp
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>방명록 메시지 목록</title>
</head>
<body>
<form action="writeMessage.do" method="post">
이름: <input type="text" name="guestName"> <br>
암호: <input type="password" name="password"> <br>
메시지: <textarea name="message" cols="30" rows="3"></textarea> <br>
<input type="submit" value="메시지 남기기" />
</form>
<hr>
<c:if test="${viewData.isEmpty()}">
등록된 메시지가 없습니다.
</c:if>
<c:if test="${!viewData.isEmpty()}">
<table border="1">
<c:forEach var="message" items="${viewData.messageList}">
<tr>
<td>
메시지 번호: ${message.id} <br/>
손님 이름: ${message.guestName} <br/>
메시지: ${message.message} <br/>
<a href="confirmDeletion.do?messageId=${message.id}">[삭제하기]</a>
</td>
</tr>
</c:forEach>
</table>
<c:forEach var="pageNum" begin="1" end="${viewData.pageTotalCount}">
<a href="list.jsp?page=${pageNum}">[${pageNum}]</a>
</c:forEach>
</c:if>
</body>
</html>
writeMessage.jsp
<%@ page contentType="text/html; charset=utf-8" %>
<html>
<head>
<title>방명록 메시지 남김</title>
</head>
<body>
방명록에 메시지를 남겼습니다.
<br/>
<a href="list.do">[목록 보기]</a>
</body>
</html>
confirmDeletion.jsp
<%@ page contentType="text/html; charset=utf-8" %>
<html>
<head>
<title>방명록 메시지 삭제 확인</title>
</head>
<body>
<form action="deleteMessage.do" method="post">
<input type="hidden" name="messageId" value="${messageId}">
메시지를 삭제하시려면 암호를 입력하세요:<br>
암호: <input type="password" name="password"> <br>
<input type="submit" value="메시지 삭제하기">
</form>
</body>
</html>
deleteMessage.jsp
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>방명록 메시지 삭제함</title>
</head>
<body>
<c:choose>
<c:when test="${invalidPassowrd eq 'no'}">
<p> 메시지를 삭제하였습니다. </p>
</c:when>
<c:otherwise>
<p> 입력한 암호가 올바르지 않습니다. 암호를 확인해주세요. </p>
</c:otherwise>
</c:choose>
<br/>
<a href="list.do">[목록 보기]</a>
</body>
</html>
'프로젝트 기반 자바(JAVA) 응용 SW개발자 취업과정' 카테고리의 다른 글
2023-08-08 58일차 (0) | 2023.08.08 |
---|---|
2023-08-07 57일차 (0) | 2023.08.07 |
2023-08-03 55일차 (0) | 2023.08.03 |
2023-08-02 54일차 (0) | 2023.08.02 |
2023-08-01 53일차 (0) | 2023.08.01 |