앞서 작성했던 게시판 페이지이다.

 

이번 포스팅에서 구현할 기능은 아래와 같다.

 

1. 글쓰기를 누르면 글쓰기 페이지로 넘어감

2. 글쓰기 페이지에서 제목과 내용 등을 입력하여 submit해주면 db에 입력이 됨

3. 리스트 페이지로 리다이렉트로 되어 업데이트된 페이지를 보여줌

 

1. 글쓰기 JSP파일 만들기

 

list.jsp와 같은 경로에 writeForm.jsp를 만들어 아래와 같이 코딩을 해준다.

 

writeForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
    
<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
</head>
<body>
<div align="center">
	<h2>글쓰기 페이지</h2>
	<hr width="500" />
	<table width="500" cellpadding="0" cellspacing="0" border="1">
		<form:form commandName="_BVO" action="writeOK" method="post">
			<tr>
				<td>작성자</td>
				<td><form:input path="bName" size="20" /></td>
			</tr>
			<tr>
				<td>제목</td>
				<td><form:input path="bSubject" size="50" /></td>
			</tr>
			<tr>
				<td>내용</td>
				<td><form:textarea path="bContent" cols="60" rows="8" /></td>
			</tr>
			<tr>
				<td colspan="2" align="center"><input type="submit" value="등록" /></td>
			</tr>
		</form:form>
	
	</table>
</div>

</body>
</html>

아까는 prefix="c"를 사용하였지만 여기에서는 태그라이브러리 prefix="form"을 사용하였다. 

 

<form:form> 태그안에 commandName은 modelAttribute로 바꾸어 사용해도 된다. 컨트롤러에서 BVO()를 리턴하게끔 모델을 정해주는 역할이다.

 

그리고 action은 어떤 url로 이동할지 정해주고, 이를 컨트롤러에서 받아와서 처리해준다.

method는 post이다.

 

그리고 <form:input>태그안에는 path 구문을 넣어 입력값이 어떤 객체로 들어갈 것인지 정해준다.

 

2. VO 작성

VO는 한번 작성하면 db의 항목이 변동되지 않는 이상 바꾸는 경우는 잘 없다.

아까 변수 선언 구문 아래에 주석 처리 되있었던  public BVO() { }만 주석을 해제해준다.

 

3. Controller 작성

여기서 작성해야 될 것은 2가지 메소드이다.

하나는 글쓰기 작성 jsp파일로 이동시키는 writeForm() 메소드이고, 하나는 글쓰기 form을 submit했을 때 처리되게끔 하는 writeOk()메소드이다.

 

구문에 대한 상세설명은 주석에 적어 놓았다.

 

Bcontroller.java

package com.spring.bbsController;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

import com.spring.bbsCommand.Bcmd;
import com.spring.bbsCommand.ListCmd;
import com.spring.bbsCommand.WriteCmd;
//import com.spring.bbsCommand.WriteCmd;
import com.spring.bbsVO.BVO;

@Controller
public class BController {
	Bcmd cmd = null; //Bcmd 인터페이스를 불러와서 cmd에 저장해준다.

	
	@RequestMapping("/list")
	public String list(Model model) {
		//String으로 list 메소드를 생성했으니 리턴값도 String이다. RequestMapping의 아래는 대부분 String메소드이다.
		//파라미터형태로 모델 생성
		//모델의 역할은 뷰에게 데이터를 전달하기 위한 객체
		//여기서는 모델활용안하고 Bcmd.class에서 모델을 활용함.
		
		System.out.println("------------------list() 호출-------------");//에러날때를 대비해서 써줌
		//Model은 뷰에 데이터를 전달하기 위한 방법
		cmd = new ListCmd(); 	//Bcmd 인터페이스를 가져온 녀석에다 ListCmd()를 넣어줌
		//위에서 Bcmd cmd = null;을 안해주고 곧바로 이것을 해줘도 되지만 의존성을 낮추기 위해서 이렇게 해줌
		
		cmd.service(model);	//모델을 인자로 넘겨줌. 서비스를 시행
		
		return "list";
	}
	
	
	@RequestMapping("/writeForm")
	public String writeForm(Model model) {
		System.out.println("----------writeForm() 호출----------");
		
		return "writeForm";
	}
//	
//	//write폼 >>BController >> WriteCmd로 전달
	@RequestMapping("/writeOK")
	public String writeOk(HttpServletRequest request, Model model) {
		//데이터를 컨트롤러로 보냈을때, HttpServletRequest 객체안에 모든 데이터들이 들어가게 된다. 출처: https://hongku.tistory.com/118
		//String id = httpServletRequest.getParameter("id"); <<id를 불러옴
		
		System.out.println("----------writeOk() 호출-------------");
		
		model.addAttribute("request_ctrl", request); //이 request값에 formWrite에서 적었던 내용이 들어있음
		
		//서비스객체 불러옴
		cmd = new WriteCmd();
		cmd.service(model);
		
		return "redirect:list"; //등록한글을 리스트로 보여줌
	}
	
	//commandName="_BVO"와 관계 있음
	@ModelAttribute("_BVO") 
	public BVO formBacking() {
		
		return new BVO(); //BVO 안에 빈메소드로 연결됨
	}
}

 

/writeOK 리퀘스트 매핑에서는 HttpServletRequest라는 객체가 새로 생겼다.

 

그 이유는 /writeOK는 페이지를 보여주는 것이 아닌 form에서 submit된 데이터를 처리하는 용도이기 때문이다.

 

writeForm.jsp에서 submit하면 맨 끝 주소가 /writeForm에서 /writeOk로 주소가 변경되며, 컨트롤러에선 이를 받아온다.

이 때, 데이터들이 HttpServletRequest의 request안에 저장된다.

 

이 저장된 정보들을 꺼내오면 되는 것이다.

 

컨트롤러에서는 modelAttribute까지만 해주고, 데이터 저장 작업은 Service 클래스에서 해준다.

 

4. Service 작성

request에 모델 형태로 저장되었지만 이를 맵형태(키, 밸류)로 저장해준다.

 

위에서 모델을 잡아줄 때 왜 request_ctrl로 명했냐면, 그냥 request라고 할 경우 이것이 어디서 왔는지 헷갈린다.

 

실무에서야 그냥 쓰면 된다지만, 배우는 사람 입장에서는 이것이 어디서 왔는지 명확히 짚고 넘어가는 것이 중요하다.

 

블로그나 책에 req라고 나왔다고 그대로 req라고 쓰고 con이라고 나왔다고 con이라고 쓰는 것이 아니라 이것이 무엇을 의미하고 어느 클래스에서 왔는지, 또 내가 지정한 임의의 이름으로 넣었을 때 실행되는지 실험하면서 진행해가는 것이 실력향상에 도움이 된다.

 

WriteCmd.java

package com.spring.bbsCommand;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.ui.Model;

import com.spring.bbsDAO.BDAO;

public class WriteCmd implements Bcmd {

	@Override
	public void service(Model model) {
		
		System.out.println("model: "+model);
		//모델의 정보 model: {_BVO=com.spring.bbsVO.BVO@788ca69c, request_ctrl=org.apache.catalina.connector.RequestFacade@764b47fd}
		//아까 컨트롤러에서 정의해줬던 모델명 request_ctrl를 그대로 가져오는 것을 볼수 있다.
		
		Map<String, Object> map = model.asMap(); //모델객체를 맵으로 받음. 해쉬맵을 사용해도 무방
		//_BVO
		
		HttpServletRequest request = (HttpServletRequest)map.get("request_ctrl");		
		//map에 저장된 request_ctrl의 밸류값을 request에 저장
		//request_ctrl은 컨트롤러에서 모델어트리뷰트 해준 것임
		
		
		String bName = request.getParameter("bName");
		String bSubject = request.getParameter("bSubject");
		String bContent = request.getParameter("bContent");
		
		//db접속
		BDAO dao = new BDAO();
		dao.write(bName, bSubject, bContent);
	}
}

 

request에서 getParameter로 값을 가져와서 원하는 객체에 저장해준다.

 

그 다음 DAO클래스에서 write()메소드를 작성해준다.

 

5. DAO 작성

 

굳이 Controller > Service > DAO 순서대로 작성안하고 취향대로 작성해도 된다.

 

리스트 페이지를 만들 때는 DAO > Service > Controller 순으로 작성했지만 이번에는 반대로 한 이유는 어떤 순서로 보는 것이 이해하기 쉽고 내가 코드를 직접 작성할 때 좀 편할지 간접적으로 체험하라는 뜻도 있다.

 

점진적 구체화라는 용어가 있듯이 대개의 경우에는 VO > Controller > Service > DAO 순서가 편하다.

 

그럼 다시 돌아와서 write()메소드를 작성해본다.

 

윗코드내용은 아까 작성했던 부분이므로 write()메소드 시작부터 보면된다.

 

BDAO.java

package com.spring.bbsDAO;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;

//import javax.activation.DataSource; 액티베이션 아님
import javax.naming.Context; //JNDI
import javax.naming.InitialContext; //JNDI
import javax.naming.NamingException; //JNDI
import javax.sql.DataSource;

import com.spring.bbsVO.BVO;

public class BDAO {
	DataSource dataSource; //데이타소스를 가져오는 구문
	
	//생성자
	public BDAO() {
		//JNDI 를 사용한다. JNDI란 자바에서 객체를 네이밍 서비스에 등록, 삭제, 검색을 할 수 있는 방법
		
		try{
			
			Context ctx = new InitialContext(); //JNDI 네이밍 서비스 컴파일해줌
			dataSource = (DataSource)ctx.lookup("java:comp/env/jdbc/Oracle11g");
			//lookup으로 데이타소스의 객체를 얻어온다. java:comp/env/는 기본이며 그뒤의 이름은 톰캣서버 context.xml의 name을 참조한다.
			
	} catch(NamingException e) {
		e.printStackTrace();
	}
		
}
	//리스트 보여주기 위한 메소드 list()
	public ArrayList<BVO> list() {
		//DB에 있는 글목록들을 가져오는 역할 형식은 ArrayList이고 BVO타입. 칼럼정보가 BVO에 있다.
		
		ArrayList<BVO> bVOs = new ArrayList<BVO>(); //ArrayList형태의 bVOs 객체 생성
		
		//////연결을 위한 3구문/////
		Connection connection = null; //커넥션 javax
		PreparedStatement preparedStatement = null; //프리패어드 스테이트먼트 javax		
		ResultSet resultSet = null;  //데이터를 가져오는 기능의 리절트셋 javax
		//////////////
		
		
		try {
		connection = dataSource.getConnection();
		
		
		
		//쿼리문을 만들어줌
		String sql = "select bNo, bName, bSubject, bContent, bDate, bHit, bGroup, bStep, bIndent from mvc_bbs"
					+ " order by bGroup desc, bStep asc";
		
		
		preparedStatement = connection.prepareStatement(sql); //preparedStatement에 전송
		
		resultSet = preparedStatement.executeQuery(); //result값 데이터를 가져오는 것
		
		while(resultSet.next()) {
			//Resultset 다음행에 데이터가 있으면 while 문으로 반복 작업을 함		
			
			//vo의 9인자를 참조해서 작성
			int bNo = resultSet.getInt("bNo");
			String bName = resultSet.getString("bName");
			String bSubject = resultSet.getString("bSubject");
			String bContent = resultSet.getString("bContent");
			Timestamp bDate = resultSet.getTimestamp("bDate");
			
			int bHit = resultSet.getInt("bHit");
			int bGroup = resultSet.getInt("bgroup");
			int bStep = resultSet.getInt("bStep");
			int bIndent = resultSet.getInt("bIndent");
			///////
			
			//인자생성자
			BVO bVO = new BVO(bNo, bName, bSubject, bContent, bDate, bHit, bGroup, bStep, bIndent);
			
			bVOs.add(bVO); //bVOs라는 어레이에 bVO 추가함
		}
		

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			
			//finally 안에 있는 구문
			try {
				//null이면 구문들을 다 안쓰는 것
				if(resultSet !=null) {resultSet.close();}
				if(preparedStatement != null) {preparedStatement.close();}
				if(connection != null) {connection.close();}
				
			} catch (Exception e2) {	
				e2.printStackTrace();
			}
	
		}
		
		return bVOs;	
	}//list() 메소드 종료
	
	
	
	//write() 메소드 시작
	public void write(String bName, String bSubject, String bContent) {
		//글쓴이, 글제목, 글내용을 인자로 써줌.
		
		Connection connection = null;
		PreparedStatement preparedStatement = null;
		
		try {
			connection = dataSource.getConnection();
			System.out.println("---------Connection 확보 -----------");
			
			String sql = "insert into mvc_bbs(bNo, bName, bSubject, bContent, bHit, bGroup, bStep, bIndent) " 
			+ "values(seq_bbs.nextval, ?, ?, ?,0,seq_bbs.currval,0,0)";
			//? 밸류는 사용자가 넣어줘야 될 것임. ?가 아닌 다른것을 쓰면 작동이 안된다. 공란도 안된다.
			
			preparedStatement = connection.prepareStatement(sql);
			
			preparedStatement.setString(1, bName); //첫번째 들어갈값 bName
			preparedStatement.setString(2, bSubject); //두번째 들어갈값 bSubject
			preparedStatement.setString(3, bContent); //세번째 들어갈값 bContent
			
			int n = preparedStatement.executeUpdate(); //select문은 executeQuery(), Update문은 executeUpdate()
			//변수n이 아닌 아무거나 써도 된다.
            
		} catch(SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if(preparedStatement != null) {preparedStatement.close();}
				if(connection != null) {connection.close();}
				
			} catch(Exception e2) {
				e2.printStackTrace();
			}	
		}
		
	}//write
	
}

 

그럼 이제 글작성 기능이 끝났다.

 

부가적으로 회원가입기능, 글에 비번넣기 기능도 추가할 수 있지만 우선은 CRUD 기본만 하도록 한다.

 

여기까지 실습한 내용은 첨부파일에 올려놓았다.

CRUD(글작성 까지).zip
0.03MB

아래는 서버폴더의 context.xml과 server.xml파일

서버와 콘텍스트 파일.zip
0.00MB

앞서 만들었던 게시판 리스트이다. (현재는 글쓰기 안됨)

 

백단의 DAO, VO, Service, Controller와 프론트단의 list.jsp가 어떻게 유기적으로 소통하는지 살펴본다.

"<-----화살표로 끊어지는 로직을 설명해놓았다.

 

여기 코딩 들은 단순 설명용 코딩이니 복붙해서 실행해도 안먹는다.

 

 

1-1. Controller // 리퀘스트 맵핑

주소창에 localhost:8080/list라고 입력하면 디스패처가 컨트롤러로 전달해준다.

Bcontroller에서 일련의 과정을 처리한다.

 

Bcontroller.java

@RequestMapping("/list")

public String list(Model model) {

cmd = new ListCmd(); <-------여기서 Service 클래스를 참조한다.

/*
cmd.service(model); 

return "list";



}
*/

 

2-1. Service //  DAO 참조

ListCmd는 Bcmd 인터페이스를 참조하지만 Bcmd 없이 ListCmd로 만들어줘도 된다. 

 

ListCmd.java

public class ListCmd implements Bcmd {

	@Override
	public void service(Model model) {
		
		BDAO dao =new BDAO(); <------------여기서 DAO클래스를 참조한다.
      	
        
/*        
        
        ArrayList<BVO> bVOs = dao.list(); 

		model.addAttribute("list", bVOs);
	}

}
*/

 

3-1. DAO // JNDI 네이밍을 이용하여 오라클 Lookup

실재로 SQL문을 데이터베이스에서 실행시키게끔 하는 클래스이다. 객체는 VO에서 참조한다.

 

BDAO.java

public class BDAO {
	DataSource dataSource; //데이타소스를 가져오는 구문
	
	//생성자
	public BDAO() {
		//JNDI 를 사용한다. JNDI란 자바에서 객체를 네이밍 서비스에 등록, 삭제, 검색을 할 수 있는 방법
		
		try{
			
			Context ctx = new InitialContext(); //JNDI 네이밍 서비스 컴파일해줌
			dataSource = (DataSource)ctx.lookup("java:comp/env/jdbc/Oracle11g");
			//lookup으로 데이타소스의 객체를 얻어온다. java:comp/env/는 기본이며 그뒤의 이름은 톰캣서버 context.xml의 name을 참조한다.
			
	} catch(NamingException e) {
		e.printStackTrace();
	}
		
}

	public ArrayList<BVO> list() {
		//DB에 있는 글목록들을 가져오는 역할 형식은 ArrayList이고 BVO타입. 칼럼정보가 BVO에 있다.
		
		ArrayList<BVO> bVOs = new ArrayList<BVO>(); <-------여기서 VO를 참조하여 ArrayList 객체를 만든다.
		
/*        
		//////연결을 위한 3구문/////
		Connection connection = null; //커넥션 javax
		PreparedStatement preparedStatement = null; //프리패어드 스테이트먼트 javax		
		ResultSet resultSet = null;  //데이터를 가져오는 기능의 리절트셋 javax
		//////////////
		
		
		try {
		connection = dataSource.getConnection();
		
		//쿼리문을 만들어줌
		String sql = "select bNo, bName, bSubject, bContent, bDate, bHit, bGroup, bStep, bIndent from mvc_bbs"
					+ " order by bGroup desc, bStep asc";
		
		preparedStatement = connection.prepareStatement(sql); //preparedStatement에 전송
		
		resultSet = preparedStatement.executeQuery(); //result값 데이터를 가져오는 것
		
		while(resultSet.next()) {
			//Resultset 다음행에 데이터가 있으면 while 문으로 반복 작업을 함		
			
			//vo의 9인자를 참조해서 작성
			int bNo = resultSet.getInt("bNo");
			String bName = resultSet.getString("bName");
			String bSubject = resultSet.getString("bSubject");
			String bContent = resultSet.getString("bContent");
			Timestamp bDate = resultSet.getTimestamp("bDate");
			
			int bHit = resultSet.getInt("bHit");
			int bGroup = resultSet.getInt("bgroup");
			int bStep = resultSet.getInt("bStep");
			int bIndent = resultSet.getInt("bIndent");
			///////
			
			//인자생성자
			BVO bVO = new BVO(bNo, bName, bSubject, bContent, bDate, bHit, bGroup, bStep, bIndent); <--여기서도 VO 참조
			
			bVOs.add(bVO); //bVOs라는 어레이에 bVO 추가함
		}
				
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			
			//finally 안에 있는 구문
			try {
				//null이면 구문들을 다 안쓰는 것
				if(resultSet !=null) resultSet.close();
				if(preparedStatement != null) preparedStatement.close();
				if(connection != null) connection.close();
				
			} catch (Exception e2) {	
				e2.printStackTrace();
			}
	
		}
		
		return bVOs;	
	}
	
}
*/

 

4-1. VO // 변수 선언

DAO에서 최초로 VO를 불러내었다. VO에서는 따로 참조하는 클래스가 없다.

VO에서는 순수하게 변수선언, 인자생성, setter/getter만 만들어준다.

따라서 코딩할때 가장 먼저 작성되어야할 클래스이기도 하다.

 

BVO.java

public class BVO {
	
	//db에서의 인덱스를 변수로 지정해준다. 각자의 형식에 맞춰서 형식을 지정해준다.
	//VO클래스는 변수선언, 인자생성자, setter getter 이렇게 3개로 나뉜다.
	
	//1.변수 선언
	int bNo;
	String bName;
	String bSubject;
	String bContent;
	Timestamp bDate;  //timestamp는 sql에서 불러오면됨
	int bHit;
	int bGroup;
	int bStep;
	int bIndent;
	
//	public BVO() {
//		
//	}
	
	
	//2.인자생성자
	public BVO(int bNo, String bName, String bSubject, String bContent, Timestamp bDate, int bHit, int bGroup, int bStep, int bIndent) {
		this.bNo = bNo;
		this.bName = bName;
		this.bSubject = bSubject;
		this.bContent = bContent;
		this.bDate = bDate;
		this.bHit = bHit;
		this.bGroup = bGroup;
		this.bStep = bStep;
		this.bIndent = bIndent;
	}
	
	
	//3.setter getter
	public int getbNo() {
		return bNo;
	}

	public void setbNo(int bNo) {
		this.bNo = bNo;
	}

	public String getbName() {
		return bName;
	}

	public void setbName(String bName) {
		this.bName = bName;
	}

	public String getbSubject() {
		return bSubject;
	}

	public void setbSubject(String bSubject) {
		this.bSubject = bSubject;
	}

	public String getbContent() {
		return bContent;
	}

	public void setbContent(String bContent) {
		this.bContent = bContent;
	}

	public Timestamp getbDate() {
		return bDate;
	}

	public void setbDate(Timestamp bDate) {
		this.bDate = bDate;
	}

	public int getbHit() {
		return bHit;
	}

	public void setbHit(int bHit) {
		this.bHit = bHit;
	}

	public int getbGroup() {
		return bGroup;
	}

	public void setbGroup(int bGroup) {
		this.bGroup = bGroup;
	}

	public int getbStep() {
		return bStep;
	}

	public void setbStep(int bStep) {
		this.bStep = bStep;
	}

	public int getbIndent() {
		return bIndent;
	}

	public void setbIndent(int bIndent) {
		this.bIndent = bIndent;
	}
	
}

 

간단히 "VO > DAO > Service > 컨트롤러"  이 순서대로 불러와진다고 보면된다.

다시 3. DAO로 거슬러 돌아간다.

 

 

3-2. DAO // 남은 부분처리

 

남은 부분을 처리 해주고 끝부분에서는 bVOs ArrayList를 리턴해준다.

 

BDAO.java

public class BDAO {
	/*DataSource dataSource; //데이타소스를 가져오는 구문
	
	//생성자
	public BDAO() {
		//JNDI 를 사용한다. JNDI란 자바에서 객체를 네이밍 서비스에 등록, 삭제, 검색을 할 수 있는 방법
		
		try{
			
			Context ctx = new InitialContext(); //JNDI 네이밍 서비스 컴파일해줌
			dataSource = (DataSource)ctx.lookup("java:comp/env/jdbc/Oracle11g");
			//lookup으로 데이타소스의 객체를 얻어온다. java:comp/env/는 기본이며 그뒤의 이름은 톰캣서버 context.xml의 name을 참조한다.
			
	} catch(NamingException e) {
		e.printStackTrace();
	}
		
}

	public ArrayList<BVO> list() {
		//DB에 있는 글목록들을 가져오는 역할 형식은 ArrayList이고 BVO타입. 칼럼정보가 BVO에 있다.
		
		ArrayList<BVO> bVOs = new ArrayList<BVO>(); <-------여기서 VO를 참조하여 ArrayList 객체를 만든다.
		*/
        
		//////연결을 위한 3구문/////
		Connection connection = null; //커넥션 javax
		PreparedStatement preparedStatement = null; //프리패어드 스테이트먼트 javax		
		ResultSet resultSet = null;  //데이터를 가져오는 기능의 리절트셋 javax
		//////////////
		
		
		try {
		connection = dataSource.getConnection();
		
		//쿼리문을 만들어줌
		String sql = "select bNo, bName, bSubject, bContent, bDate, bHit, bGroup, bStep, bIndent from mvc_bbs"
					+ " order by bGroup desc, bStep asc";
		
		preparedStatement = connection.prepareStatement(sql); //preparedStatement에 전송
		
		resultSet = preparedStatement.executeQuery(); //result값 데이터를 가져오는 것
		
		while(resultSet.next()) {
			//Resultset 다음행에 데이터가 있으면 while 문으로 반복 작업을 함		
			
			//vo의 9인자를 참조해서 작성
			int bNo = resultSet.getInt("bNo");
			String bName = resultSet.getString("bName");
			String bSubject = resultSet.getString("bSubject");
			String bContent = resultSet.getString("bContent");
			Timestamp bDate = resultSet.getTimestamp("bDate");
			
			int bHit = resultSet.getInt("bHit");
			int bGroup = resultSet.getInt("bgroup");
			int bStep = resultSet.getInt("bStep");
			int bIndent = resultSet.getInt("bIndent");
			///////
			
			//인자생성자
			BVO bVO = new BVO(bNo, bName, bSubject, bContent, bDate, bHit, bGroup, bStep, bIndent); <--여기서도 VO 참조
			
			bVOs.add(bVO); //bVOs라는 어레이에 bVO 추가함
		}
				
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			
			//finally 안에 있는 구문
			try {
				//null이면 구문들을 다 안쓰는 것
				if(resultSet !=null) resultSet.close();
				if(preparedStatement != null) preparedStatement.close();
				if(connection != null) connection.close();
				
			} catch (Exception e2) {	
				e2.printStackTrace();
			}
	
		}
		
		return bVOs; <----list()메소드 끝부분에서는 bVOs ArrayList를 리턴해준다.
	}
	
}

 

다시 2. Service로 거슬러 올아간다.

 

2-2. Service //

dao.list()에서 Return시킨 bVOs를 cmd의 bVOS에도 저장 시킨다.

그리고 이 bVOS를 "list"란 이름의 모델명에 적용시킨다.

 

ListCmd.java

public class ListCmd implements Bcmd {
/*
	@Override
	public void service(Model model) {
		
		BDAO dao =new BDAO(); <------------여기서 DAO클래스를 참조한다.
 */     	
       
        
        ArrayList<BVO> bVOs = dao.list(); <---list()에서 리턴된 bVOs를 bVOs에 저장

		model.addAttribute("list", bVOs);
	}

}

 

적용시킨 모델명 "list"는 컨트롤러를 통해서 list.jsp로 값을 보내주게된다. (또는 불러오게)

 

그리고 public void service(Model model)에서 model이 아닌 이름을 내가 아무렇게나 지정해도 된다.

한국의 주입식 교육의 폐해 중 하나가 이건 vo로 써야하고, 이건 model로 써야하고 이건 dao로 써야 하는 것으로 알고 가르치는 것이다.

 

편의상 그렇게 쓰는 것이지 소문자로 시작하는 것은 내가 정한 변수이므로 아무렇게나 지정해줘도 된다.

이른바 아래처럼

 

 ListCmd.java

public class ListCmd implements Bcmd {

	@Override
	public void service(Model abcdefg) {
		
		BDAO dddddddd=new BDAO(); <------------여기서 DAO클래스를 참조한다.
    	
       
        
        ArrayList<BVO> qwerqwer = dddddddd.list(); <---list()에서 리턴된 bVOs를 bVOs에 저장

		abcdefg.addAttribute("list", qwerqwer);
	}

}

 

극단적인 예로 이렇게 한것이다. 복사 붙혀넣기만 하지말고 이렇게 변수를 이거저거 바꾸어 적용해보고 하면 온전히 나의 것으로 만들 수 있다.

 

 

ListCmd 클래스에서는 이렇게 모델을 지정해주는 것으로 끝났고, 이제 Back단 중 마지막으로  1. Controller로 올라가보자.

 

1-2. Controller // 뷰페이지로 이동

cmd= new ListCmd()로 서비스를 가져와서 cmd에 저장해주었다.

 

하지만 거기서 끝이 아니라 cmd안의 service()메소드를 실행시켜줘야 작동한다.

service(model)의 model은 물론 변수이기 때문에 아무렇게나 지정해줘도 된다.

 

@RequestMapping("/list")
public String list(Model model) {
/*
cmd = new ListCmd(); <-------여기서 Service 클래스를 참조한다.
*/

cmd.service(model); <-------ListCmd의 service()메소드를 실행시킨다.

return "list"; <-------list.jsp를 사용자에게 보여준다.



}

list로 리턴하였으므로 list.jsp로 넘어간다.

 

5. 뷰페이지 // list.jsp

여기서는 다른 내용은 볼것없고 <Table>태그 안의 내용만 보면 된다.

태그라이브러리를 이용할 것이므로 맨 윗부분에 <%@ taglib prefix = "c" uri="http://java.sun.com/jsp/jstl/core" %>를 붙여주었다.

 

<c:forEach items="${list}" var="vo">

</c:forEach>

구문을 통하여 아까 모델로 지정해주었던 "list"를 불러온다.

 

이 list라는 모델에는 bNo, bSubject 등의 행들이 리스트형태로 저장되어 있다.

forEach라는 이름에 걸맞게 태그안에서 각각의 행들을 모두 불러와준다.

 

그리고 ${vo.bNO} 등을 통하여 그 모델값을 불러올 수 있다.

 

list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <% request.setCharacterEncoding("utf-8"); %>
<%@ taglib prefix = "c" uri="http://java.sun.com/jsp/jstl/core" %>
    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" http-equiv="Content-Type" content="text/html;">
<title>게시판 리스트</title>
</head>
<body>

<div align="center">
	<h2>게시판 글목록</h2>
	<hr width="400" color="red" />
	
	<table border="1" cellpadding="0" cellspacing="0" width="500">
		<tr>
			<td>번호</td>
			<td>제목</td>
			<td>작성자</td>
			<td>날짜</td>
			<td>조회수</td>
		</tr>
 
				<!-- 게시글 목록 가져오기 -->
		<c:forEach items="${list}" var="vo">	
		<!-- ListCmd에서 만들었던 모델 list를 컨트롤러를 통해 받아온다.-->
		<tr>
			<td>${vo.bNo}</td>
			<td>${vo.bSubject}</td>
			<td>${vo.bName}</td>
			<td>${vo.bDate}</td>
			<td>${vo.bHit}</td>
		</tr>
		</c:forEach>
		<tr>
			<td colspan="5" align="center"><a href="writeForm">글쓰기</a></td>
		</tr>
		
	</table>
    
   
</div>
<div>
</div>

</body>
</html>

 

다음 포스팅에선 글쓰기 기능을 추가해본다.

 

 

 

이번에는 db를 불러와서 리스트로 보여주기 위해 필요한 과정이다.

아래와 같은 파일들을 만들어 주어야한다. (WriteCmd.java 제외)

 

1. VO 클래스 만들기

Value Object로 가장 기초가 되는 객체들을 정의 해놓는 클래스이다.

SQL문에서 지정해놓았던 것들과 이름을 같게 해준다.

 

BVO.java

package com.spring.bbsVO;

import java.sql.Timestamp;

public class BVO {
	
	//db에서의 인덱스를 변수로 지정해준다. 각자의 형식에 맞춰서 형식을 지정해준다.
	//VO클래스는 변수선언, 인자생성자, setter getter 이렇게 3개로 나뉜다.
	
	//1.변수 선언
	int bNo;
	String bName;
	String bSubject;
	String bContent;
	Timestamp bDate;  //timestamp는 sql에서 불러오면됨
	int bHit;
	int bGroup;
	int bStep;
	int bIndent;
	
//	public BVO() {
//		
//	}
	
	
	//2.인자생성자
	public BVO(int bNo, String bName, String bSubject, String bContent, Timestamp bDate, int bHit, int bGroup, int bStep, int bIndent) {
		this.bNo = bNo;
		this.bName = bName;
		this.bSubject = bSubject;
		this.bContent = bContent;
		this.bDate = bDate;
		this.bHit = bHit;
		this.bGroup = bGroup;
		this.bStep = bStep;
		this.bIndent = bIndent;
	}
	
	
	//3.setter getter
	public int getbNo() {
		return bNo;
	}

	public void setbNo(int bNo) {
		this.bNo = bNo;
	}

	public String getbName() {
		return bName;
	}

	public void setbName(String bName) {
		this.bName = bName;
	}

	public String getbSubject() {
		return bSubject;
	}

	public void setbSubject(String bSubject) {
		this.bSubject = bSubject;
	}

	public String getbContent() {
		return bContent;
	}

	public void setbContent(String bContent) {
		this.bContent = bContent;
	}

	public Timestamp getbDate() {
		return bDate;
	}

	public void setbDate(Timestamp bDate) {
		this.bDate = bDate;
	}

	public int getbHit() {
		return bHit;
	}

	public void setbHit(int bHit) {
		this.bHit = bHit;
	}

	public int getbGroup() {
		return bGroup;
	}

	public void setbGroup(int bGroup) {
		this.bGroup = bGroup;
	}

	public int getbStep() {
		return bStep;
	}

	public void setbStep(int bStep) {
		this.bStep = bStep;
	}

	public int getbIndent() {
		return bIndent;
	}

	public void setbIndent(int bIndent) {
		this.bIndent = bIndent;
	}
	
}

 

2. DAO 클래스 만들기

DAO는 Database access object의 약자로 말그대로 SQL에 접근시켜주는 역할을 맡는다.

쿼리문도 여기다 작성한다.

 

많은 방법이 있지만 JNDI 네이밍 서비스를 활용하여 오라클을 LOOKUP해주는 것으로 시작한다.

 

BDAO.java

package com.spring.bbsDAO;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;

//import javax.activation.DataSource; 액티베이션 아님
import javax.naming.Context; //JNDI
import javax.naming.InitialContext; //JNDI
import javax.naming.NamingException; //JNDI
import javax.sql.DataSource;

import com.spring.bbsVO.BVO;

public class BDAO {
	DataSource dataSource; //데이타소스를 가져오는 구문
	
	//생성자
	public BDAO() {
		//JNDI 를 사용한다. JNDI란 자바에서 객체를 네이밍 서비스에 등록, 삭제, 검색을 할 수 있는 방법
		
		try{
			
			Context ctx = new InitialContext(); //JNDI 네이밍 서비스 컴파일해줌
			dataSource = (DataSource)ctx.lookup("java:comp/env/jdbc/Oracle11g");
			//lookup으로 데이타소스의 객체를 얻어온다. java:comp/env/는 기본이며 그뒤의 이름은 톰캣서버 context.xml의 name을 참조한다.
			
	} catch(NamingException e) {
		e.printStackTrace();
	}
		
}
	//리스트 보여주기 위한 메소드 list()
	public ArrayList<BVO> list() {
		//DB에 있는 글목록들을 가져오는 역할 형식은 ArrayList이고 BVO타입. 칼럼정보가 BVO에 있다.
		
		ArrayList<BVO> bVOs = new ArrayList<BVO>(); //ArrayList형태의 bVOs 객체 생성
		
		//////연결을 위한 3구문/////
		Connection connection = null; //커넥션 javax
		PreparedStatement preparedStatement = null; //프리패어드 스테이트먼트 javax		
		ResultSet resultSet = null;  //데이터를 가져오는 기능의 리절트셋 javax
		//////////////
		
		
		try {
		connection = dataSource.getConnection();
		
		//쿼리문을 만들어줌
		String sql = "select bNo, bName, bSubject, bContent, bDate, bHit, bGroup, bStep, bIndent from mvc_bbs"
					+ " order by bGroup desc, bStep asc";
		
		preparedStatement = connection.prepareStatement(sql); //preparedStatement에 전송
		
		resultSet = preparedStatement.executeQuery(); //result값 데이터를 가져오는 것
		
		while(resultSet.next()) {
			//Resultset 다음행에 데이터가 있으면 while 문으로 반복 작업을 함		
			
			//vo의 9인자를 참조해서 작성
			int bNo = resultSet.getInt("bNo");
			String bName = resultSet.getString("bName");
			String bSubject = resultSet.getString("bSubject");
			String bContent = resultSet.getString("bContent");
			Timestamp bDate = resultSet.getTimestamp("bDate");
			
			int bHit = resultSet.getInt("bHit");
			int bGroup = resultSet.getInt("bgroup");
			int bStep = resultSet.getInt("bStep");
			int bIndent = resultSet.getInt("bIndent");
			///////
			
			//인자생성자
			BVO bVO = new BVO(bNo, bName, bSubject, bContent, bDate, bHit, bGroup, bStep, bIndent);
			
			bVOs.add(bVO); //bVOs라는 어레이에 bVO 추가함
		}
				
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			
			//finally 안에 있는 구문
			try {
				//null이면 구문들을 다 안쓰는 것
				if(resultSet !=null) resultSet.close();
				if(preparedStatement != null) preparedStatement.close();
				if(connection != null) connection.close();
				
			} catch (Exception e2) {	
				e2.printStackTrace();
			}
	
		}
		
		return bVOs;	
	}//list() 메소드 중료
}

 

3. service 클래스 만들기

여기서는 cmd라고 한다. 인터페이스 형태로 만들어져 컨트롤러에서 service 클래스를 호출하게 된다.

(클라이언트 > 디스패처 > 컨트롤러 > service 클래스 순으로 요청이 된다.)

 

우선 com.spring.bbsCommand 패키지 안에 Bcmd라는 인터페이스를 만든다.

 

Bcmd.java  (인터페이스 형식)

package com.spring.bbsCommand;

import org.springframework.ui.Model;

//데이터를 가져오는 역할
public interface Bcmd {
	void service(Model model);
	//파라미터를 생성하는 방법 또는 리턴타입을 생성하는 경우가 있음
}

 

 

컨트롤러에서 Model을 불러옴. 위에 것은 인터페이스이기에 Overriding 해줘야함.

 

모델을 불러오는 방법에는 두가지가 있다.

1. 파라미터 이용

2. 리턴타입 이용

위는 파라미터 형태로 불러왔다.

 

그리고 실제로 db를 받아서 저장하는 ListCmd.java를 com.spring.bbsCommand 패키지 안에 만든다.

 

ListCmd.java

package com.spring.bbsCommand;

import java.util.ArrayList;

import org.springframework.ui.Model;

import com.spring.bbsDAO.BDAO;
import com.spring.bbsVO.BVO;

//이 객체의 목적: 데이터베이스를 받아 모델로 만들어줌

public class ListCmd implements Bcmd {
	//Bcmd 인터페이스를 가져와서 오버라이드함.
	//이 객체를 만들고 컨트롤러에서 활용하면 됨
	

	@Override
	public void service(Model model) {
		
		BDAO dao =new BDAO(); //BDAO.class를 불러온 dao 변수 생성
		
		ArrayList<BVO> bVOs = dao.list();  //dao의 list를 bVOs에 저장함
		
		//model.addAttribute("test01", "컨트롤러에서 받아오는지 테스트하는 용도");
		
		model.addAttribute("list", bVOs); //list 변수에 bvos 추가, 이 "list"는 return 값을 할 수 있음
		//JSP에서 ${list}를 입력하면 bVOs를 가져옴. 컨트롤러에 cmd.service(model)이  이 모델을 가져오기 때문

	}

}

 

 

4. Controller 만들기

 

컨트롤러는 페이지 매핑을 주로 담당한다. 

아래와 같이 Bcontroller.java를 생성한다.

 

주저리 주저리 말안하고 자세한 것은 아래 코드 주석으로 설명한다.

 

Bcontroller.java

package com.spring.bbsController;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

import com.spring.bbsCommand.Bcmd;
import com.spring.bbsCommand.ListCmd;
//import com.spring.bbsCommand.WriteCmd;
import com.spring.bbsVO.BVO;

@Controller
public class BController {
	Bcmd cmd = null; //Bcmd 인터페이스를 불러와서 cmd에 저장해준다.

	
	@RequestMapping("/list")
	public String list(Model model) {
		//String으로 list 메소드를 생성했으니 리턴값도 String이다. RequestMapping의 아래는 대부분 String메소드이다.
		//파라미터형태로 모델 생성
		//모델의 역할은 뷰에게 데이터를 전달하기 위한 객체
		//여기서는 모델활용안하고 Bcmd.class에서 모델을 활용함.
		
		System.out.println("------------------list() 호출-------------");//에러날때를 대비해서 써줌
		//Model은 뷰에 데이터를 전달하기 위한 방법
		cmd = new ListCmd(); 	//Bcmd 인터페이스를 가져온 녀석에다 ListCmd()를 넣어줌
		//위에서 Bcmd cmd = null;을 안해주고 곧바로 이것을 해줘도 되지만 의존성을 낮추기 위해서 이렇게 해줌
		
		cmd.service(model);	//모델을 인자로 넘겨줌. 서비스를 시행
		
		return "list";
	}
}

 

5. view 페이지 만들기

앞 컨트롤러에서 list로 리턴을 해주었으니 파일명을 list.jsp를 만들어 준다.

viewResolver 설정을 확장자가 저절로 생기게끔 했기 때문에 "list"만 적어주면된다.

 

프론트로 보여주는 것은 태그라이브러리를 사용한다.

 

list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <% request.setCharacterEncoding("utf-8"); %>
<%@ taglib prefix = "c" uri="http://java.sun.com/jsp/jstl/core" %>
    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" http-equiv="Content-Type" content="text/html;">
<title>게시판 리스트</title>
</head>
<body>
<div align="center">
	<h2>게시판 글목록</h2>
	<hr width="400" color="red" />
	
	<table border="1" cellpadding="0" cellspacing="0" width="500">
		<tr>
			<td>번호</td>
			<td>제목</td>
			<td>작성자</td>
			<td>날짜</td>
			<td>조회수</td>
		</tr>
				<!-- 게시글 목록 가져오기 -->
		<c:forEach items="${list}" var="vo">	
		<!-- ListCmd에서 만들었던 모델 list를 컨트롤러를 통해 받아온다.-->
		<tr>
			<td>${vo.bNo}</td>
			<td>${vo.bSubject}</td>
			<td>${vo.bName}</td>
			<td>${vo.bDate}</td>
			<td>${vo.bHit}</td>
		</tr>
		</c:forEach>
		<tr>
			<td colspan="5" align="center"><a href="writeForm">글쓰기</a></td>
		</tr>
		
	</table>

</div>
<div>
</div>

</body>
</html>

 

 

실행 결과

톰캣을 가동한 뒤 localhost:8080/list를 들어가보면 아래와 같이 뜸을 확인할 수 있다.

값은 미리 sql문을 통해서 넣은 것이다.

 

localhost:8080/list

노캐쉬 설정을 안하면 컴퓨터를 껐다 킬때마다 시쿼스가 20씩 증가해서 번호가 이상해지는데 그것을 방지하기 위해 아까 시퀀스를 만들때 nocache 구문을 넣어준 것이다.

 

"ALTER SEQUENCE seq_bbs nocache"로도 캐쉬미사용 설정을 할 수 있다.

 

아직 글쓰기 부분은 코딩하지 않았으니 글쓰기를 누르면 실행안되는 것이 맞다.

 

글쓰기 기능 작성으로 넘어가기전에 다음 포스팅에서는 어떻게 해서 리스트를 보여주는지 절차를 한번 짚고 넘어가도록한다.

 

저게 단순해서 몇번 반복하면 알아 들을것 같지만 세세하게 복기를 안하면 알기 힘들다.

인터넷을 찾아보면 주먹구구식 "스프링 게시판 만들기" 블로그 및 강의가 많은데, 거의 태그라이브러리라는 라이브러리와 오라클을 사용하고 있다.

하지만 다른 라이브러리를 사용해야 하는 경우도 많고, 여러 라이브러리(프레임워크)를 사용하여 게시판만들기를 반복하다 보면 자바 실력이 매우 늘 것으로 예상한다.

 

따라서 MYSQL, AngularJS 게시판 등 몇가지로 구분하여 포스팅할 것이며,

이번 포스팅에서는 Taglib와 오라클을 사용하여 게시판을 만들 것이다.

 

Taglib는 자바에서 제공하는 프론트쪽 라이브러리이고, 오라클은 데이터베이스 프로그램이다.

 

백엔드 언어는 자바이며, 스프링프레임워크를 사용한다. (모든에듀의 스프링활용 강의를 참조하였다.)

 


오라클 설치

 

SQL Developer 19.1 다운로드

오라클 11g를 설치하기 전에 설치해야 한다.

개인은 무료로 사용할 수 있다.

https://www.oracle.com/technetwork/developer-tools/sql-developer/downloads/index.html

 

Oracle SQL Developer Downloads

 

www.oracle.com

 

Oracle Database 11g R2 다운로드

압축파일 2개를 받아서 같은 폴더 경로에 합친다.

https://www.oracle.com/technetwork/database/enterprise-edition/downloads/112010-win64soft-094461.html

 

Oracle Database 11g Release 2 for Microsoft Windows (x64)

Oracle Database 11g Release 2 (11.2.0.1.0) Standard Edition, Standard Edition One, and Enterprise Edition Thank you for accepting the OTN License Agreement; you may now download this software. Oracle Database 11g Release 2 Client (11.2.0.1.0) for Microsoft

www.oracle.com

SQL developer에 들어가서 새로만들기를 눌러 아래와 같이 설정

사용자 이름을 system이라고 둔다.


테이블 생성

오라클을 설치했으면, SQL 디벨로퍼에 들어가서 DB가 저장될 테이블을 생성해야 한다.

아래의 쿼리문을 오라클에 입력/실행 해준다.

create table mvc_bbs(
	bNO number(3) primary key,
	bName varchar2(20),
	bSubject varchar2(80),
	bContent varchar2(300),
	bDate date default sysdate,
	bHit number(3) default 0,
	bGroup number(4),
	bStep number(4),
	bIndent number(4)
);

Table MVC_BBS이(가) 생성되었습니다. 라는 문구가 나오면 성공적으로 테이블이 생성된 것이다.

bStep과 bIndent는 댓글과 관련된 것이다.

 

그리고 오라클은 mysql과 달리 bNO가 1부터 올라가려면 sequence를 생성시켜줘야한다. 아래 쿼리문도 실행시켜준다.

create sequence seq_bbs nocache;

Sequence SEQ_BBS이(가) 생성되었습니다. 라는 문구가 나오면 성공적으로 시퀀스가 생성 된것이다.

 

뒤에 노캐쉬를 왜 붙혀주냐면, 저걸 안붙혀주면 컴퓨터 메모리가 날라가면 디폴트로 시퀀스에 20이 추가된다. 그래서 아래와 같이 이상한 번호들을 보여주는 참사가 일어날 수 있다. nocache붙혀주자.

 

이제 더미 데이터를 넣을 차례, 아래의 쿼리문을 입력/실행 시켜준다.

insert into mvc_bbs (bNo, bName, bSubject, bContent, bHit, bGroup, bStep, bIndent) 
values (seq_bbs.nextval, 'test', 'test입니다.', '안녕하세요.', 0, seq_bbs.currval, 0, 0);

bNO는 1씩 증가해야 하니 시퀀스에 nextval을 넣어준 것이고 그룹은 현재의 시퀀스를 가져와야 하기 때문에 current value 명령어를 넣어주었다.

 

1 행 이(가) 삽입되었습니다. 라는 문구가 나오면 성공적으로 행이 삽입된 것이다.

 

새로고침을 누른 뒤 아래와 같이 보여질 것이다.

 


 

스프링 프레임워크 환경 설정

 

web.xml에 다음과 같이 코드를 붙여넣는다.

 

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">

	<!-- 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>
	
	
	<!-- 필터를 만든다. 한번 작성해논 뒤 다른 프로젝트에서도 복사 붙여넣기 함-->
	<filter>
		<filter-name>encodingFilter</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>encodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

</web-app>

 

그 뒤 아래와 같은 경로에 다음과 같은 이름의 5개의 패키지를 만든다.

 

톰캣 서버에서 오라클 세팅

스프링에서 오라클을 불러 올 수 있도록 세팅을 해야한다.

 

서버의 context.xml 파일에서 아래와 같이 입력함.

 

context.xml

<?xml version="1.0" encoding="UTF-8"?>

<!-- The contents of this file will be loaded for each web application --><Context>

    <!-- Default set of monitored resources. If one of these changes, the    -->
    <!-- web application will be reloaded.                                   -->
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>

    <!-- Uncomment this to disable session persistence across Tomcat restarts -->
    <!--
    <Manager pathname="" />
    -->
    <!-- 오라클 세팅 -->
    <Resource auth="Container"
    	driverClassName="oracle.jdbc.driver.OracleDriver"
    	maxActive="50"
    	maxWait="1000"
    	name="jdbc/Oracle11g"
    	password="12351235"
    	type="javax.sql.DataSource"
    	url="jdbc:oracle:thin:@localhost:1521:orcl"
    	username="system" />
    
</Context>

 

 

 

 

그 안에 컨트롤러, VO, DAO 등의 설정은 다음 포스팅에서 

 

 

개요

SQL과 Java 객체를 연결하는 지속성 프레임워크이다.

이전에는 iBATIS라는 이름으로 Apache 프로젝트의 하나로 개발되고 이었다. 그러나 2010년 6월에 Apache 소프트웨어 재단에서 개발이 중단되어 현재는 MyBatis라는 이름으로 개발되고 있다.

SQL 문을 완전히 제어하고 싶을 때 사용하면 편하다.

 

명령어

 

사용 방법

[test.java]

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

java 파일 위에 위와 같이 써준다.

 

[test.xml]

 

 

명령문

 

 

1. myBatis / ibatis: SQL문을 제어하는 것을 돕는다.

 

관련 명령문

  • seletList("String", 매개변수)
  • selectOne("String", 매개변수)

 

2. httpSession: 로그인 관련하여 세션처리를 해준다. 사용자 정보를 조회하고 업뎃하는 등에 사용된다.

 

 

3. httpServletRequest하나의 요청에서 HttpServletRequest 객체가 소멸하기 까지 상태정보를 유지하고자 할 때, 한번의 요청으로 실행된 페이지끼리 정보를 공유하고자 할 때 사용된다.

 

- 참조

httpSession과 HttpServletRequest의 차이점

https://salguru.tistory.com/23

 

 

4. httpServletResponse: 응답할 클라이언트에 대한 정보와 동작 정보를 가지고 있는 객체

불러오기

ServletWebRequest servletContainer = (ServletWebRequest)RequestContextHolder.getRequestAttributes();

HttpServletRequest request = servletContainer.getRequest();
HttpServletResponse response = servletContainer.getResponse();

 

 

5. httpService: HTTP >> 데이터를 GET 또는 POST 방식으로 웹서버로 전송 >> XML 형식으로 리턴

 

 

6. IOException어떠한 입출력 예외의 발생을 통지하는 시그널을 발생시킨다. 클래스 선언시 "throws IOException"으로 사용

 

 

7. Spring security: HttpSecurity메소드를 사용하여 보안 인증을 만드는 라이브러리이다.

 

관련 명령문

  • getAuthentication()
  • getPrincipal()

 

8. UUID: 무작위 문자열을 생성하는 자바 유틸이다.

 

 

9. JacksonJSON 데이터 구조를 처리해주는 라이브러리이다.

 

관련 명령문

  • JsonParseException
  • JsonMappingException
  • ObjectMapper
  • TypeReference

10. UserAgent: http-header로 부터 요청된 user-agent를 분석하여 브라우저 정보를 획득한다.

 

 

11. jsoup: 웹크롤링을 도와주는 강력한 라이브러리이다.

 

참조

https://mommoo.tistory.com/83

 

 

12. gsonjson을 생성하고 파싱하는 구글에서 제공하는 라이브러리이다.

 

관련 명령문

  • Gson
  • JsonObject
  • JsonParser

 

13. deviceUtils: 현재 사용하는 디바이스를 판별해준다.

 

관련 명령문

  • isNormal()
  • isMobile()
  • isTablet()

 

1. 개요 (from 전자정부표준프레임워크)

 

Spring MVC Framework의 유일한 Front Controller인 DispatcherServlet은 spring MVC의 핵심요소이다.

DispatcherServlet은 Controller로 향하는 모든 웹요청의 진입점이며, 웹요청을 처리하며 결과 데이터를 Client에게 응답한다.

 

web.xml에 DispatcherServlet 설정하기

Spring MVC Framework을 사용하기 위해서는 web.xml에 DispatcherServlet을 설정하고, DispatcherServlet이 WebApplicationContext를 생성할수 있도록 빈(Bean) 정보가 있는 파일들도 설정해주어야 한다. 

 

1-1 MVC1, MVC2 패턴의 종말

DispatcherServlet 사용으로 기존 MVC1과 MVC2패턴은 쓰이지 않는다.

 

2. 기본설정

web.xml에 아래와 같이 DispatcherServlet이 자동으로 설정된다.

	<!-- 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>

클라이언트가 해당 어플리케이션에 접근하면 접근한 URL 요청을 DispatcherServlet 이 가로챈다.

이렇게 요청을 가로챌 수 있는 이유는 web.xml 에 등록된 DispatcherServlet  <url-pattern>이 ‘/’ 와 같이 해당 어플을 통과하는 모든 URL로 등록했기 때문이다.

특정 URL 만 적용하고 싶다면 <url-pattern> 의 내용을 바꿔주어 범위를 변경시켜주면 된다.

 

3. HandlerMapping

  • Dispatcher가 받은 요청은 HandlerMapping으로 넘어간다. 그리고 이 요청을 처리할 수 있는 Controller를 찾게 된다.
  • Controller부터는 개발된 애플리케이션 영역이다. DB 연동 등 로직 처리가 이루어지고 view로 넘어간 후에 최종적으로 DispatcherServlet를 거쳐 클라이언트에 리턴된다.

 

4. Spring MVC 핵심 구성 요소 (1)

① DispatcherSevlet 은 모든 연결을 담당하며, 웹 브라우저에서 요청이 들어오면 

② 그 요청을 처리하기 위해 HandlerMapping 객체에게 컨트롤러 검색을 요청한다.

    HandlerMapping은 클라이언트의 요청 경로를 이용해서 이를 처리할 컨트롤러 객체를 찾아서 DispatcherServlet 에 리턴한다.  

ex) root-context.xml 속

	<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
    
		<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
 		<property name="url" value="jdbc:mysql://172.16.0.150:3306/btctrade?characterEncoding=UTF-8"></property> 
		<property name="username" value="btckorea"></property> 
		<property name="password" value="road0ds!32"></property> 
		
	</bean>

 

③  DispatcherServlet 은 @Controller 어노테이션을 이용해서 구현한 컨트롤러, 스프링 2.5까지 사용됐던 Controller 인터페이스를 구현한 컨트롤러, 특수 목적으로 사용되는 HttpRequestHandler 인터페이스를 구현한 클래스를 동일한 방식으로 실행하고 처리하기 위해 HandlerAdapter 객체에게 요청 처리를 위임한다.

④ HandlerAdapter 객체는 컨트롤러의 알맞은 메소드를 호출해서 요청을 처리하고,

⑤ 반환 받은 결과를 

⑥ ModelAndView 객체에 담아서 DispatcherServlet 에 리턴한다.

⑦ ModelAndView 객체를 반환 받은 DispatcherServlet 은 ViewResolver 객체를 이용해서 결과를 보여줄 뷰를 검색한다.

    ViewResolver 객체는 ModelAndView 객체에 담긴 뷰 이름을 이용해서 View 객체를 찾거나 생성해서 리턴한다.

    ViewResolver 는 매번 새로운 View 객체를 생성해서 DispatcherServlet에 리턴한다.

⑧ DispatcherServlet 은 ViewResolver 가 리턴한 View 객체에게 응답 결과 생성을 요청한다.

⑨ JSP를 사용하는 경우, View 객체는 JSP를 실행함으로서 브라우저에게 전송할 응답 결과를 생성한다.

    ModelAndView 의 Model 객체에 담겨 있는 데이터가 응답 결과에 필요하면 Model 에서 데이터를 꺼내 JSP 에서 사용할 수 있다.

 

 

클라이언트의 요청을 실제로 처리하는 것은 컨트롤러이고, 

DispatcherServlet 은 클라이언트의 요청을 전달 받는 창구 역할을 한다.

DispatcherServlet 에게 어떤 컨트롤러가 요청을 처리하는가는 중요하지 않으며, 

처리 결과를 ModelAndView 타입의 객체로 전달 받을 수 있기만 하면 된다.

이 때, 사용할 컨트롤러를 찾고, 처리 결과를 ModelAndView 객체로 변환해 주는 객체가 HandlerAdapter 이다.

 

핸들러 객체의 실제 타입마다 그에 알맞은 HandlerMapping 과 HandlerAdapter 가 존재하기 때문에,

사용할 핸들러의 종류에 따라 해당 HandlerMapping 과 HandlerAdapter 를 스프링 빈으로 등록해 주어야 하는데,

스프링 설정 기능(<mvc:annotaion-driven>)을 사용하면 직접 등록하지 않아도 스프링이 알아서 처리해 준다.

 

요청을 처리할 컨트롤러를 찾기 때문에 ControllerMapping 이라는 이름이 어울리는데,

스프링 MVC 는 웹 요청을 처리할 수 있는 범용적인 프레임워크를 제공하고 있기 때문에,

클라이언트의 요청을 처리하는 객체가 컨트롤러가 아닐 수도 있다(HttpRequestHandler 등).

그래서 스프링 MVC 는 웹 요청을 실제로 처리하는 객체를 Handler 라고 표현하고 있다.

따라서 컨트롤러는 DispatcherServlet 입장에서 보면 한 종류의 핸들러 객체이다.

 

5. Spring MVC 핵심 구성 요소 (2) 설명2

  1. 클라이언트가 해당 어플리케이션에 접근하면 접근한 URL 요청을 DispatcherServlet 이 가로챕니다. 이렇게 요청을 가로챌 수 있는 이유는 web.xml 에 등록된 DispatcherServlet  <url-pattern>이 ‘/’ 와 같이 해당 어플을 통과하는 모든 URL로 등록했기 때문입니다. 특정 URL 만 적용하고 싶다면 <url-pattern> 의 내용을 바꿔주어 범위를 변경시켜주면 됩니다.

  2. 가로챈 정보를 HandlerMapping 에게 보내 해당 요청을 처리할 수 있는 Controller 를 찾아냅니다. (스프링은 기본적으로 5가지의 핸들러 매핑을 제공합니다.) 이 부분은 스프링의 디폴트 전략에 의해 BeanNameUrlHandlerMapping DefaultAnnotationHandlerMapping 이 기본으로 Spring MVC에 탑재되있기 때문에 특별한 경우가 아니면 따로 설정할 필요가 없습니다.

  3. 핸들러 매핑이 해당 요청을 처리할 컨트롤러를 찾아냈다면 요청을 컨트롤러에 보내줍니다. 컨트롤러는 사용자가 직접 구현해주는 부분입니다. @MVC는 매우 다양한 코딩방식과 직관적이고 편리한 컨트롤러 작성방법을 제공하므로 이 부분에 대해서는 차후 심층적인 분석으로 자신에게 알맞는 전략을 선정해야합니다.

  4. 해당 요청을 처리한 후에 컨트롤러는 요청을 응답받을 View 의 이름을 리턴하게 됩니다. ( 물론 다른 핸들러 매핑 전략을 이용한다면 응답 과정이 다를 수도 있습니다. ) 그 때 이 이름을 ViewResolver 가 먼저 받아 해당하는 View가 존재하는지 검색합니다.

  5. 컨트롤러에서 보내온 View 이름을 토대로 처리 View 를 검샙합니다.

  6. 해당 View가 있다면 처리결과를 View에 보낸 후 7. 이 결과를 다시 DispatcherServlet 에 보낸 후 8. DispatcherServlet 은 최종 결과를 클라이언트에 전송합니다.

 

자원의 분리

  • ’/’ 요청에 대한 모든 처리를 DispatcherServlet 이 담당한다면, 비어플리케이션 자원 (js, css …)에 대해서도 컨트롤러를 찾아 해매는 에러가 발생할 수 있다.
  • 그에 따라 Spring 은 자원을 분리할 수 있는 기능을 추가 시켜놓았다.
  • 이와 같은 처리는 preference의 Deplyment Assembly에 가면 확인 가능하다.

 

servlet-context.xml 파일 안

<resources mapping="/resources/-*" location="/resources/" />

  • <mvc:resources> 는 디스패처 서블릿이 해당 요청을 컨트롤러에서 찾지 못했을 때 2차적으로 위의 설정된 경로를 검색하여 해당 자원을 찾아내게 하는 것입니다.
  • 어플리케이션 자원과 비어플리케이션 자원( js, css …)을 분리하여 resources 폴더에서 따로 관리 가능하도록 한 것 입니다.

HttpSession을 이용한 Session 관리방법
- Client의 상태값을 서버측에 저장하여 Session 관리
- javax.servlet.http.HttpSession 객체를 이용하여 관리

 

 

HttpSession은 로그인 처리할 때 유용하게 쓰인다. 이것의 동작은 세션 쿠키를 통해 이루어진다. 서버는 접속한 브라우저에게 고유한 세션쿠키를 전달하고, 매번 브라우저에서 서버를 호출할 때 세션 쿠키를 가지고 다니기 때문에, 이를 마치 열쇠처럼 사용해서 필요한 데이터를 보관한다.

 

session을 이용하는 방식의 핵심은 HttpSession을 이용해서 객체를 보관할 수 있다는 점이다. 사용자는 항상 열쇠에 해당하는 세션쿠키를 가지고 접근하고, 서버의 내부에 상자가 필요한 객체를 보관하기 때문에 안전하다는 장점을 가지고 있다.

 

session에 보관된 객체는 JSP에서 EL을 이용해서 자동으로 추적하는 방식을 사용한다. 예를 들면 ${name}은 page > request > session > application 순서대로 원하는 데이터를 검색한다. 따라서 JSP를 개발하는 개발자는 자신이 사용하는 변수가 request에 존재하는 것인지, session에 존재하는 것인지 고민하지 않아도 된다.

 

 

장점 ?
- 관리할 수 있는 상태값(Client Data)의 종류나 크기나 개수의 제한이 없음
- 서버에 저장되므로 cooie에 비해 보안상 유리

단점 ?
- 서버에 부담을 줌

 

 

////////////////////////////////////////////

 

HttpSession의 주요 메서드

 

 메소드 이름

리턴 타입 

설명 

getAttribute(String name) 

 java.lang.Object

 세션 속성명이 name인 속성의 값을 Object 타입으로 리턴한다. 해당 되는 속성명이 없을 경우에는 null 값을 리턴한다.

getAttributeNames() 

java.util.Enumeration 

 세션 속성의 이름들을 Enumeration 객체 타입으로 리턴한다.

getCreationTime() 

long 

1970년 1월 1일 0시 0초를 기준으로 하여 현재 세션이 생성된 시간까지 경과한 시간을 계산하여 1/1000초 값으로 리턴한다. 

getId() 

java.lang.String 

세션에 할당된 고유 식별자를 String 타입으로 리턴한다. 

getMaxInactiveInterval()

int 

현재 생성된 세션을 유지하기 위해 설정된 세션 유지시간을 int형으로 리턴한다.

invalidate() 

void 

현재 생성된 세션을 무효화 시킨다.

소멸

removeAttribute(String.name)

void 

세션 속성명이 name인 속성을 제거한다. 

setAttribute(String name, Object value)

void 

세션 속성명이 name인 속성에 속성값으로 value를 할당한다. 

setMaxInactiveInterval(int interval) 

void 

세션을 유지하기 위한 세션 유지시간을 초 단위로 설정한다. 즉, Client가 Second 만큼 동안 요청이 들어오지 않으면 Session을 소멸

 

 

 

Enumeration: 

Enumeration 인터페이스는 객체들의 집합(Vector)에서 각각의 객체들을 한순간에 하나씩 처리할 수 있는 메소드를 제공하는 켈렉션이다.

 

[JAVA] Vector 클래스 정리

 

인터페이스이므로, 직접 new 연산자를 이용하여 객체를 생성할 수 없으며, Enumeration 인터페이스에 선언된 메소드는 그 인터페이스를 사용하는 클래스로 구현해서 사용해야만 한다.

 

* Enumeration 인터페이스 메소드

 

Enumeration 메소드 

설명 

boolean hasMoreElements() 

 Vector로 부터 생성된 Enumeration의 요소가 있으면 true, 아니면 false 반환

Object nextElement() 

 Enumeration 내의 다음 요소를 반환한다. 

 

Enumeration 객체는 new 연산자로 생성할 수 없으며, Vector를 이용하여 생성할 수 있다.

Vector 클래스의 elements() 라는 메소드는 객체의 모든 요소들을 Enumeration 객체로 반환한다.

 

//////////////////////////////

 

getSession(), getSession(true)는 null 체크없이 바로 getAttribute()를 사용해도 무방하지만, getSession(false)는 null을 리턴할수 있기 때문에 null체크를 해야 한다.

문제점

스프링 퀵 스타트 게시판 페이지 p.127를 공부하다가 코드를 입력 후 board_inset를 실행하였지만 아래와 같은 에러를 발생 시켰다...

 

 


INFO : org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor - JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@7ea37dbf: defining beans [boardDAO,boardService,homeController,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0]; root of factory hierarchy
메인 구동
===> JDBC로 insertBoard() 기능 처리
org.h2.jdbc.JdbcSQLException: Connection is broken: "unexpected status 16777216" [90067-193]
===> JDBC로 getBoardList() 기능 처리
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
at org.h2.message.DbException.get(DbException.java:179)
at org.h2.message.DbException.get(DbException.java:155)
at org.h2.engine.SessionRemote.done(SessionRemote.java:639)
at org.h2.command.CommandRemote.prepare(CommandRemote.java:68)
at org.h2.command.CommandRemote.(CommandRemote.java:45)
at org.h2.engine.SessionRemote.prepareCommand(SessionRemote.java:494)
at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1203)
at org.h2.jdbc.JdbcPreparedStatement.(JdbcPreparedStatement.java:73)
at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:287)
at com.springbook.biz.board.impl.BoardDAO.insertBoard(BoardDAO.java:35)
at com.springbook.biz.board.impl.BoardServiceImpl.insertBoard(BoardServiceImpl.java:17)
at com.springbook.biz.board.BoardServiceClient.main(BoardServiceClient.java:23)
org.h2.jdbc.JdbcSQLException: Connection is broken: "unexpected status 768" [90067-193]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
at org.h2.message.DbException.get(DbException.java:179)
at org.h2.message.DbException.get(DbException.java:155)
at org.h2.engine.SessionRemote.done(SessionRemote.java:639)
at org.h2.engine.SessionRemote.close(SessionRemote.java:570)
at org.h2.jdbc.JdbcConnection.close(JdbcConnection.java:394)
at com.springbook.biz.common.JDBCUtil.close(JDBCUtil.java:37)
at com.springbook.biz.board.impl.BoardDAO.insertBoard(BoardDAO.java:43)
at com.springbook.biz.board.impl.BoardServiceImpl.insertBoard(BoardServiceImpl.java:17)
at com.springbook.biz.board.BoardServiceClient.main(BoardServiceClient.java:23)
org.h2.jdbc.JdbcSQLException: Connection is broken: "unexpected status 16777216" [90067-193]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
at org.h2.message.DbException.get(DbException.java:179)
at org.h2.message.DbException.get(DbException.java:155)
at org.h2.engine.SessionRemote.done(SessionRemote.java:639)
at org.h2.command.CommandRemote.prepare(CommandRemote.java:68)
at org.h2.command.CommandRemote.(CommandRemote.java:45)
at org.h2.engine.SessionRemote.prepareCommand(SessionRemote.java:494)
at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1203)
at org.h2.jdbc.JdbcPreparedStatement.(JdbcPreparedStatement.java:73)
at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:287)
at com.springbook.biz.board.impl.BoardDAO.getBoardList(BoardDAO.java:111)
at com.springbook.biz.board.impl.BoardServiceImpl.getBoardList(BoardServiceImpl.java:33)
at com.springbook.biz.board.BoardServiceClient.main(BoardServiceClient.java:26)
INFO : org.springframework.context.support.GenericXmlApplicationContext - Closing org.springframework.context.support.GenericXmlApplicationContext@51521cc1: startup date [Thu Apr 11 16:33:36 KST 2019]; root of context hierarchy
INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@7ea37dbf: defining beans [boardDAO,boardService,homeController,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0]; root of factory hierarchy


 

해결방안

메이븐 pom.xml 설정을 통해 h2의 버전을 내가 사용하는 h2의 버전과 맞춰주었다.

또는  jdbc 버전을 높여주니 예외가 해결되었다.

 

pom.xml ==>

		
		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<version>1.4.193</version>
		</dependency>

 

고찰

mySQL이든 다른 프로그램이든 pom.xml의 버전을 반드시 확인해서 맞춰주어야 한다.

 

스프링 유용한 단축키

 

1. 자동 완성 기능

키: crtl+space

 

명령어를 어느정도 입력한 뒤 crtl+space를 누르면 추천 명령어가 뜬다.

 

syso 입력한 후 Ctrl + Space 하면 System.out.println(); 으로 바뀐다.

try 입력한 후 Ctrl + Space 하면 try-catch 문이 완성된다.

for 입력한 후 Ctrl + Space 하면 여러가지 for 문을 완성할 수 있다.

 

2. 주석 기능

키: crtl+shift+C

 

선택한 뒤 crtl+shift+c를 누르면 알아서 /* */ 또는 <!-- --> 등으로 주석 처리 해줌

 

3. 코드 찾기 기능

키: crtl+H

 

파일 안에 쓰여진 코드를 찾을 수 있다.

보통 file search로 한다.

 

4. 파일 찾기 기능

키: crtl+shft+R

 

프로젝트 안의 파일들을 찾을 수 있다.

 

5. 에러 내용 확인

키: F2

 

컴파일 에러기호에 커서를 갖져다가 이 키를 누르면 에러의 원인에 대한 힌트를 제공한다.

 

6. 한줄 삭제

키: crtl+D

 

7. 하이어라키창 띄우기 (인터페이스 구현 클래스간 이동시 편리)

키: crtl+T

 

8. 메소드나 필드 이동하기

키: crtl+O

 

9. 자동 import

키: crtl+shift+O

 

10. 디버그

키: F11

+ Recent posts