글검색() 의 결과가 저장된 boards 를 setAttribute 하여 dispatcher 를 이용해 list페이지로 이동하게 한다.
글검색 된 boards 도 페이지처리가 적용되어야 하기 때문에 글개수(keyword) 함수를 오버로딩하여 새로 만들어야 한다.
BoardService.java
public List<Board> 글검색(String keyword, int page){
return boardDao.findByKeyword(keyword, page);
}
public int 글개수(String keyword) {
return boardDao.count(keyword);
}
BoardDao.java
public List<Board> findByKeyword(String keyword, int page){
String sql = "SELECT * FROM board WHERE title like ? ORDER BY id DESC LIMIT ?, 4"; // 0,4 4,4 8,4
Connection conn = DB.getConnection();
PreparedStatement pstmt = null;
ResultSet rs = null;
List<Board> boards = new ArrayList<>();
try {
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "%"+keyword+"%");
pstmt.setInt(2, page*4); // 0 -> 0, 1 ->4, 2->8
rs = pstmt.executeQuery();
// Persistence API
while(rs.next()) { // 커서를 이동하는 함수
Board board = Board.builder()
.id(rs.getInt("id"))
.title(rs.getString("title"))
.content(rs.getString("content"))
.readCount(rs.getInt("readCount"))
.userId(rs.getInt("userId"))
.createDate(rs.getTimestamp("createDate"))
.build();
boards.add(board);
}
return boards;
} catch (Exception e) {
e.printStackTrace();
} finally { // 무조건 실행
DB.close(conn, pstmt, rs);
}
return null;
}
public int count(String keyword) {
String sql = "SELECT count(*) FROM board WHERE title like ?";
Connection conn = DB.getConnection();
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "%"+keyword+"%");
rs = pstmt.executeQuery();
if(rs.next()) {
return rs.getInt(1);
}
} catch (Exception e) {
e.printStackTrace();
} finally { // 무조건 실행
DB.close(conn, pstmt, rs);
}
return -1;
}
public int deleteById(int id) { // 회원가입
String sql = "DELETE FROM board WHERE id = ?";
Connection conn = DB.getConnection();
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, id);
int result = pstmt.executeUpdate();
return result;
} catch (Exception e) {
e.printStackTrace();
} finally { // 무조건 실행
DB.close(conn, pstmt);
}
return -1;
}
BoardService.java
public int 글삭제(int id) {
return boardDao.deleteById(id);
}
CommonRespDto.java
모든 요청,응답을 이 통합Dto 하나로 관리합니다.
제네릭을 사용하네요.
package com.cos.blog.domain.board.dto;
import lombok.Data;
@Data
public class CommonRespDto<T> {
private int statusCode; // 1, -1
private T data;
}
BoardController.java
else if(cmd.equals("delete")) {
int id = Integer.parseInt(request.getParameter("id"));
// DB에서 id값으로 글 삭제
int result = boardService.글삭제(id);
// 응답할 json 데이터를 생성
CommonRespDto<String> commonRespDto = new CommonRespDto<>();
commonRespDto.setStatusCode(result);
commonRespDto.setData("성공");
Gson gson = new Gson();
String respData = gson.toJson(commonRespDto);
System.out.println("respData : "+respData);
PrintWriter out = response.getWriter();
out.print(respData);
out.flush();
}
CommonRespDto 는 알아두면 편리한데 제가 아직 개념정리가 덜되어있어서 설명이 어렵습니다.
원래 지원하던 다음블로그 ? 에디터가 좋았는데 Flash 가 2021년에 지원중단되면서 티스토리가 지원하는 신 에디터로 글을 써야하거든요
신 에디터 사진넣는거, 이건 좋ㄷ ㅏ이말이야. 근데 글자 폰트조절을 못하겠다는거 >> 화난다 .
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
글 목록 보기를 구현해봅시다.
'글 목록' 을 볼려면 글이 저장되어있는 데이터베이스를 Select 해야할것입니다.
데이터베이스가 어떻게 생겼었는지 다시 면상이나 한 번 보죠 ~
사실 제가 글쓰는 텀이 너무 길어서 까먹었습니다.
MySQL
create user 'bloguser'@'%' identified by '비밀번호';
GRANT ALL PRIVILEGES ON *.* TO 'bloguser'@'%';
create database blog;
use blog;
drop table user;
drop table board;
drop table reply;
CREATE TABLE user(
id int primary key auto_increment,
username varchar(100) not null unique,
password varchar(100) not null,
email varchar(100) not null,
address varchar(100),
userRole varchar(20),
createDate timestamp
) ;
CREATE TABLE board(
id int primary key auto_increment,
userId int,
title varchar(100) not null,
content longtext,
readCount int default 0,
createDate timestamp,
foreign key (userId) references user (id)
);
CREATE TABLE reply(
id int primary key auto_increment,
userId int,
boardId int,
content varchar(300) not null,
createDate timestamp,
foreign key (userId) references user (id) on delete set null,
foreign key (boardId) references board (id) on delete cascade
);
우리가 봐야할 데이터는 Board .
BoardDao.java
public List<Board> findAll(){
String sql = "SELECT * FROM board ORDER BY id DESC";
Connection conn = DB.getConnection();
PreparedStatement pstmt = null;
ResultSet rs = null;
List<Board> boards = new ArrayList<>();
try {
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
// Persistence API
while(rs.next()) { // 커서를 이동하는 함수
Board board = Board.builder()
.id(rs.getInt("id"))
.title(rs.getString("title"))
.content(rs.getString("content"))
.readCount(rs.getInt("readCount"))
.userId(rs.getInt("userId"))
.createDate(rs.getTimestamp("createDate"))
.build();
boards.add(board);
}
return boards;
} catch (Exception e) {
e.printStackTrace();
} finally { // 무조건 실행
DB.close(conn, pstmt, rs);
}
return null;
}
BoardDao에 findAll() 함수 추가.
DB에서 Board를 SELECT 해서 싸ㅡ악 가져오네요
BoardService.java
public List<Board> 글목록보기(){
return boardDao.findAll();
}
Ajax (Async Javascript And XML)는 웹 페이지에서 새로운 데이터를 보여주려고 할 때 웹페이지 전체를 새로고침 하지 않고, 보여주고자 하는 데이터가 포함된 페이지의 일부 만을 로드 하기 위한 기법입니다.
Ajax는 비동기 처리 모델 (또는 non-blocking 이라고도 함)을 사용하여 데이터를 처리합니다.
동기 처리 모델에서 브라우저는 자바스크립트 코드를 만나면 스크립트를 처리하기 전까지 다른 작업을 일시 중지하고, 자바스크립트 코드의 처리가 끝난 후 기존 작업을 진행합니다.
반면에 Ajax를 사용하면 브라우저는 서버에 데이터를 요청한 뒤 페이지의 나머지를 로드하고 페이지와 사용자의 상호작용을 처리합니다.
Ajax 동작방식
function usernameCheck(){
// DB에서 확인해서 username이 없다면 isChecking = true
var username = $("#username").val();
$.ajax({
type: "POST",
url: "/blog/user?cmd=usernameCheck",
data: username,
contentType: "text/plain; charset=utf-8",
dataType: "text" // 응답 받을 데이터의 타입을 적으면 자바스크립트 오브젝트로 파싱해줌.
}).done(function(data){
if(data === 'ok'){ // 유저네임 있다는 것
isChecking = false;
alert('유저네임이 중복되었습니다.')
}else{
isChecking = true;
$("#username").attr("readonly", "readonly");
alert("해당 유저네임을 사용할 수 있습니다.")
}
});
}
//UserController.java (Servlet)
else if(cmd.equals("usernameCheck")) { //유저네임 중복체크
BufferedReader br = request.getReader(); //input 에 입력된 username을 읽음
String username = br.readLine();
System.out.println(username);
//DB와 통신함 (service -> Dao)
//Dao 에서 Select 해보고 int 결과값을 리턴해줌. 있으면 1 없으면 not 1
int result = userService.유저네임중복체크(username);
PrintWriter out = response.getWriter();
if(result == 1) {
out.print("ok");
}else {
out.print("fail");
}
out.flush();
}
요청(request) - 브라우저가 서버에 정보를 요청한다. 바로 위에있는 JoinForm.jsp 에서 첫번째 Form의 중복검사 action이 usernameCheck() 함수를 가지고있는데, 그 함수는 파일 하단에. 자바스크립트 함수로 정의되어 있습니다.
이 함수가 JQuery를 이용한 Ajax 요청방법입니다. ( Web Front 에 입력된 데이터를 서버로 전송 ) type : 요청방식 (get, post, delete, put) // url : 요청주소 ( Controller 에서 Servlet이 처리함 )
data : 서버로 보낼 데이터. (위 함수에서는 var username = $("#username").val() 이 전송되는중)
contentType : 응답받을 데이터의 형태, 보통은 데이터를 처리하기위해 JSON 이겠지만 Controller의 결과값을 보면 ok , fail 의 단순 문자열이기때문에 text
응답에 성공을 한다면, done(function(data){ '대충 실행될 명령' } ) 분기로 가서 응답받은 데이터( data << Ajax 함수의 data 아님. Ajax의 결과값임 )로 해야할 일을 처리합니다. data를 result 로 바꾸는게 좀 보기 편할거같네요
서버의 동작 - 서버는 JSON, XML 등의 형식으로 데이터를 전달한다. 최근에는 JSON을 가장 많이 사용하고 있습니다.
package com.cos.blog.service;
import com.cos.blog.domain.user.User;
import com.cos.blog.domain.user.UserDao;
import com.cos.blog.domain.user.dto.JoinReqDto;
import com.cos.blog.domain.user.dto.LoginReqDto;
import com.cos.blog.domain.user.dto.UpdateReqDto;
public class UserService {
private UserDao userDao;
public UserService() {
userDao = new UserDao();
}
public int 회원가입(JoinReqDto dto) {
int result = userDao.save(dto);
return result;
}
public User 로그인(LoginReqDto dto) {
return userDao.findByUsernameAndPassword(dto);
}
public int 회원수정(UpdateReqDto dto) {
return -1;
}
public int 유저네임중복체크(String username) {
int result = userDao.findByUsername(username);
return result;
}
}
drop table user;
drop table board;
drop table reply;
CREATE TABLE user(
id int primary key auto_increment,
username varchar(100) not null unique,
password varchar(100) not null,
email varchar(100) not null,
address varchar(100),
userRole varchar(20),
createDate timestamp
) ;
CREATE TABLE board(
id int primary key auto_increment,
userId int,
title varchar(100) not null,
content longtext,
readCount int default 0,
createDate timestamp,
foreign key (userId) references user (id)
);
CREATE TABLE reply(
id int primary key auto_increment,
userId int,
boardId int,
content varchar(300) not null,
createDate timestamp,
foreign key (userId) references user (id) on delete set null,
foreign key (boardId) references board (id) on delete cascade
);