BASHA TECH

ch10 본문

Computer/JSP

ch10

Basha 2022. 9. 1. 16:59
728x90

sql

CREATE TABLE news (
	  newsid NUMBER PRIMARY KEY
	, title  VARCHAR2(100) NOT NULL
	, img 	 VARCHAR2(300)
	, regdate DATE DEFAULT SYSDATE -- news 등록일
	, content VARCHAR2(2000) NOT NULL
);

DROP TABLE news;

INSERT INTO news(newsid, title, img, content)
VALUES(	(SELECT NVL(MAX(newsid)+1,1) FROM news)
			 , 'test'
			 , 'test'
			 , 'test'
);

SELECT  newsid
			, title
			, TO_CHAR(regdate, 'YYYY-MM-DD HH24:mm:ss') AS regdate
	FROM news;

-- 상세
SELECT  a.NEWSID
			, a.TITLE
			, TO_CHAR(a.regdate, 'YYYY-MM-DD HH24:mm:ss') AS regdate
			, a.CONTENT
   FROM NEWS a
	WHERE a.NEWSID =: newid -- =: 가변 데이터 입력할 때 사용 db에서 테스트할 때 사용함
;

 

참고: 

java단과 wep단

> Java단

jwbook/main/java/kr.co.big15/news/controller/NewsController.java

package kr.co.big15.news.controller;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import kr.co.big15.news.dto.NewsDto;
import kr.co.big15.news.model.NewsDao;

//annotation이 자바 코드로 바뀜.
@WebServlet("/news.nhn")
@MultipartConfig(maxFileSize = 1024*1024 * 2, location = "c:/Temp/img" ) //@MultipartConfig: 파일 업로드 처리하는 애
public class NewsController extends HttpServlet {
	private static final long serialVersionUID = 1L;
    
	private NewsDao dao;
	private ServletContext ctx; //ServletContext: 요청 들어온 걸 다 받아줌. 서블릿 컨테이너임. 
	
//	웹 리소스 기본 경로 지정
	private final String START_PAGE = "news.nhn?action=listNews";
	//init을 쓰는 이유 생성자 호출이 안됨.
	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config); //super는 HTTPServlet임 여기를 초기화 하겠다는 것
		dao = new NewsDao();
		ctx = super.getServletContext(); //Httpt서블릿안에 있음 그래서 상속 받을 수 있다. => overriding
	}
	// 얘도 실행은 서블릿 컨테이너가 함
	@Override
	protected void service(HttpServletRequest req
			, HttpServletResponse resp) throws ServletException, IOException {
	//	request의 한글 처리 = > utf-8 : 첫째 줄에 있어야함
		req.setCharacterEncoding("utf-8");
		String action = req.getParameter("action");
		
	//	dao = new NewsDao(); 필요 없다. 위에 선언되어잇음 중복됨
		Method method;
		String view = "null";
		
		if(action == null) {
			action = "listNews"; //listNews가 메소드 이름이 됨
		} 
		try {
			method = this.getClass().getMethod(action, HttpServletRequest.class); //NewsController class를 가져오는 코드임 => 코드양이 많이 주는 좋은 코드다
//			m.invoke => 해당 메소드 실행
			view = (String)method.invoke(this, req); //this가 들어간다는 것 멤버 변수 접근을 가능하게 한다.
		} catch (Exception e) { //NoSuchException : 네가 부른 메소드가 없다
//			e.printStackTrace();
			req.setAttribute("error", "action 파라미터가 잘못 되었습니다.");
			view = START_PAGE;
		}
//		Post 요청에서는 리디렉션 방법으로 이동하도록 분기
//		redirect:/view => view만 남기고 얘 가지고만 redirect 처리 하겠다는 얘기
		if(view.startsWith("redirect:/")) {//시작하는 문자열
			String rview = view.substring("redirect:/".length()); //redirect의 length부터 가져와라 index는 0부터 length는 1부터
			resp.sendRedirect(rview); //양식 다시 제출 확인이라는 창이 뜨게 함. 핵심 redirect해야한다는 것. url을 알아야함. 그럴려면
//url에 redirect가 추가되면서 view가 들어와서 다시 제출하라는 요청이 뜨게 함. = > 이때 다시 제출하면 안되니까 억지로 view로 redirect하라는 뜻
//안되면 forwarding 해야함
		} else {
			RequestDispatcher disp = req.getRequestDispatcher(view);
			disp.forward(req, resp);
		}
	}

//	뉴스 목록 처리 메소드
	public String listNews(HttpServletRequest request) {
		List<NewsDto> list = null; //alt+shift+o
		
		try {
			list = dao.select();
			request.setAttribute("listNews", list);
		} catch (Exception e) {
			e.printStackTrace(); // 에러 추적해서 출력해주는 것. 개발 시 적용했다가 실제 운용시에는 제거해야함
			request.setAttribute("error", "뉴스 목록이 정상적으로 처리되지 않았습니다.");
		}
		return "news/listNews.jsp"; //이건 웹상 경로임
	}
}

jwbook/main/java/kr.co.big15/news/dto>NewsDto.java

package kr.co.big15.news.dto;

public class NewsDto {
	private int newsid;
	private String title;
	private String img;
	private String regdate;
	private String content;
	public int getNewsid() {
		return newsid;
	}
	public void setNewsid(int newsid) {
		this.newsid = newsid;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getImg() {
		return img;
	}
	public void setImg(String img) {
		this.img = img;
	}
	public String getRegdate() {
		return regdate;
	}
	public void setRegdate(String regdate) {
		this.regdate = regdate;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	//alt+ s+s+s
	@Override
	public String toString() {
		return "NewsDto [newsid=" + newsid + ", title=" + title + ", img=" + img + ", regdate=" + regdate + ", content="
				+ content + "]";
	}
	
	
}

jwbook/main/java/kr.co.big15/news/model/NewDao.java

package kr.co.big15.news.model;

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 javax.naming.spi.DirStateFactory.Result;

import kr.co.big15.news.dto.NewsDto;

public class NewsDao {
	public static Connection getConnection() {
		Connection conn 		= null;
		String driver 		= "oracle.jdbc.driver.OracleDriver";
		String url 			= "jdbc:oracle:thin:@localhost:1521:xe";
		String userid 		= "ora_user";
		String userpassword = "hong";
	
		try {
			Class.forName(driver);
			conn = DriverManager.getConnection(url, userid, userpassword);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return conn;
		
	}

	public static void close(Connection conn, PreparedStatement pstmt) {
		try {
			pstmt.close();
			conn.close();
		}catch(SQLException e) {
			e.printStackTrace();
		}
	}
	
//	위에 있는 close랑 뭐가 다른 걸까? ? ? 
	public static void close(Connection conn, PreparedStatement pstmt, ResultSet rs) {
		try {
			conn.close();
			rs.close();
			pstmt.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
	}
	
//	뉴스 추가 => insert => int
	public void addNews(NewsDto newsDto) { //throws Exception=> 안에서 에러나면 던진다는 것. 컨트롤러에서 에러를 해결을 해야함.
		// 따라서 에러난 곳에서 해결하는 것이 좋다.
		Connection conn 		= getConnection();
		PreparedStatement pstmt = null; //웬만하면 connection뒤에 선언을 해주는 것이 맞다
		
		StringBuilder sql = new StringBuilder();
		sql.append("insert into news(newsid, title, img, content)");
		sql.append("values((select nvl(max()+1,1) from news), 	 ");
		sql.append("?,?,?)	 	 						 	     ");
		
		try {
			pstmt = conn.prepareStatement(sql.toString()); //conn.preparedStatement~부터 처리 한다. 예외일 땐, catch로 빠져나감. 따라서 pstmt 자체가 아예 선언이 되지 않을 수 있다. //따라서 pstmt부터 선언을 밖에서 해줘야함.
			pstmt.setString(1, newsDto.getTitle());
			pstmt.setString(2, newsDto.getImg());
			pstmt.setString(3, newsDto.getContent());
			
			pstmt.executeUpdate();
			
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			close(conn, pstmt);
		}
	}
	
//	뉴스 전체 목록 추출 => select all
	public ArrayList<NewsDto> select() throws Exception {
		Connection conn 		= null;
		PreparedStatement pstmt = null;
		ResultSet rs 			= null;
		
		ArrayList<NewsDto> newsArr = new ArrayList<>();
//		처리 코드
		StringBuilder sql = new StringBuilder();
		sql.append("SELECT  newsid										  		");
		sql.append("	  , title												");
		sql.append("	  , TO_CHAR(regdate, 'YYYY-MM-DD HH24:mm:ss') AS regdate");
		sql.append("  FROM news											  		");

//		try(conn;pstmt;rs){ //이렇게 쓰면 안에서 정상적인 처리가 끝나면 } finally {close(conn, pstmt);}를 안 쳐도 자동으로 종료 됨
		try {
			conn  = getConnection();
			pstmt = conn.prepareStatement(sql.toString());
			rs 	  = pstmt.executeQuery();
			
			while(rs.next()) {
				NewsDto n = new NewsDto();
				n.setNewsid(rs.getInt("newsid"));
				n.setTitle(rs.getString("title"));
				n.setRegdate(rs.getString("regdate"));
				
				newsArr.add(n);
			}
		} catch (Exception e) {
			
		}
		return newsArr;
	}
// 뉴스 상세 추출 = > select where newsid =?
	public NewsDto select(int newsid) {
		Connection conn 		= null;
		PreparedStatement pstmt = null;
		ResultSet rs 			= null;
		
		NewsDto newsDto = new NewsDto();
//		처리 코드
		StringBuilder sql = new StringBuilder();
		sql.append("SELECT  a.NEWSID											  ");
		sql.append("	  , a.TITLE												  ");
		sql.append("	  , TO_CHAR(a.regdate, 'YYYY-MM-DD HH24:mm:ss') AS regdate");
		sql.append("	  , a.CONTENT											  ");
		sql.append("   FROM NEWS a												  ");
		sql.append("  WHERE a.NEWSID = ?										  ");
		
		try {
			conn = getConnection();
			pstmt = conn.prepareStatement(sql.toString());
			pstmt.setInt(1, newsid);
			rs = pstmt.executeQuery();

			if(rs.next()) {
				newsDto.setNewsid(rs.getInt("newsid"));
				newsDto.setTitle(rs.getString("title"));
				newsDto.setImg(rs.getString("img"));
				newsDto.setRegdate(rs.getString("regdate"));
				newsDto.setContent(rs.getString("content"));
				
			} else {
				System.out.println("해당 뉴스가 없다!!!");
			}
			
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			close(conn, pstmt, rs);
		}
		
		return newsDto;
	}
	
//	
//	뉴스 제목 검색 추출 = > select where 검색 제목
	public ArrayList<NewsDto> select(String title) {
		ArrayList<NewsDto> newsArr = new ArrayList<>();

//		****** 처리 코드

		return newsArr;
	}

//	뉴스 삭제 = > delete where newsid = ?
	public void delete(int newsid) {
		Connection conn   		= null;
		PreparedStatement pstmt = null;
		
		String sql = "delete news where newsid = ?";
		
		try {
			conn = getConnection();
			pstmt = conn.prepareStatement(sql.toString());
			
			pstmt.setInt(1, newsid);
			if(pstmt.executeUpdate() == 0) {
				//insert, updat, del은 int값으로 나오는 데 결과 값이 0이다. => 삭제된 것이 없다
				System.out.println("삭제된 뉴스가 없다.");
			}

		} catch (SQLException e) {
			e.printStackTrace();
		}
				
	}
}

jwbook/main/java/kr.co.big15/news/service

여기서는 안 만들었지만 현장 가면 만들 가능성 ↑

 

> web단

jwbook/main/webapp/news/listNews.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">
<title>뉴스 관리 앱</title>
<!--https://www.w3schools.com/bootstrap5/bootstrap_get_started.php 여기 MaxCDN 복붙 -->
<!-- Latest compiled and minified CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Latest compiled JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>

</head>
<body>
	<div class="container w-75 mt-5 mx-auto">
	<h2>뉴스 목록</h2>
	<hr>
	<ul class="list-group">
		<c:forEach items="${listNews }" var="news" varStatus="status">
			<li class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
				<a href="news_nhn?action=getNews&newsid=${news.newsid } class="text=decoration-none">
					[${status.count}] [${news.title}] [${news.regdate}]
				</a>
				<a href="news.nhn?action=deleteNews&newsid=${news.newsid }">
					<span class="badge bg-secondary">&times;</span>
				</a>
			</li>
		</c:forEach>
	</ul>	
	<hr>
	<c:if test="${error != null }">
		<div class="alert alert-danger alert-dismissible fade show mt-3">
		에러 발생 : ${error}
		<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
		</div>
	</c:if>
	<!-- 에러 처리 끝 -->
	<!-- 뉴스 등록 시작 -->
	<button class="btn btn-outline-info mb-3" type="button" data-bs-toggle="collapse" 
	data-bs-target="#addForm" aria-controls="addForm" aria-expanded="false">
	뉴스 등록 
	</button>
	<!--<input type="button" value="뉴스 등록">-->
	<div class = "collapse" id="addForm">
		<div class="card card-body">
			<form action="/jwbook/news.nhn?action=addNews" method="post" enctype="multipart/form-data">
			<label class="form-label">제목</label>
				<input type = "text" name="title" class="form-control">
			<label class="form-label">이미지</label>
			<	input type = "file" name="file" class="form-control">
			<label class="form-label">기사 내용</label>
				<textarea rows="5" cols="50" class="form-control"></textarea>
			<button type="sumit" class="btn btn-success mt-3">저장</button>
			</form>
		</div>
	</div>
	
	<!-- 뉴스 등록 끝 -->
	
	</div>
</body>
</html>
728x90
반응형

'Computer > JSP' 카테고리의 다른 글

startsWith/endsWith 특정 문자로 시작하거나 끝나는지 체크  (0) 2022.09.01
annotation이 java코드로 바뀌는 원리  (0) 2022.09.01
ch09  (0) 2022.08.31
JSP 목차  (0) 2022.08.30
ch08  (0) 2022.08.30
Comments