예순여덟 번째 수업

정혅·2024년 10월 6일

더 조은 아카데미

목록 보기
72/76

jsp 오전 문제

구구단 출력하기

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="Bruce">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
<%!
    public int sum(int num1, int num2){
    return num1 * num2;
}
%>
<table border = "1">
<%
    out.print("<caption>구구단</caption>");
    for(int i = 1; i < 10; i++){
        out.print("<tr>");
        for(int j = 2; j < 10; j++){
            out.print("<td> " + i + " * " + j + " = " + sum(i, j) + "</td>");
        }
        out.print("</tr>");
    }
%>
</table>
</body>
</html>

출력하기

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="Bruce">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
<%!
    int i = 1;
    String str = "ABCED";
    public int sum(int num1, int num2){
        return num1 + num2;
    }
%>
<%
    out.print(i + " "); //1
    out.print(str + " "); //ABCED
    out.print(sum(10, 20)); //30
%>
</body>
</html>

표현식으로 출력하기

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="Bruce">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
<%!
    int i = 1;
    String str = "ABCED";
    public int sum(int num1, int num2){
        return num1 + num2;
    }
%>
<%= i %><br>
<%= str %><br>
<%= sum(10, 20) %><br>
</body>
</html>
  • 출력 값은 위와 같은데 거기서 개행 되었음

배열 값을 toString()을 이용해 출력

<%@page import="java.util.Arrays"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="Bruce">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Insert title here</title>
</head>
<body>
    <%
    int[] iArr = { 10, 20, 30 };
    out.print(Arrays.toString(iArr) + "<br>");
    %>
</body>
</html>

게시판 글쓰기 - 비밀번호 유효성 검사 및 목록 보기

sql 테이블 생성

CREATE TABLE board
(
no int AUTO_INCREMENT PRIMARY KEY,
title varchar(200),
name varchar(20),
password varchar(20),
email varchar(20),
contents text,
wTime datetime default CURRENT_TIMESTAMP,
rcnt int DEFAULT 0
);

글 작성

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="Bruce">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>게시판 글 쓰기</title>
</head>
<body>
    <form method="post" action="writeOK.jsp">
        <table>
            <caption>글 쓰 기</caption>
            <tr>
                <td><label for="title">제목</label></td><td><input type="text" name="title" id="title" size="40" required></td>
            </tr>
            <tr>
                <td><label for="name">이름</label></td><td><input type="text" name="name" id="name" size="40"  required></td>
            </tr>
            <tr>
                <td><label for="pw">비밀번호</label></td><td><input type="password" name="pw" id="pw" size="40"  required></td>
            </tr>
            <tr>
                <td><label for="email">E-mail</label></td><td><input type="email" name="email" id="email" size="40"  required></td>
            </tr>
            <tr>
                <td colspan="2"><textarea cols="50" rows="10" name="contents"  required></textarea></td>
            </tr>
            <tr>
                <td colspan="2"><input type="submit" value="등록"> <a href="list.jsp"><input type="button" value="목록"></a></td>
            </tr>
        </table>
    </form>
</body>
</html>
  • 등록을 누르면 writeOk파일로 이동, 목록을 누르면 list 파일로 이동

등록 - writeOK

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.sql.*"%>
<%
    request.setCharacterEncoding("UTF-8");
    String title = request.getParameter("title");
    String name = request.getParameter("name");
    String pw = request.getParameter("pw");
    String email = request.getParameter("email");
    String contents = request.getParameter("contents");

    String driver = "com.mysql.cj.jdbc.Driver";
    String url = "jdbc:mysql://localhost:3306/project?serverTimezone=UTC";
    String mysqlId = "root";
    String mysqlPw = "1234";

    String sql = "INSERT INTO board(title, name, password, email, contents) values(?, ?, ?, ?, ?)";
    int result = 0;

    try{
        Class.forName(driver);
    } catch(ClassNotFoundException e){
        System.out.println("드라이버 로드 실패");
    }
    try(Connection conn = DriverManager.getConnection(url, mysqlId, mysqlPw);
            PreparedStatement pstmt = conn.prepareStatement(sql)){
        pstmt.setString(1, title);
        pstmt.setString(2, name);
        pstmt.setString(3, pw);
        pstmt.setString(4, email);
        pstmt.setString(5, contents);
        result = pstmt.executeUpdate();
        if(result > 0) response.sendRedirect("list.jsp");
        else response.sendRedirect("error.jsp");
    }  catch(SQLException e){
        e.printStackTrace();
    }
%>
  • pstmt.setString을 통해 넘어온 값을 해당 번째의 물음표에 넣어서 sql에 값 입력

  • 값 삽입이 성공했다면 list 실패했다면 error로 이동

목록 list

<%@ page import="java.sql.*"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>게시판 목록</title>
</head>
<body>
    <h3>목록</h3>
    <table border="1">
        <tr>
            <td>번호</td>
            <td>제목</td>
            <td>작성자</td>
            <td>작성일</td>
            <td>조회수</td>
        </tr>
        <%
        String driver = "com.mysql.cj.jdbc.Driver";
        String url = "jdbc:mysql://localhost:3306/project?serverTimezone=UTC";
        String mysqlId = "root";
        String mysqlPw = "1234";
        String sql = "Select no, title, name, wTime, rCnt, email from BOARD ORDER BY no DESC";
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            System.out.println("드라이버 로드 실패");
        }

        try (Connection conn = DriverManager.getConnection(url, mysqlId, mysqlPw);
                PreparedStatement pstmt = conn.prepareStatement(sql);
                ResultSet rs = pstmt.executeQuery()) {
            while (rs.next()) {
        %>
        <tr>
            <td><%=rs.getInt("no")%></td>
            <td><a href="view.jsp?no=<%=rs.getInt("no")%>"><%=rs.getString("title")%></a></td>
            <td><a href="mailto:<%=rs.getString("email")%>"><%=rs.getString("name")%></a></td>
            <td><%=rs.getString("wTime")%></td>
            <td><%=rs.getString("rCnt")%></td>
        </tr>
        <%
        }
        } catch (SQLException e) {
        e.printStackTrace();
        }
        %>
    </table>
    <div>
        <a href="write.jsp">글쓰기</a>
    </div>
</body>
</html>
  1. sql에서 받아온 정보를 getInt("no")로 번호를 가져와서 넣었다.

  2. <a href="view.jsp?no=<%=rs.getInt("no")%>"><%=rs.getString("title")%> 부분은 view.jsp페이지로 이동하되 url에 no 라는 파라미터 이름을 추가해 특정 게시글의 번호를 전달한다.

    • 물음표는 URL에 쿼리 문자열을 추가하기 위한 구분 기호이다. >> 웹 서버에 추가 정보를 전달하는 데 사용되며, 이름-값 쌍의 형태로 구성된다.
  • no=<%=rs.getInt("no")%>는 쿼리 문자열입니다. no는 파라미터의 이름이고, <%=rs.getInt("no")%>는 그 값이다. 이 값은 ResultSet에서 가져온 게시글의 번호다. > view.jsp에서 request.getParameter("no"); 하면 no의 값을 가져올 수 있다.

    따라서 링크를 클릭하면 view.jsp페이지로 이동하면서 URL에 no파라미터를 포함해 전달해 해당 페이지에서 no파라미터를 사용해 특정 게시글의 상세정보를 db에서 조회할 수 있다.

  1. <a href="mailto:<%=rs.getString("email")%>"><%=rs.getString("name")%> 부분은 mailto: 스키마를 사용해 이메일 클라이언트를 열고, 작성자의 이메일 줏를 수신자로 설정해 사용자를 클릭하여 메일을 보낼 수 있게끔 연결할 수 있다. >> 앵커태그와, 해당 스키마의 기능

작성 글 수정 및 삭제하기

view.jsp

<%@page import="java.sql.*"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>내용보기</title>
<style>
form {
    display: inline;
}
</style>
</head>
<body>
    <table border="1">
        <caption>내용보기</caption>
        <%
        String no = request.getParameter("no");

        String driver = "com.mysql.cj.jdbc.Driver";
        String url = "jdbc:mysql://localhost:3306/project?serverTimezone=UTC";
        String mysqlId = "root";
        String mysqlPw = "1234";
        String sql = "SELECT title, name, wTime, contents, rCnt, password FROM board where no =" + no;
        String pw = null; // 추가

        int rCnt = 0;
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            System.out.println("드라이버 로드 실패");
        }

        try (Connection conn = DriverManager.getConnection(url, mysqlId, mysqlPw);
                Statement stmt = conn.createStatement();
                ResultSet rs = stmt.executeQuery(sql)) {
            if (rs.next()) {
                rCnt = rs.getInt("rCnt");
                pw = rs.getString("password"); // 추가
        %>
        <tr>
            <td>제목</td>
            <td><%=rs.getString("title")%></td>
        </tr>
        <tr>
            <td>이름</td>
            <td><%=rs.getString("name")%></td>
        </tr>
        <tr>
            <td>작성일</td>
            <td><%=rs.getString("wTime")%></td>
        </tr>
        <tr>
            <td colspan="2"><textarea cols="50" rows="10" style="resize: none;" ><%=rs.getString("contents")%></textarea></td>
        </tr>
        <%
        }
        sql = "UPDATE board SET rCnt = " + (rCnt + 1) + " WHERE no = " + no;
        stmt.executeUpdate(sql); /*조회수 업데이트해서 sql에 수정 > 띄어쓰기 주의 */
        } catch (SQLException e) {
        e.printStackTrace();
        }
        %>
    </table>
    <a href="list.jsp"><input type="button" value="목록" class="formbtn"></a>
    <form method="post" action="inputPassword.jsp">
        <input type="hidden" name="no" value="<%=no%>"> <input type="hidden" name="pw"
            value="<%=pw%>"> <input type="hidden" name="mode" value="2"> <input type="submit"
            value="수정" class="formbtn">
    </form>
    <form method="post" action="inputPassword.jsp">
        <input type="hidden" name="no" value="<%=no%>"> <input type="hidden" name="pw"
            value="<%=pw%>"> <input type="hidden" name="mode" value="1"> <input type="submit"
            value="삭제" class="formbtn">
    </form>
    <%--앵커태그 방법으로  <a href="inputPassword.jsp?no=<%=no%>&pw=<%=pw%>&mode=1">삭제</a> --%>
</body>
</html>
  • createStatement() : SQL문을 데이터베이스에 보내기 위한 Statement객체를 생성

    • Statement 객체는 executeQuery()메소드를 사용해 SQL쿼리를 실행하고, ResultSet 객체를 반환해 SQL 쿼리의 결과를 나타내고, next()메소드를 사용해 각 레코드를 순회할 수 있다. > executeUpdate()를 사용해 수정 삭제도 가능하다.
  • <td colspan="2"><textarea cols="50" rows="10" style="resize: none;"><%=rs.getString("contents")%></textarea></td> 게시글의 내용을 불러오는 코드다.textarea태그를 사용하면, 텍스트의 줄바꿈이 그대로 유지되므로, 게시글의 내용을 원래 형태로 보여줄 수 있다. style="resize: none" 은 사용자가 textarea필드의 크기를 변경할 수 없게 비활성화 할 수 있다.

  • input type="hidden" 으로 설정하면, 숨겨진 입력 필드를 생성한다. > 웹 페이지에 표시되지 않고, 사용자는 이를 볼 수도, 직접 수정할 수도 없다. 웹 페이지의 콘텐츠 내에서는 보이지 않고, 이를 보안 수단으로 사용해서는 안된다.

  • form 태그 내에서 name="mode"는 폼 데이터를 서버로 전송할 때 추가저인 정보를 제공하는 데 사용된다. mode의 값에 따라 서버에서 수행할 작업이 달라지는 것이다. > inputPassword.jsp 페이지에서 이 mode파라미터를 확인해 무엇을 수행할 지 정한다.

    • post로 파라미터를 보냈으니 request.getParameter("mode") 로 확인

비밀번호 입력 inputPassword.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>비밀번호 입력</title>
</head>
<body>
    <form method="post" action="inputPasswordOK.jsp">
        <table>
            <tr>
                <td>비밀번호</td><td><input type="password" name="password"></td>
            </tr>
            <tr>
                <td colspan="2"><input type="submit" value="확인"></td>
            </tr>            
        </table>
        <input type = "hidden" name="no" value="<%=request.getParameter("no") %>">
        <input type = "hidden" name="pw" value="<%=request.getParameter("pw") %>">
        <input type = "hidden" name="mode" value="<%=request.getParameter("mode") %>">
    </form>
</body>
</html>
  • view.jsp에서 post로 보내줬는데 인코딩을 따로 명시하지 않은 이유는, 위 코드는 POST요청의 본문을 읽지 않고, URL의 쿼리 문자열에서 파라미터를 읽고있기 때문에 사용하지 않았다.
  • 해당 게시글의 비밀번호와 사용자가 입력한 비밀번호가 일치하는지 알기 위해, input type="hidden"으로 값을 받아와 다시 inputPasswordOK.jsp로 전송한다.

비밀번호 유효성 검사 - 삭제

  • html위에 jsp코드를 작성하여 변수를 선언하면 script코드를 head내부에 작성할 수 있고, jsp페이지 어디에서나 사용할 수 있다.
<%@page import="java.sql.*"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%
String pw = request.getParameter("pw");
String password = request.getParameter("password");
String no = request.getParameter("no");
String mode = request.getParameter("mode");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>비밀번호 확인</title>
<script>
    function goToLocation(no)
    {
        if(no==1){
            alert("데이터가 삭제 되었습니다");
            location.href = "list.jsp";            
        }
        else if(no==2){
            location.href = "modify.jsp?no=<%=no%> /* 수정하는 페이지로 이동 */
    ";
        } else if (no == 3) {
            alert("비밀번호가 일치하지 않습니다.");
            history.go(-2);
        }
    }
</script>
</head>
<body>
    <%
    String driver = "com.mysql.cj.jdbc.Driver";
    String url = "jdbc:mysql://localhost:3306/project?serverTimezone=UTC";
    String mysqlId = "root";
    String mysqlPw = "1234";

    String sql = null;

    try {
        Class.forName(driver);
    } catch (ClassNotFoundException e) {
        System.out.println("드라이버 로드 실패");
    }

    try (Connection conn = DriverManager.getConnection(url, mysqlId, mysqlPw); Statement stmt = conn.createStatement()) {
        if (pw.matches(password)) {
            if (mode.matches("1")) {
        sql = "DELETE FROM board where no = " + no;
        stmt.executeUpdate(sql);
            }
        } else
            mode = "3";
    } catch (SQLException e) {
        e.printStackTrace();
    }
    %>
    <script>
        goToLocation(
    <%=mode%>
        );
    </script>
</body>
</html>
  • Statement 는 정적인 SQL쿼리를 실행하는데 사용된다. createStatement()메소드를 이용해 생성하고, 파라미터가 없다.

  • PreparedStatement는 동적인 SQL쿼리를 실행하는 데 사용된다. PrepareStatement()메소드를 이용해 생성하며, SQL쿼리를 파라미터로 받는다. 물음표를 사용해 값을 동적으로 삽입해 실행할 수 있다.

  • location 객체는 javascript에서 제공하는 객체로, 웹 브라우저의 현재 URL에 대한 정보를 담아, 다른 URL로 리다이렉트 할 수 있다. window.location / document.location을 통해 접근할 수 있는데 window객체의 속성 중 하나이므로 location으로 바로 접근 가능하다.

  • history.go(-2)는 javascript의 history객체의 go()메소드를 호출하는 코드이다. history는 웹 브라우저의 세션 기록을 나타내며, go()메소드는 이 세션기록에서 특정 페이지를 로드하는데 사용된다. > 음수 값은 뒤로, 양수 값은 앞으로 이동한다.

수정하기 - modify

<%@page import="java.sql.*"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>수정하기</title>
<link rel="stylesheet" href="css/view.css">
</head>
<body>
<form method="post" action="modifyOK.jsp">
<table border="1">
    <caption>수정하기</caption>
<%
    String no = request.getParameter("no");

    String driver = "com.mysql.cj.jdbc.Driver";
    String url = "jdbc:mysql://localhost:3306/project?serverTimezone=UTC";
    String mysqlId = "root";
    String mysqlPw = "1234";
    String pw = null;
    String sql = "SELECT title, name, wTime, contents, password FROM board where no =" + no;

    try{
        Class.forName(driver);
    } catch(ClassNotFoundException e){
        System.out.println("드라이버 로드 실패");
    }

    try( Connection conn = DriverManager.getConnection(url, mysqlId, mysqlPw);
            Statement stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery(sql) ){
        if(rs.next()){
            pw = rs.getString("password");
%>
    <tr>
        <td>제목</td><td><input type="text" name="title" value='<%=rs.getString("title") %>'></td>
    </tr>
    <tr>
        <td>이름</td><td><%=rs.getString("name") %></td>
    </tr>
    <tr>
        <td>작성일</td><td><%=rs.getString("wTime") %></td>
    </tr>
    <tr>
        <td colspan="2"><textarea name="contents" cols="50" rows="10" style="resize: none;"><%=rs.getString("contents") %></textarea></td>
    </tr>

<%    
        }
    }  catch(SQLException e){
        e.printStackTrace();
    }        
%>        
</table>
<input type="hidden" name="no" value="<%=no %>">
<a href="list.jsp"><input type="button" value="목록"></a> 
<input type="submit" value="등록">
</form>
</body>
</html>
  • 이미 정해진 sql이 있기 때문에 Statement 객체로 createStatement()메소드를 이용해 정적 sql쿼리 실행

modifyOK

<%@page import="java.sql.*"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%
    request.setCharacterEncoding("UTF-8");
    String no = request.getParameter("no");
    String title = request.getParameter("title");
    String contents = request.getParameter("contents");
    String driver = "com.mysql.cj.jdbc.Driver";
    String url = "jdbc:mysql://localhost:3306/project?serverTimezone=UTC";
    String mysqlId = "root";
    String mysqlPw = "1234";
    String sql = "UPDATE board SET title=?, contents=?, wTime=now() WHERE no = ?";    

    int result = 0;

    try{
        Class.forName(driver);
    } catch(ClassNotFoundException e){
        e.printStackTrace();
    }
    try(Connection conn = DriverManager.getConnection(url, mysqlId, mysqlPw);
            PreparedStatement pstmt = conn.prepareStatement(sql)){
        pstmt.setString(1, title);
        pstmt.setString(2, contents);
        pstmt.setInt(3, Integer.parseInt(no));
        result = pstmt.executeUpdate();
        if(result > 0) response.sendRedirect("list.jsp");
        else response.sendRedirect("error.jsp");
    }  catch(SQLException e){
        e.printStackTrace();
    }
%>

에러

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="description" content="HTML Study">
<meta name="keywords" content="HTML,CSS,XML,JavaScript">
<meta name="author" content="Bruce">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>에러</title>
</head>
<body>
에러
</body>
</html>

js는 클라이언트에서 돌아가는 것이고, jsp는 서버에서 돌아가는 방식이다.

JDBC SQL쿼리 실행 메소드

  1. Statement : 문자열 기반의 sql쿼리를 실행하는 데 사용된다. Statement 객체createStatement() 메소드를 통해 생성된다. 주로 정적 SQL문을 실행할 때 사용된다.

  2. PreparedStatement : 매개변수화된 SQL쿼리를 실행하는 데 사용된다. SQL문을 인자로 물음표를 이용해 받는다. 주로 동적 SQL문을 실행할 때 사용되며, 쿼리가 미리 컴파일 되므로 반복적인 실행에 대한 성능이 향상된다.

  3. executeQuery() : SQL에서 SELECT문을 실행하는데 사용된다. 쿼리를 실행한 후 결과를 담은 ResultSet 객체를 반환한다. > 이를 통해 각 행의 데이터에 접근할 수 있다.

  4. executeUpdate() : SQL에서 INSERT, UPDATE, DELETE등과 같은 DML문, DDL문 등을 실행하는데 사용된다. 쿼리를 실행한 후 영향 받은 행의 수를 나타내는 int값을 반환한다.

0개의 댓글