반응형

 

 

 

 

 

 

 

 

 

<MVC 아키텍쳐>

MVC 이전
Model DAO
View HTML 영역
Controller java영역(서블릿)

 

MODEL(DAO)

package study;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
public class BangMyungDAO_OracleImpl implements BangMyungDAO
{
     @Override
     public void add(BangMyungVO vo) throws Exception
     {
         Connection conn = null;
         Statement stmt = null;
         try {
                 Class.forName("oracle.jdbc.driver.OracleDriver");
                 conn =
            DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:32771/xe",
             "system", "1234");
                stmt = conn.createStatement();
             String sql = "insert into bangmyung_t values (
            seq_bangmyung.nextval, '"+
             vo.getGul() + "', sysdate )";
             stmt.executeUpdate( sql );
             }
                catch( Exception e ){ throw e; }
                finally {
                 if( stmt != null ) stmt.close();
                 if( conn != null ) conn.close();
                }
         }
         @Override
         public List<BangMyungVO> findAll() throws Exception {
             List<BangMyungVO> ls = new ArrayList<BangMyungVO>();
             Connection conn = null;
             Statement stmt = null;
             ResultSet rs = null;
         try {
             Class.forName("oracle.jdbc.driver.OracleDriver");
             conn =
        DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:32771/xe",
         "system", "1234");
             stmt = conn.createStatement();
             String sql = "SELECT no, gul, the_time FROM bangmyung_t order by
        no desc";
             rs = stmt.executeQuery( sql );
         while( rs.next() ) {
              BangMyungVO vo = new BangMyungVO();
             vo.setNo( rs.getInt("no") );
             vo.setGul( rs.getString("gul") );
             vo.setTheTime( rs.getString("the_time") );
             ls.add( vo );
         }
         }
         catch( Exception e ){}
         finally {
             if( rs != null ) rs.close();
             if( stmt != null ) stmt.close();
             if( conn != null ) conn.close();
         }
     return ls;
     }
}

VIEW(HTML)

<%@ page language="java" contentType="text/html; charset=EUC-KR"
 pageEncoding="EUC-KR"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="sso" %>
<!DOCTYPE>
<html>
    <body>
        <table border='1'>
             <tr>
             <td>No</td>
             <td>글</td>
             <td>작성시간</td>
             </tr>
             <sso:forEach varStatus="vs" var="vo" items="${ lst }">
             <tr bgColor="${ (vs.count % 2 != 0)?'#aabbcc':'#bbccdd' }">
                 <td>${ vs.count }</td>
                 <td>${ vo.no }</td>
                 <td>${ vo.gul }</td>
                 <td>${ vo.theTime }</td>
             </tr>
             </sso:forEach>
        </table>
        <form method="POST" action="bangmyung_add.jsp">
         <input type="text" name="gul" size="50"/>
         <input type="submit"/>
        </form>
    </body>
</html>

 

CONTROLLER(JAVA)

<%@ page language="java" contentType="text/html; charset=utf-8"
 pageEncoding="utf-8" import="java.util.List, study.*" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="sso" %>
<%!
 public void submit() {
 System.out.println("submit");
 }
%>
<%
     // 1. 변수선언
     List<BangMyungVO> rl = null;
     Exception err = null;
     // 2. DB 연동
     BangMyungDAO dao = new BangMyungDAO_OracleImpl();
     try {
     rl = dao.findAll();
     } catch (Exception e) {
     err = e;
     }
     // 3. 흐름 만들기
     if ( rl == null || err != null ) {
     response.setCharacterEncoding("utf-8");
     response.sendRedirect("/study3/error.jsp");
     } else {
     request.setAttribute("lst", rl);
     RequestDispatcher rd = request.getRequestDispatcher("/Test125_1.jsp");
     rd.forward(request, response);
    %>
<!DOCTYPE>
<html>
    <body>
        <table border='1'>
         <tr>
             <td>No</td>
             <td>글</td>
             <td>작성시간</td>
         </tr>
         <sso:forEach varStatus="vs" var="vo" items="${ lst }">
         <tr bgColor="${ (vs.count % 2 != 0)?'#aabbcc':'#bbccdd' }">
             <td>${ vs.count }</td>
             <td>${ vo.no }</td>
             <td>${ vo.gul }</td>
             <td>${ vo.theTime }</td>
         </tr>
         </sso:forEach>
        </table>
    <form method="POST" action="bangmyung_add.jsp">
     <input type="text" name="gul" size="50"/>
     <input type="submit"/>
    </form>
    <% } %>
    </body>
</html>

 

MVC 만들기

package mvc;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    public interface Controller {
         public String handleRequest(HttpServletRequest request,
        HttpServletResponse response) throws Exception;
}
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
    public @interface RequestMapping {
     public String value();
}
package mvc;
//import 생략~
    public class DispatcherServlet extends HttpServlet {
     private Map<String, Controller> map = null;

     @Override
     public void init(ServletConfig config) throws ServletException{
         map = new Hashtable<String, Controller>();

         String cs = "mvc.CtrlList,mvc.CtrlAdd2";
         for(String str : cs.split(",")){
         try{
             //해당 클래스 가져오고
             Class<?> cls = Class.forName(str);
             //RequestMapping에서 지정된 url 패턴 따오고
             RequestMapping an = cls.getAnnotation(RequestMapping.class);
            //얘 때문에 Controller에너는 Annotation!
             System.out.println("this is an : " + an);
             //해당 controller instance 받아오고
             Controller value = (Controller) cls.newInstance(); 
             // 이름이 str인 Controller 클래스 찾기
             // url 따기
             String key = an.value();
             //url-pattern과 controller 매핑
                 map.put(key, value);
                 }catch (Exception e) {}
                 } //String[] cs2 = cs.split(","); for(int i=0;i<cs2.length;i++)
                 System.out.println(map.toString());
         }
     @Override
     protected void service(HttpServletRequest request, HttpServletResponse
    response)
     throws IOException, ServletException {
     }
 }
package mvc;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

    @RequestMapping("/apple_list.do")
    public class CtrlList implements Controller {

     @Override
         public String handleRequest(HttpServletRequest request,
    HttpServletResponse response) throws Exception {
         return null;
 }
package mvc;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@RequestMapping("/apple_add2.do")
public class CtrlAdd2 implements Controller{

     @Override
     public String handleRequest(HttpServletRequest request,
    HttpServletResponse response) throws Exception {
     return null;
     }
 }

JSP MODEL1 / MVC MODEL2

 

 

model1 VS model2

<model1>

가장먼저 들어오는 곳이 JSP이다.

JSP에서 비즈니스 로직, VIEW모든 것을 처리한다.

 

<model2>

가장먼저 요청하는 곳이 서브릿단이다.

비즈니스 로직을 처리하는 서블릿을 완전히 분리시켜서 VIEW단과 로직을 처리하는 단을 분리시킨다.




 

 

Controller 추가해야할 때

<servlet>
 <servlet-name>abcd2</servlet-name>
 <servlet-class>mvc.DispatcherServlet</servlet-class>
     <init-param>
         <param-name>controllers</param-name>
         <param-value>
         mvc.CtrlList,
         mvc.CtrlAdd2
         </param-value>
     </init-param>
</servlet>

<!-- 여기 이렇게 controller를 추가하면 되지 않을까! -->

public void init(ServletConfig config) throws ServletException{
 map = new Hashtable<String, Controller>();
 String cs = config.getInitParameter("controllers");

 

HTML 소스 긁어오는애

package main;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;
public class Test126 {
     public static void main(String[] args) throws Exception{
         URL rl = new URL("http://localhost:8081/0802/apple_list.do");
         URLConnection ucon = rl.openConnection();
         InputStream in = ucon.getInputStream();

     BufferedReader bin = new BufferedReader(new InputStreamReader(in,
    "UTF-8")); //>> char 단위로 읽게해주는 adapter
     //사실 UTF-8 빼도 되더라 얜 응답 내용
            String l = null;
         while((l = bin.readLine()) !=null){

         System.out.println(l);
         }
     in.close();
    }
}

java.net.URL은 이것 자체가 작은 웹브라우저의 역할을 한다. 요청을 날리고 그에 해당하는 응답을 받아들인
다 안드로이드 앱에서 버튼을 누르면 오늘의 배송정보가 넘어오는 ? 배송정보는 서버에 올라와 있는 상태! => 이
다운 받는 역할, 서버에 존재하는 배송정보를 다운받는 역할을 수행한다. 소켓으로 다 짜는 것이 아니라 http 프
로토콜로 서버와 통신할 때는 이 클래스를 주로 이용한다.
소켓으로 다 짜는 것이 아니라 http 프로토콜로 서버와 통신할 때는 이 클래스를 주로 이용한다.
앱 같은 경우에서 서버로부터 많은 데이터를 다운 받아야 할 경우에 URL 클래스를 이용하여 jsp 파일로부터 정
보를 다운받는다
이게 워낙 많이 쓰이다 보니 이를 강화한 오픈 소스 라이브러리가 등장 = apache http client 프로젝트 = 안
드로이드의 http 기반 표준 통신 수단

 

암호가 맞으면 다운, 아니면 안됨

    <%@ page contentType="text/plain; charset=UTF-8" pageEncoding="EUC-KR" %><%
     String pw = request.getParameter("pw");
     if(pw.equals("1234")){
         String[] l = {"사과", "귤", "배", "토마토"};
         String nl = "\r\n"; //줄 바꿈 표시

     for (int i = 0; i < l.length; i++) {%>
         <%=l[i]%><%=nl%>
         <%}}else{%>
         암호틀림
 <%}%>
public static void main(String[] args) throws Exception{
     URL rl = new URL("http://localhost:8081/0802/Test126.jsp?pw=1230");
     URLConnection ucon = rl.openConnection();
     InputStream in = ucon.getInputStream();

     BufferedReader bin = new BufferedReader(new InputStreamReader(in, "UTF8")); //>> char 단위로 읽게해주는 adapter
     //사실 UTF-8 빼도 되더라 얜 응답 내용

     String l = null;
     while((l = bin.readLine()) !=null){
         System.out.println(l);
         }
         in.close();
}
반응형

'Language Study > Java' 카테고리의 다른 글

5. 자바, 더 정확하게  (0) 2019.09.08
제주에서 자바_Week4  (0) 2019.08.12
##자바 헷갈리는 이론  (0) 2019.08.01
제주에서 자바_Week3_3  (0) 2019.07.31
제주에서 자바_Week3_2  (0) 2019.07.30
반응형

1.방명록dao

 

2.서블렛의 한계

단점

-> 동기화 사용

package study3;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LikeServlet extends HttpServlet{

	int i = 0;
	
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		System.out.println(this.toString());
		/*많은 사람들이 동시에 접속해도 동일한 문자열이 계속 찍힌다 -> 동일한 인스턴스가 재사용되고 있다.
		 * 메모리 관리에는 장점이다
		 * 한꺼번에 많이 들어와도 적게 메모리를 소모한다
		 * */
		PrintWriter out = response.getWriter();
		out.println("<html><body>");
		
		/*왜 synchronized ?
		 * 동시 요청 시 여러개의 쓰레드가 하나의 서블릿 인스턴스를 사용할 수 있다.*/
		synchronized(this){
			i = i+1;
			for(int i = 0 ; i < 20000; i ++){
				out.println(this.i);
				
			}
		}
	
		out.println("</body></html>");
		out.flush();
		out.close();
	}
}

 

 

3.서블렛 여러 기능

<ConfigServlet.java>

package study3;

import java.io.IOException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ConfigServlet extends HttpServlet{

	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		System.out.println("service");
		
		//컨텍스트 경로
		String l = request.getContextPath();
		System.out.println("getContextPath : "  + l);
		
		//ip 주소 다음 나오는 전체 경로
		String m = request.getRequestURI();
		System.out.println("getRequestURI : "  + m);
		
		//접속한 브라우저의 ip 주소값
		String n = request.getRemoteAddr();
		System.out.println("getRemoteAddr : "  + n);
		
		//접속한 브라우저와 운영체제 정보를 담은 문자열이 얻어진다
		//이것을 이용하여 모바일로 접근한 건지 컴으로 접근 한 건지 알수 있고 
		//모바일용 화면과 컴용 화면을 구분하여 제공할 수 도 있다.
		String o = request.getHeader("User-Agent");
		System.out.println("User-Agent : "  + o);
		

		/*getContextPath : /study3
		getRequestURI : /study3/config
		getRemoteAddr : 0:0:0:0:0:0:0:1
		User-Agent : Mozilla/5.0 (Windows NT 6.2; Win64; x64; Trident/7.0; rv:11.0) like Gecko	*/
		
	}

	/*init
service
service
service
service -> 서블릿의 인스턴스는 재활용 된다. 
인스턴스는 재활용을 위해 내부적으로 적재된다 => init
적재되는 시점에 호출되는 함수가 init - 최초 요청 시 에만 호출된다.*/
	@Override
	public void init(ServletConfig config) throws ServletException {
//		String val = config.getInitParameter("apple");
//		System.out.println(val);
		
		/*WEB-INF 폴더의 절대 경로값을 얻어온다
		 * 브라우저가 접근 못하는 폴더가 업로드 파일을 놓기에 가장 적합
		 * 허락받고 (돈내고) 다운 받을 때 FileInputStream 으로 읽어 내보낸다
		 * FileInputStream : 절대 경로를 필요로한다
		 * getRealPath : 유용하게 쓰인다.*/
		ServletContext application = config.getServletContext();
		String path = application.getRealPath("/WEB-INF/");
		System.out.println(path);
		
//		System.out.println("init");
	}
	/*blabla
C:\workspace3\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\study3\WEB-INF\
service*/
}

<LikeServlet.java>

package study3;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LikeServlet extends HttpServlet{

	int i = 0;
	
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		System.out.println(this.toString());
		/*많은 사람들이 동시에 접속해도 동일한 문자열이 계속 찍힌다 -> 동일한 인스턴스가 재사용되고 있다.
		 * 메모리 관리에는 장점이다
		 * 한꺼번에 많이 들어와도 적게 메모리를 소모한다
		 * */
		PrintWriter out = response.getWriter();
		out.println("<html><body>");
		
		/*왜 synchronized ?
		 * 동시 요청 시 여러개의 쓰레드가 하나의 서블릿 인스턴스를 사용할 수 있다.*/
		synchronized(this){
			i = i+1;
			for(int i = 0 ; i < 20000; i ++){
				out.println(this.i);
				
			}
		}
	
		out.println("</body></html>");
		out.flush();
		out.close();
	}
}

web.xml

<?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" id="WebApp_ID" version="3.1">
	<servlet>
		<servlet-name>abcd5</servlet-name>
		<servlet-class>study3.LikeServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>abcd5</servlet-name>
		<url-pattern>/like</url-pattern>
	</servlet-mapping>
	
	
	<servlet>
		<servlet-name>abcd6</servlet-name>
		<servlet-class>study3.ConfigServlet</servlet-class>
		<init-param>
			<param-name>apple</param-name>
			<param-value>blabla</param-value>
		</init-param>
	</servlet>
	<servlet-mapping>
		<servlet-name>abcd6</servlet-name>
		<url-pattern>/config</url-pattern>
	</servlet-mapping>
	
	
</web-app>
반응형

'Language Study > Java' 카테고리의 다른 글

##자바 헷갈리는 이론  (0) 2019.08.01
제주에서 자바_Week3_3  (0) 2019.07.31
제주에서 자바_Week3_1  (0) 2019.07.29
제주에서 자바_Week2_3  (0) 2019.07.25
제주에서 자바_Week2_2  (0) 2019.07.24
반응형

Day 1

 

1.아파치

아파치 소프트웨어 재단의 오픈소스 프로젝트. 일명 웹서버로 불리며, 클라이언트 요청이 왔을때만 응답하는 정적 웹페이지에 사용
  • 웹서버 = 80번 포트로 클라이언트 요청(POST,GET,DELETE)이 왔을때만 응답함.

  • 정적인 데이터만 처리한다.(HTML,CSS,이미지 등)

2.톰캣

dynamic(동적)인 웹을 만들기 위한 웹 컨테이너, 서블릿 컨테이너라고 불리며, 웹서버에서 정적으로 처리해야할 데이터를 제외한 JSP, ASP, PHP 등은 웹 컨테이너(톰캣)에게 전달한다.
  • WAS(Web Application Server)
  1. 컨테이너, 웹 컨테이너, 서블릿 컨테이너라고 부름
  2. JSP,서블릿처리,HTTP요청 수신 및 응답
  3. 아파치만 쓰면 정적인 웹페이지만 처리하므로 처리속도가 매우 빠르고 안정적이다.

<전반적인 서버 운영>

-톰캣 운영

C:\Users\USER>cd \

C:\>cd apa*

C:\apache-tomcat-8.0.45>cd bin

 

C:\apache-tomcat-8.0.45\conf\server.xml -> 8080 포트 => 8081 로 변경

 

C:\apache-tomcat-8.0.45\bin>startup.bat

 

-> ipconfig 후 ipv4 주소 + 8081  => http://192.168.2.95:8081/

 

  • web은 실제로 파일 다운로드 소켓 프로그램 기본과 같다
    • Client :  웹 브라우저
    • Server : 톰캣(Web Application Server : WAS) 

 

  • 브라우저 => 톰캣 접속 => 서버의 파일 다운받아 보여줌

 

  • 톰캣 서버 하나에는 여러개의 Web Application 이 설치 가능=> context
    • Context가 가져야 하는 것 : 홈 디렉터리, 접근 경로

   C:\StudyHome\ 생성 
   C:\StudyHome\WEB-INF\
   C:\StudyHome\WEB-INF\classes
   C:\StudyHome\WEB-INF\lib

 

클라이언트는 홈 디렉토리 아래의 모든 파일을 다운로드 가능하다

단, WEB-INF는 접근이 불가능하다(내부 설정파일 등을 놓는다)

 

classes : java class 파일을 놓는 곳

lib : 동작에 필요한 jar 파일을 놓는 곳

 

C:\StudyHome\WEB-INF>copy C:\apache-tomcat-8.0.45\webapps\ROOT\WEB-INF\web.xml
        1개 파일이 복사되었습니다.

-> WEB-INF 폴더에 web.xml 파일을 복사해 넣는다.

 

web.xml 이렇게 변경
http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  version="3.1"
  metadata-complete="true">

= >기본적인 Context 설정은 되어있다 

=> 이것을 톰캣에 등록해야한다.

 

다시

->C:\apache-tomcat-8.0.45\conf / server.xml에서 변경

<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Context docBase="C:\StudyHome" path="/study" reloadable="true"></Context>

-> 다시 C:\apache-tomcat-8.0.45\bin>startup.bat

 

->StudyHome/test.html 생성

<html>
    <body> HelloWorld : ^^*</body>
</html>

http://192.168.2.95:8081/study/test.html로 연결

 

흐름도

C:\StudyHome\apple\test.html로 복사

http://192.168.2.95:8081/study/apple/test.html

 

-docBase 디렉토리 하위 폴더의 파일은 폴더명을 경로명으로 바꾸어 접속 할 수있다

 

C:\StudyHome\WEB-INF\test.html로 복사

http://192.168.2.95:8081/WEB-INF/test.html

오류 !

-WEB-INF 는 특수한 의미를 갖는다
-> 브라우저에 공개치 않는다 

 

-javaWork 에 클래스를 만들어보자

C:\StudyHome>cd C:\JavaWork

 

HelloWorld2.java를 만들자

package apple;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import java.io.IOException;


public class HelloWorld2 extends HttpServlet{
public void service() throws IOException, ServletException{
}

}

C:\JavaWork>javac -d C:\StudyHome\WEB-INF\classes -classpath servlet-api.jar HelloWorld2.java

 

-HelloWorld2.java를 변경하자 -> 꼭 compile 하기!

-web.xml변경하자

<?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1" metadata-complete="true"> <servlet> <servlet-name>abcd</servlet-name> <servlet-class>apple.HelloWorld2</servlet-class> </servlet> <servlet-mapping> <servlet-name>abcd</servlet-name> <url-pattern>/study01</url-pattern> </servlet-mapping> </web-app>

-다시 서버 돌려보자

http://192.168.2.95:8081/study/study01

 

<tomcat>

29-Jul-2019 12:19:34.131 정보 [main] org.apache.catalina.startup.Catalina.start Server startup in 2683 ms
HelloWorld2 

 

-HelloWorld2 다시 수정

package apple;
import javax.servlet.http.HttpServlet;
import javax.servlet.ServletException;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

public class HelloWorld2 extends HttpServlet {
@Override
   public void service( HttpServletRequest request, 
      HttpServletResponse response)
      throws IOException, ServletException 
      {
         System.out.println("HelloWorld2");
PrintWriter out = response.getWriter();
out.println(""); out.println("    ");
out.println("HelloWorld 2: T 0 T *");
out.println("    "); out.println("");


out.close();
      }
   }
   

-> 이러고 서버 닫았다가 다시 키면 홈페이지에 out.println("HelloWorld 2: T 0 T *");  찍힌다

 

WEB-INF 사용 연결 방식

-> 서블릭의 동작 흐름

0. WAS 쪽에 적절한 설정이 되어 있다고 가정

1. 브라우저에서 /study/study01 으로 요청이 들어온다

2. /study 로 경로를 설정한 Context 있나?

3. 2.에서 찾은 contetxt 의 docBase 폴더 (C:\StudyHome) 아래의 /WEB-INF/web.xml찾음

4. url-pattern 중 / study01에 해당하는 설정 -> servlet-mapping 아래에 -> 서블릿 abcd라는 것을 지명하고 있음
    -서블릿은 서버쪽에서 동작하는 것

5. abcd로 이름 붙여진 서블릿 클래스가 있나? apple.HelloWorld2

6. apple.HelloWorld2 을 찾아 -> 인스턴스 생성 -> 오버라이딩 하는 service 함수호출한다

7. System.out.println ("HelloWorld2"); 은 서버쪽에서 찍힌다.

8. PrintWriter out = response.getWriter(); 를 이용하여 내보내는 것은 요청으로 들어온 브라우저 쪽으로 내보내진다

9. 요청했던 브라우저는 응답으로 전달된 내용을 받아 화면에 출력한다

 

<HelloWorld2.java> 변경한다
package apple;
import javax.servlet.http.HttpServlet;
import javax.servlet.ServletException;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

public class HelloWorld2 extends HttpServlet {
@Override
   public void service( HttpServletRequest request, 
      HttpServletResponse response)
      throws IOException, ServletException 
      {
         System.out.println("HelloWorld2");
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
}
catch(Exception e){
//에러가 난 정보를 역추적해서 출력해준다
e.printStackTrace();
}


PrintWriter out = response.getWriter();
out.println(""); out.println("    ");
out.println("HelloWorld 2: T 0 T *");
out.println("    "); out.println("");


out.close();
      }
   }
   

-ojdbc.jar => 현재 컴파일 하고 있는 StudyHome > WEB-INF > lib 폴더 안에 복사 붙여넣기 

   -> oracle db와 톰캣을 함께 사용할 수 있게 된다.

 

<HelloWorld2.java> 또 바꿔..

 

package apple;
import javax.servlet.http.HttpServlet;
import javax.servlet.ServletException;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;


public class HelloWorld2 extends HttpServlet {
@Override
   public void service( HttpServletRequest request, 
      HttpServletResponse response)
      throws IOException, ServletException 
      {
         System.out.println("HelloWorld2");
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn= DriverManager.getConnection(
"jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");
System.out.println(conn);
conn.close();
}
catch(Exception e){
e.printStackTrace();
}


PrintWriter out = response.getWriter();
out.println(""); out.println("    ");
out.println("HelloWorld 2: T 0 T *");
out.println("    "); out.println("");


out.close();
      }
   }
   

-> 컴파일 하고 서버 돌리면 톰캣에 요렇게 찍힘

Context.reload Reloading Context with name [/study] is completed
HelloWorld2
oracle.jdbc.driver.T4CConnection@6b77a082
package apple;
import javax.servlet.http.HttpServlet;
import javax.servlet.ServletException;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.*;

public class HelloWorld2 extends HttpServlet {
@Override
   public void service( HttpServletRequest request, 
      HttpServletResponse response)
      throws IOException, ServletException 
      {
         System.out.println("HelloWorld2");
String theTime = null;
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn= DriverManager.getConnection(
"jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");

Statement stmt = conn.createStatement();
String sql = "SELECT SYSDATE FROM DUAL";
ResultSet rs = stmt.executeQuery(sql);

if(rs.next()) {
theTime = rs.getString(1);
}
rs.close();

stmt.close();
conn.close();
}
catch(Exception e){
e.printStackTrace();
}


PrintWriter out = response.getWriter();
out.println(""); out.println("    ");
out.println("HelloWorld 2: T 0 T *" + theTime);
out.println("    "); out.println("");


out.close();
      }
   }
   

-> 이렇게하고 서버 실행하면 

HelloWorld 2: T 0 T *2019-07-29 14:28:26.0

<이클립스 다이나믹 프로젝트>

-프로젝트 -> context로 인식 -> src를 서버와 연결(add and remove) -> xml 변경 후


<?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" id="WebApp_ID" version="3.1"> <servlet> <servlet-name>abcd</servlet-name> <servlet-class>study2.HelloWorld3</servlet-class> </servlet> <servlet-mapping> <servlet-name>abcd</servlet-name> <url-pattern>/study2</url-pattern> </servlet-mapping> </web-app>

-> .java에서 Run as tomcat 서버로 돌리면 완성

 

<HelloWorld3.java>

 

package study2;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloWorld3 extends HttpServlet {

   @Override
   public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      // TODO Auto-generated method stub

      List ls = new ArrayList();
      try {
         Class.forName("oracle.jdbc.driver.OracleDriver");
         Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521/XE", "HR", "HR");
         Statement stmt = conn.createStatement();
         String sql = "SELECT no, gul, THE_THIME FROM bangmyung_t";
         ResultSet rs = stmt.executeQuery(sql);

         while (rs.next()) {
            BangMyungVO vo = new BangMyungVO();
            vo.setNo(rs.getInt(1));
            vo.setGul(rs.getString(2));
            vo.setTheTime(rs.getString(3));
            ls.add(vo);
         }
         rs.close();
         stmt.close();
         conn.close();
      } catch (Exception e) {
         e.printStackTrace();
      }
      response.setContentType("text/html; charset=euc-kr");
      PrintWriter out = response.getWriter();
      out.println("");       out.println("   ");
      for (BangMyungVO vo : ls) {
         out.println(vo.getNo() + "\t" + vo.getGul() + "\t" + vo.getTheTime());
      }
      out.println("   ");       out.println("");
      out.close();
   }

}
<BangMyungVO.java>

package study2;

public class BangMyungVO {
public Integer getNo() {
return no;
}
public void setNo(Integer no) {
this.no = no;
}
public String getGul() {
return gul;
}
public void setGul(String gul) {
this.gul = gul;
}
public String getTheTime() {
return theTime;
}
public void setTheTime(String theTime) {
this.theTime = theTime;
}
private Integer no = null;
private String gul = null;
private String theTime = null;
}

<test_01.html>


<!DOCTYPE html> <head> <body> test_01.html <!-- cellspacing="0" : 셀 간 간격 cellpadding="12" : 셀의 벽과 내용과의 간격 border="1" : 경계줄의 굵기 bgcolor="#ccddee" 배경색, 각각 16진수이고 앞 두자리 : red, 다음 두자리 : green, 마지막 두자리 : blue => RGB 값을 섞은 값 rowspan="3", colspan="2" : 엑셀에서의 셀 병합과 같은 개념 rowspan은 상하, colspan은 좌우 셀과 병합한다. <font size = "20px" face = "Impact">apple</font> : 브라우저에 깔린 글꼴만 가능 align ="left| center | right" : 내용물의 좌우 정렬 속성을 정한다 width : 셀의 폭을 결정함 같은 오와 열에 있는 것들은 자동으로 지정된 크기에 맞춰진다(일일이 모든 칸에 크기를 줄 필요가 없다) --> <table border="0" cellspacing="2" cellpadding="12"> <tr bgcolor="#aabbcc"> <td width = "400px" rowspan="2"><font size = "20px" face = "Impact">apple</font></td> <td width = "250px">banana</td> </tr> <tr> <td bgcolor="#ccddee">kiwi</td> </tr> <tr> <td colspan="2" bgcolor="#ccddee" align="center">kiwi</td> </tr> </table> </body> </html>



apple banana
kiwi
kiwi



 

반응형

'Language Study > Java' 카테고리의 다른 글

제주에서 자바_Week3_3  (0) 2019.07.31
제주에서 자바_Week3_2  (0) 2019.07.30
제주에서 자바_Week2_3  (0) 2019.07.25
제주에서 자바_Week2_2  (0) 2019.07.24
제주에서 자바_Week2_1  (0) 2019.07.22
반응형

Day 4

1. Thread(스레드)

  • 하나의 프로세스 내부에서 독립적으로 실행되는 하나의 작업 단위를 말하며,
  • 세부적으로는 운영체제에 의해 관리되는 하나의 작업 혹은 태스크
  • 스레드와 태스크(혹은 작업)은 바꾸어 사용해도 무관
  • 스레드 구현 방법 : 1. 스레드 이용  / 2. Runnable 이용하는 방법
JVM에 의해 하나의 프로세스가 발생하고 main( ) 안의 실행문 들이 하나의 스레드
main( ) 이외의 또 다른 스레드를 만들려면 Thread 클래스를 상속하거나 Runnable 인터페이스를 구현
다중 스레드 작업 시에는 각 스레드 끼리 정보를 주고받을 수 있어 처리 과정의 오류를 줄일 수 있음
프로세스끼리는 정보를 주고받을 수 없음

 

package Lecture.Week2;

//외우기
class CustomThreaded implements Runnable{
    //implements 받아오려면 runaable을 오버라이딩 해줘야 한다. / 오버라이딩 시 throws exception 같은 것은 붙일 수 없다.
    @Override
    public void run() {
        for(int i = 0; i < 100; i++){
            System.out.println("HelloWorld" + i);
        }
    }

}
    public class Test12 {
        public static void main(String[] args){
            //단순한 함수 호출
            Runnable rb = new CustomThreaded();
            rb.run();

            /*new Thread를 하면 가상의 cpu를 OS에서 할당한다. (분신)
            //할당받은 CPU는 생성자에 넘겨진 포인터를 물고 간다.
            start() 호출 : 준비과정을 거쳐 새로운 가상 CPU가 rb.run()을 호출한다.

            1. Runnable  상속받은 클래스 선언
            2. new Thread 하면서 1의 인스턴스의 포인터를 넘긴다
            2. Thread::start() 를 호출하면 가상 CPU(쓰레드) 가 run()을 호출*/
            Thread th = new Thread(rb); //thread의 참조형 변수
            th.start(); //이걸 해야 돌아감
        }
}

2. 프로세스 ,프로그램, 스레드

  • 프로세스 : 데이터(data) + 자원(memory) + 쓰레드(Thread) 로 구성(a running program)
  • 프로그램 : executable file
  • 스레드 : a light-weighted process (독자 행동을 하지만 조금 다르다)
    • 스레드는 프로세스 안에서만 존재가 가능하다
    • 스레드 간 메모리를 공유할 수 있다
    • 프로세스 간 메모리 전달은 가능해도 공유는 불가능하다
    • 프로세스간의 메모리 전달의 대표적 수단이 소켓이다(복사 & 붙이기도 전달로 볼 수 있지만 이건 윈도우에서 국한된 개념)
    • 프로세스 종료 == 프로세스가 가진 모든 쓰레드의 종료
    • start() : 이 스레드가 실행을 시작하도록 함-> 가상 머신 run이 thread의 메소드를 호출한다
    • run() : 이 스레드가 별도의 Runnable 실행 객체를 사용하여 작성한 경우 해당 runnable 객체의 run 메소드 호출
      그렇지 않을 경우 , 이 메서드는 아무것도 수행하지 않고 반환함.
package Lecture.Week2;
class Toilet{
    public void bigWork(String by){
        System.out.println("Step1," + by);
        System.out.println("Step2," + by);
        System.out.println("Step3," + by);
        System.out.println("Step4," + by);
        System.out.println("Step5," + by);

    }
}

/*참조형 : 오른쪽이 가르키는 대상을 왼쪽이 가르친다.
* 멤버변수 : 인스턴스 만들어진 시점에 생성*/


class A implements Runnable{
    private Toilet toilet = null;

    public A(Toilet t){
        toilet = t;
    }

    public void run(){
        for(int i = 0; i < 100;){
//            System.out.println("APPLE");
            toilet.bigWork("APPLE");
            try{
                int time = (int)(Math.random() *1000); //초 단위로 쉬게 하기
                Thread.sleep(time); //try  catch 필요
            }
            catch (InterruptedException e){}
        }
    }
}


class B implements Runnable{
    private Toilet toilet = null;

    public B(Toilet t){
        toilet = t;
    }

    public void run(){
        for(int i = 0; i < 100;){
//            System.out.println("BANANA");
            toilet.bigWork("BANANA");

            try{
                int time = (int)(Math.random() *1000); //초 단위로 쉬게 하기
                Thread.sleep(time); //try  catch 필요
            }
            catch (InterruptedException e){}
        }
    }
}
public class Test13 {
    public static void main(String[] args){
        Toilet t = new Toilet();
        new Thread( new A(t)).start(); //RUNNABLE에서 implements 받은 A의 인스턴스를 생성자에 넣어주고 START
        new Thread( new B(t)).start();
    }
}
/*쓰레드는 독자적으로 돌아가는 프로그램이 된다
* APPLE 과 BANANA 끼어들게 안 짯는데도 결과 가 나옴
* APPLE
BANANA
BANANA
APPLE
BANANA
BANANA
APPLE
BANANA
BANANA
BANANA....
*/

결과 :

Step1,APPLE
Step1,BANANA
Step2,APPLE
Step2,BANANA
Step3,BANANA
Step3,APPLE
Step4,BANANA
Step4,APPLE
Step5,BANANA
Step5,APPLE


* > 아무런 제약이 없다면 이렇게 동시 진행될 수도 있다
* 쓰레드는 독자적이기 떄문에 일어나는 현상
* -> 화장실 문을 잠가야 하니까 

=> 그것을 동기화(Synchronization)이라고 한다.

 

class Toilet{
    public void bigWork(String by){
        synchronized (this) { //this : 참조형 변수 (자기 자신에 대한)
            System.out.println("Step1," + by);
            System.out.println("Step2," + by);
            System.out.println("Step3," + by);
            System.out.println("Step4," + by);
            System.out.println("Step5," + by);
        }
    }
}

 

-모든 인스턴스에는 lock이라는 개념의 자물쇠? 열쇠?가 있다

-synchronized (this) => this가 가리키는 인스턴스가 가지고 있는 록을 획득해야 { .. 에 진입 가능

  획득하지 못하면 쓰레드는 멈추어 기다려야 한다. 

   }로 일을 마쳤으면 lock을 반납한다.

-이런 방법으로 공유하는 메모리에서 작업 도중 끊기는 일을 막을 수 있다. 

 

 

-스레드 조인  / run

package Lecture.Week2;


class A1 implements Runnable{
    public void run(){
        for(int i = 0; i <10; i++){
            System.out.println("A running");
        }
    }
}

class B1 implements Runnable{
    public void run(){
        for(int i = 0; i <10; i++){
            System.out.println("B running");
        }
    }
}

class C1 implements Runnable{
    public void run(){
        for(int i = 0; i <10; i++){
            System.out.println("C running");
        }
    }
}


public class Test14 {
    public static void main(String[] args){
        Thread[] threads = new Thread[3];

        threads[0] = new Thread(new A1());
        threads[1] = new Thread(new B1());
        threads[2] = new Thread(new C1());

        threads[0].start();
        threads[1].start();
        threads[2].start();

        try{
            threads[0].join(); //threads[0]이 끝나기전에는 내려가지 않는다.
            threads[1].join();//join()메소드는 쓰레드가 멈출때까지 기다리게 한다.
            threads[2].join();
        }//모든 쓰레드들이 다 끝나고 난 다음에 최종정리가 찍힌다.
        catch (InterruptedException e){}
//        new Thread(new A1()).start();
//        new Thread(new B1()).start();
//        new Thread(new C1()).start();

        System.out.println("최종정리");
    }
}

3. 자바 - DB 연동

줄 건다 -> 바구니 건다 -> 바구니에 물건 담는다 -> 왕복한다 -> 바구니 내린다 -> 줄 내린다

conn 형성 -> stmt 형성 -> 쿼리 작업 -> stmt.close() -> conn.close()

 

Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/study","root","1111");

Statement stmt = conn.createStatement();//바구니 만든다

String sql = "insert into studentt values ('10107', '또오치','쌍문동')"; //바구니에 담는다

stmt.executeUpdate(sql2);//쿼리 실행-> sql문 실어서 간다

stmt.close(); //바구니 내린다

conn.close(); //줄 푼다.

<전체 코드>

package Lecture.Week2;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class Test15 {
    public static void main(String[] args) throws Exception{
        Class.forName("com.mysql.jdbc.Driver");
        /*Connection은 mysql에 소켓으로 접속하는 것과 관계가 깊음
        * study : 데이터베이스 명
        * root  / 1111 : 계정 및 암호
        * 127.0.0.1 : 네트워크 카드 밖으로 나가지 않고 나에게 접속할 때
        * Statement는 바구니라고 생각하면 된다. */
        Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/study","root","1111");
        //소켓을 이용해서 접속한다-> 줄 단다
        //db 연결

//        System.out.println(conn.toString());
            //connection 객체에 의해 프로그램에 리턴되는 객체에 의해 구현되는 일종의 메소드 집합
        Statement stmt = conn.createStatement();//바구니 건다
        String sql = "insert into studentt values ('10107', '또오치','쌍문동')";
        String sql2 = "delete from studentt where stid = '10107'";
        String sql3 = "update studentt set addr = '이도동' where stid = '10101'";

        stmt.executeUpdate(sql2);//쿼리 실행-> sql문 실어서 간다

        stmt.close(); //바구니 내린다
        conn.close(); //줄 푼다.

        /*Connection : IP, PORT, ID, PWD  -> 줄
        * Statement : SQL, 결과 -> 바구니
        * -> SQL로 -> RETURN 받아 -> STATEMENT.close() (바구니 먼저 내리고) -> CONNECTION.close() (줄 마지막으로 내리고)
        * executeUpdate : 함수의 리턴값은 변경된 레코드 개수 -> select는 레코드를 변경하지 않기 때문에 executeUpdate는 inser/delete/update문장에 사용한다
         */
 }
}

//java -classpath .;mysql-connector-java-5.0.8-bin.jar Test15
package Lecture.Week2;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class Test16 {
    public static void main(String[] args) throws Exception {
        /*static {
            //클래스가 로딩되는 시점에 호출

            /*connection , statement 모두 인터페이스다
            * DriverManager, getConnection 안에서 Connection 상속받은 모종의 클래스의 인스턴스를 리턴한다.
            * -> Mysql에 접속할 수 있는 기능을 구현하고 있다.        }*/

        Class.forName("com.mysql.jdbc.Driver"); //모종의 클래스 세팅하는 코드
        Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/study","root","1111");
//        System.out.println(conn.getClass().getName()); // conn이 어디 클래스에서 가져오나 찍어보는 것 -> com.mysql.jdbc.Connection
        Statement stmt = conn.createStatement(); //바구니 생성
//
        String sql = "select stid,name,addr from studentt";
        ResultSet rs = stmt.executeQuery(sql);

        while (rs.next()){
            String stid = rs.getString("stid");
            String name = rs.getString("name");
            String addr= rs.getString("addr");
            System.out.println(stid + "\t" + name +"\t" +addr);
        }
        rs.close();

        stmt.close();
        conn.close();

    }
}

///암기 하자

-select문에 정보들어가서 바구니에 담긴 걸 : CURSOR이라고 한다. -> 서버 쪽이라서 서버사이드 커서 

-쿼리에서 정보로 넘어갈 때 한 튜플을 채우고 그 밑으로 내려가면서 채운다 

Stid name
←   ↓
←   ↓
←   ↓
←   ↓

 

 

4. O-R Mapping 규칙(Golden Rule, Rule of Thumb)

  • ResultSet 은 CURSOR(select 결과)에 접근 가능한 정보
  • CURSOR는 서버에 생긴다
  • Connection 이 닫인 다음에서는 ResultSet은 사용 불가하다
    (Connection 닫기 전에 사용 끝나야 한다)
    -> connection은 비싼고 제한적인 지원이다
    -> 접속 후에 빨리 끊어주는게 바람직 하다 (콜 센터 연상)

<ArrayList 사용>

package Lecture.Week2;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

class StudentV0{
    /*property : 멤버 변수 -> public으로 열지 않는다.
    -> 대신에 getter , setter을 사용해 가져온다
    -> private 하게 선언 해야한다.*/
    private String stId = null;
    public String getStId(){ return stId;}
    public void setStId(String i){ stId = i;}

    private String name = null;
    public String getName(){ return name;}
    public void setName(String i){ name = i;}

    private String addr = null;
    public String getAddr(){ return addr;}
    public void setAddr(String i){ name = i;}
}




public class Test17{
    public static void main(String[] args) throws Exception {

        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/study","root","1111");
        Statement stmt = conn.createStatement(); //바구니 생성

        /*O-R Mapping 규칙(Golden Rule, Rule of Thumb)

        Field => property
        * table -> class
        * record => instance*/
        //connection은 살아있을때 할거 다해야 하고 / 빨리 끊어야한다 -> 아래 코드에서 이상적으로 구현

        //왜 arrayList 일까? -> 중간 삽입삭제가 필요없고 쌓기만 하는거니까 속도가 빠른 ArrayList
        //VO : Value Object : 값을 담는 객체
        /*테이블 구조와 동일하게 레코드 하나를 인스턴스에 담을 수 있는 역할
        *
        *  DTO : DATA TRANSFER OBJECT
        * Entity 등을 사용하는 경우도 있는데 실은 다 같은 얘기*/
        List<StudentV0> rl = new ArrayList<StudentV0>();

        String sql = "select stid,name,addr from studentt";
        ResultSet rs = stmt.executeQuery(sql);

        while (rs.next()){
            StudentV0 vo = new StudentV0(); //-> 하나의 인스턴스로 만들어 버림
            vo.setStId(rs.getString("stid"));
            vo.setName(rs.getString("name"));
            vo.setAddr(rs.getString("addr"));
            rl.add(vo);
        }
        rs.close();

        stmt.close();
        conn.close();
        //conn.close()이후에도 LIST 안에는 결과가 담겨 있다.
        for(StudentV0 vo : rl){
            System.out.println(vo.getStId() + "\t" + vo.getName() + "\t" + vo.getAddr());
        }
    }
}

<Oracle DB 연동>

package Lecture.Week2;

//import java.sql.Connection;
//import java.sql.DriverManager;
import java.sql.*;

public class Test18 {
    public static void main(String[] args) throws Exception {
        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");
        System.out.println(conn.getClass().getName());
        /*oracle.jdbc.driver.T4CConnection -> connection은 인터페이스 -> 모종의 클래스(T4C)를 상속받아 사용 -> 오로지 오라클에서만 사용가능
          2019-07-25 17:23:23.0

          MYSQL과 코드가 거의 틀린점이 없다
          Connection, Statement 를 상속한 ORACLE 과 연동 가능한 클래스를 OracleDriver에서 DriverManager에 세팅해주면 Oracle에 맞추어
          개발된 , Connection Statement ResultSet 등을 상속받은 클래스가 공급되는 구조
         */

        Statement stmt = conn.createStatement();
        //현재 시간 - MYSQL : now() / ORACLE : SYSDATE
        String sql = "SELECT SYSDATE FROM DUAL";
        ResultSet rs = stmt.executeQuery(sql);
        //결과 레코드가 하나인 경우에는 while 대신에 if문 사용한다.
        if (rs.next()){
            //필드명 대신에 숫자 가능 / 1은 나열된 펏번째 필드를 의미
            String l = rs.getString(1); //첫번째 필드 얘기
            System.out.println(l);
        }

        rs.close();
        stmt.close();

        conn.close();
    }
}

 

Day 5

  1. ORACLE
SQL> conn hr/hr;
연결되었습니다.
SQL> CREATE TABLE STUDY01t(
  2  ID NUMBER(3),
  3  DATA VARCHAR2(10)
  4  );
SQL> INSERT INTO STUDY01t VALUES (100, 'HelloWorld');

-오라클 숫자 : NUMBER(3) -최대 3자리 숫자

-VARCHAR2 : 오라클에서 만든 속도가 조금 빠른 VARCHAR

 

SQL> CREATE TABLE STUDY11t(
  2  ID NUMBER(5),
  3  DATA CHAR(10)
  4  );
SQL> CREATE SEQUENCE seq_study11t;

시퀀스가 생성되었습니다.
SQL> insert into study11t values(seq_study11t.NEXTVAL, 'apple');

-오라클은 mysql은 일련번호가 만드는 방법이 다르다

:mysql : auto_increment primary key를 썼다

 

SQL> SELECT ID, DATA || '*' FROM STUDY11t;
:mysql 의 concat과 동일한 기능을 수행한다.
//char여서 조금 더 떨어져 있음 (|| 공백처리)
//CHAR(10)으로 선언한 필드에 'apple'을 넣으면 'apple       '이 된다
//mysql은 그냥 'apple'이 된다

        ID DATA||'*'
---------- ----------------------
         1 apple     *
         2 apple     *
         3 apple     *
         4 apple     *
SQL> SELECT ID, TRIM(DATA) || '*' FROM STUDY11t;
//TRIM() : 좌/우 공백 문자를 제거하는 역할을 한다

        ID TRIM(DATA)||'*'
---------- ----------------------
         1 apple*
         2 apple*
         3 apple*
         4 apple*
SQL> CREATE TABLE Study12t(
  2  THE_TIME DATE
  3  );
SQL> INSERT INTO STUDY12t VALUES(SYSDATE);
SQL> SELECT * FROM STUDY12T;

THE_TIME
--------
19/07/26
SQL> SELECT TO_CHAR(THE_TIME) FROM STUDY12T;

TO_CHAR(THE_TIME
----------------
19/07/26
19/07/26
19/07/26

SQL> SELECT TO_CHAR(THE_TIME,'YYYY-MM-DD') FROM STUDY12T;

TO_CHAR(THE_TIME,'YY
--------------------
2019-07-26
2019-07-26
2019-07-26

//ORACLE 날짜 시간은 DATE자료형을 사용한다

//현재 시간은 SYSDATE를 이용한다

//보여지는 형식은 TO_CHAR을 이용하여 형식을 지정하면 된다.

 

SQL> SELECT TO_CHAR(THE_TIME,'YYYY-MM-DD HH24:MI:SS') FROM STUDY12T;

TO_CHAR(THE_TIME,'YYYY-MM-DDHH24:MI:SS
--------------------------------------
2019-07-26 11:52:54
2019-07-26 11:53:30
2019-07-26 11:53:32

Q. 역삼동 사는 학생들의 국어점수와 STID를 서브쿼리로?

SQL> SELECT * FROM SCORET WHERE STID IN (SELECT STID FROM STUDENTT WHERE ADDR LIKE '%역삼%') AND SUBID = 'KOR1';

STID       SUBID         SCORE
---------- -------- ----------
10101      KOR1             60
10103      KOR1             70

Q. 학생별 평균점수를 GROUP BY로 구하기(GROUP BY 에서 지정한 컬럼은 SELECT 절에서 쓸 수 있다)

 

SQL> SELECT STID, AVG(SCORE) FROM SCORET GROUP BY STID;

STID       AVG(SCORE)
---------- ----------
10104      73.3333333
10101      76.6666667
10102      93.3333333
10103      76.6666667
10105      63.3333333
10106      66.6666667

#INNER JOIN

SQL> SELECT * FROM STUDENTT INNER JOIN SCORET ON STUDENTT.STID = SCORET.STID; 
= SQL> SELECT * FROM STUDENTT, SCORET WHERE STUDENTT.STID = SCORET.STID; //조금 더 직관적


STID       NAME               ADDR               STID       SUBID         SCORE
---------- ------------------ ------------------ ---------- -------- ----------
10101      홍길동             역삼동             10101      KOR1             60
10101      홍길동             역삼동             10101      ENG1             80
10101      홍길동             역삼동             10101      MAT1             90
10102      고길동             개포동             10102      KOR1             90
10102      고길동             개포동             10102      MAT1             90
10102      고길동             개포동             10102      ENG1            100
10103      이기자             역삼동             10103      KOR1             70
10104      박기자             한남동             10104      KOR1             80
10105      김영삼             홍제동             10105      KOR1             50
10106      김대중             한남동             10106      KOR1             60
10103      이기자             역삼동             10103      ENG1             90

STID       NAME               ADDR               STID       SUBID         SCORE
---------- ------------------ ------------------ ---------- -------- ----------
10104      박기자             한남동             10104      ENG1             70
10105      김영삼             홍제동             10105      ENG1             60
10106      김대중             한남동             10106      ENG1             80
10103      이기자             역삼동             10103      MAT1             70
10104      박기자             한남동             10104      MAT1             70
10105      김영삼             홍제동             10105      MAT1             80
10106      김대중             한남동             10106      MAT1             60

# OUTER JOIN 

SQL> SELECT * FROM SUBJECTT LEFT OUTER JOIN SCORET
  2  ON SUBJECTT.SUBID = SCORET.SUBID;

SUBID    NAME               STID       SUBID         SCORE
-------- ------------------ ---------- -------- ----------
KOR1     국어1              10101      KOR1             60
ENG1     영어1              10101      ENG1             80
MAT1     수학1              10101      MAT1             90
KOR1     국어1              10102      KOR1             90
MAT1     수학1              10102      MAT1             90
ENG1     영어1              10102      ENG1            100
KOR1     국어1              10103      KOR1             70
KOR1     국어1              10104      KOR1             80
KOR1     국어1              10105      KOR1             50
KOR1     국어1              10106      KOR1             60
ENG1     영어1              10103      ENG1             90

SUBID    NAME               STID       SUBID         SCORE
-------- ------------------ ---------- -------- ----------
ENG1     영어1              10104      ENG1             70
ENG1     영어1              10105      ENG1             60
ENG1     영어1              10106      ENG1             80
MAT1     수학1              10103      MAT1             70
MAT1     수학1              10104      MAT1             70
MAT1     수학1              10105      MAT1             80
MAT1     수학1              10106      MAT1             60
PHY1     물리
SQL> SELECT * FROM SUBJECTT, SCORET
  2  WHERE SUBJECTT.SUBID = SCORET.SUBID(+);

SUBID    NAME               STID       SUBID         SCORE
-------- ------------------ ---------- -------- ----------
KOR1     국어1              10101      KOR1             60
ENG1     영어1              10101      ENG1             80
MAT1     수학1              10101      MAT1             90
KOR1     국어1              10102      KOR1             90
MAT1     수학1              10102      MAT1             90
ENG1     영어1              10102      ENG1            100
KOR1     국어1              10103      KOR1             70
KOR1     국어1              10104      KOR1             80
KOR1     국어1              10105      KOR1             50
KOR1     국어1              10106      KOR1             60
ENG1     영어1              10103      ENG1             90

SUBID    NAME               STID       SUBID         SCORE
-------- ------------------ ---------- -------- ----------
ENG1     영어1              10104      ENG1             70
ENG1     영어1              10105      ENG1             60
ENG1     영어1              10106      ENG1             80
MAT1     수학1              10103      MAT1             70
MAT1     수학1              10104      MAT1             70
MAT1     수학1              10105      MAT1             80
MAT1     수학1              10106      MAT1             60
PHY1     물리

-> 오라클용 아우터 조인 문법

-NULL 값으로 채워지는 일이 발생하는 쪽에 + 표시 붙인다.

 

-INNER JOIN ON , OUTER JOIN ON => 국제 표준 SQL

-각 DB별로 변형 SQL을 탑재 

-ORCLE 의 변형방법을 다른 DB 업체들이 따라하기도 하고 

-오라클만 쓴느 사람들은 오라클의 방법만 고집하는 경우가 많다

 

SQL> SELECT STID, AVG(SCORE) AS AVG FROM SCORET GROUP BY STID;

STID              AVG
---------- ----------
10104      73.3333333
10101      76.6666667
10102      93.3333333
10103      76.6666667
10105      63.3333333
10106      66.6666667
SQL> SELECT * FROM (SELECT STID, AVG(SCORE) AS AVG FROM SCORET GROUP BY STID);

STID              AVG
---------- ----------
10104      73.3333333
10101      76.6666667
10102      93.3333333
10103      76.6666667
10105      63.3333333
10106      66.6666667
SQL> SELECT X.STID, X.AVG FROM (SELECT STID, AVG(SCORE) AS AVG FROM SCORET GROUP BY STID) X; //테이블 별칭 줄때 AS를 사용하지 않는다.
//MYSQL에서는 쓰인다.


STID              AVG
---------- ----------
10104      73.3333333
10101      76.6666667
10102      93.3333333
10103      76.6666667
10105      63.3333333
10106      66.6666667
SQL>  SELECT x.stid, x.AVG FROM (
  2     SELECT stid, AVG( score ) AS AVG
  3     FROM scoret GROUP BY stid) x;

STID              AVG
---------- ----------
10104      73.3333333
10101      76.6666667
10102      93.3333333
10103      76.6666667
10105      63.3333333
10106      66.6666667

6 개의 행이 선택되었습니다.
SQL>  SELECT y.name, x.AVG FROM (
  2     SELECT stid, AVG( score ) AS AVG
  3     FROM scoret GROUP BY stid) x , studentt y WHERE x.stid = y.stid ;

NAME                      AVG
------------------ ----------
박기자             73.3333333
홍길동             76.6666667
고길동             93.3333333
이기자             76.6666667
김영삼             63.3333333
김대중             66.6666667

Constraint in Oracle

-primary key , foreign key, check, unique, not null

 

SQL> ALTER TABLE STUDENTT ADD CONSTRAINT PK_STUDENTT_STID PRIMARY KEY (STID);

테이블이 변경되었습니다.

-참조 무결성 : FK 쪽에는 PK에 없는 데이터는 존재하면 안된다

SQL> ALTER TABLE SCORET ADD CONSTRAINT FK_SCORET_STID
      2  FOREIGN KEY(STID) REFERENCES STUDENTT (STID);
SQL> DELETE FROM STUDENTT WHERE STID = '10101';
DELETE FROM STUDENTT WHERE STID = '10101'
*
1행에 오류:
ORA-02292: 무결성 제약조건(HR.FK_SCORET_STID)이 위배되었습니다- 자식 레코드가
발견되었습니다
SQL> ALTER TABLE SCORET ADD CONSTRAINT CH_SCORET_SCORE
  2  CHECK (SCORE >= 0 AND SCORE <= 100);

테이블이 변경되었습니다.

SQL> ALTER TABLE SUBJECTT ADD CONSTRAINT UQ_SUBJECT_SUBID
  2  UNIQUE (SUBID);

테이블이 변경되었습니다.
SQL> INSERT INTO SUBJECTT VALUES(NULL, '없음0');

-> NULL 값의 중복은 허용한다

SQL> INSERT INTO SUBJECTT VALUES('KOR1', '없음0');
INSERT INTO SUBJECTT VALUES('KOR1', '없음0')
*
1행에 오류:
ORA-00001: 무결성 제약 조건(HR.UQ_SUBJECT_SUBID)에 위배됩니다

왜? NOT NULL은 보장안함  / NO DUPLICATE 는 보장 

 

 권장사항 : constraint 는 테스트 끝나고서 ,,,,
         ( 회원가입 담당자가 일 다 안한 상태에서 게시판 담당자가 테스트 하려면? 절레절레)
 
-- constraint 지우기(제약 걸어있을 시 순서대로)

SQL> ALTER TABLE subjectt DROP CONSTRAINT uq_subject_subid;

테이블이 변경되었습니다.

SQL>
SQL> ALTER TABLE scoret DROP CONSTRAINT fk_scoret_stid;

테이블이 변경되었습니다.

SQL>
SQL> ALTER TABLE studentt DROP CONSTRAINT pk_studentt_stid;

 

-방명록 만들기

SQL> CREATE TABLE BANGMYUNG_T(
  2  NO INT,
  3  GUL VARCHAR2(100),
  4  THE_THIME DATE
  5  );

테이블이 생성되었습니다.

 


SQL> CREATE SEQUENCE SEQ_BANGMYUNG;

시퀀스가 생성되었습니다.
SQL> INSERT INTO BANGMYUNG_T VALUES(SEQ_BANGMYUNG.NEXTVAL, '만나서 반갑습니다', SYSDATE);

1 개의 행이 만들어졌습니다.

--MYSQL 

CREATE TABLE BANGMYUNG_T(

    NO INT AUTO_INCREMENT PRIMARY KEY,

    GUL VARCHAR(100),

    THE_TIME DATETIME

);

 

INSERT INTO BANGMYUNG_T VALUES (DAFAULT, '만나서 반갑습니다', NOW());

 

오라클 디비 JDBC

package Lecture.Week2;

import java.sql.*;

public class Test20 {
    public static void main(String[] args) throws Exception{
        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");
        System.out.println(conn.getClass().getName());

        Statement stmt = conn.createStatement();

        String gul = "HelloWorld";
        //String sql = "INSERT INTO BANGMYUNG_T VALUES" + "(SEQ_BANGMYUNG.NEXTVAL, '만나서 반갑습니다'" +" ,SYSDATE)";

        String sql = "INSERT INTO bangmyung_t VALUES " +
                "( seq_bangmyung.NEXTVAL, '" + gul +"'" +
                ", SYSDATE )";

        stmt.executeUpdate(sql);
        conn.close();
    }
}
package Lecture.Week2;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

class BangMyungV0{
    private Integer no = null;
    public void setNo (Integer i ){no = i;}
    public Integer getNo() {return no;}


    /*멤버 변수는 private 하게 선언하는게 바람직함
    * 멤버 변수는 오버라이딩 개념이 없다
    * 조상에서 생성된 변수는 자손에서 재 정의하는게 바람직하지 않다
    * 멤버 변수는 get, set으로 가져와야 한다. */
    private  String gul = null;
    public  void setGul(String i ){gul = i;}
    public String getGul() {return gul;}

    private String theTime = null;
    public void setTheTime(String i){theTime = i;}
    public String getTheTime(){return theTime;}
}


public class Test21 {
    public static void main(String[] args)throws Exception{
        Class.forName("oracle.jdbc.driver.OracleDriver");

        Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");
        Statement stmt = conn.createStatement();
        String sql = "select * from bangmyung_t";

        ResultSet rs = stmt.executeQuery(sql);

        List<BangMyungV0> ls = new ArrayList<BangMyungV0>();
        while(rs.next()){
            BangMyungV0 vo = new BangMyungV0();

            vo.setNo(rs.getInt("no"));
            vo.setGul(rs.getString("gul"));
            vo.setTheTime(rs.getString("THE_THIME"));

            ls.add(vo);
        }

        while (rs.next()){
            String no = rs.getString("no");
            String gul = rs.getString("gul");
            String THE_THIME = rs.getString("THE_THIME");

            System.out.println(no);
            System.out.println(gul);
            System.out.println(THE_THIME);
        }
        rs.close();

        stmt.close();
        conn.close();

        for(BangMyungV0 t: ls ){
            System.out.println(t.getNo() + "\t" + t.getGul() + "\t" + t.getTheTime()+"\t");
        }


    }
}

-함수로 선언해서 재사용성을 높였다 

SQL 문장에서 에러 -> stmt.executeUpdate(sql) 에서 예외발생 -> conn.close() 실행 안한다 -> conn은 빨리 끊어야한다. 

 

위의 내용을 왜 아래처럼 짤까? -> executeUpdate 상황에서 에러나도 conn.close()는 되어야 한다?

-> 되어야 한다. finally 영역 도입 시 try 영역에서 에러가 나건 안나건 무조건 실행한다. 

-> stmt.close() con.close()를 finally로 옮김

-> 변수 선언 정리

 

getConnection() 에서 에러나면? conn stmt 는 null 인채로 finally 행

stmt.close() conn.close()가 stmt, conn이 null 이 아닐 때만 호출하도록 개선했다.

 

-try -catch문 사용

package Lecture.Week2;

import java.sql.*;

class BangMyungV0{
    private Integer no = null;
    public void setNo (Integer i ){no = i;}
    public Integer getNo() {return no;}
    private  String gul = null;
    public  void setGul(String i ){gul = i;}
    public String getGul() {return gul;}

    private String theTime = null;
    public void setTheTime(String i){theTime = i;}
    public String getTheTime(){return theTime;}
}


public class Test21 {
    public static void addGul(String gul) throws Exception {
        Connection conn = null;
        Statement stmt = null;

        try{
            conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");

 String sql = "INSERT INTO bangmyung_t VALUES " +
                    "( seq_bangmyung.NEXTVAL, '" + gul +"'" +
                    ", SYSDATE )";
            stmt.executeUpdate(sql);
        }
        catch (Exception e){

        }finally { //try에서 에러가 나건 안나건 무조건 거친다.
            if (stmt != null) {stmt.close();}
            if(conn != null){conn.close();}
        }

public static void main(String[] args)throws Exception{
        Class.forName("oracle.jdbc.driver.OracleDriver");
        addGul("HelloWORLD");

트랜잭션 : 두 개 이상의 업데이트 문장을 하나처럼 묶어주는 작업 

-> LOG 에 쌓인 걸 한번에 반영하거나 버린다  

-> 동일한 CON에서 작업한 내용만 트랜잭션으로 묶을 수 있다. 

 

-비디오 가게에서의 예

대여 : INSERT
대여중 : 대여 기능에 들어가야함
예치금 --
대여중 -> 삭제
대여 기록 -> INSERT
연체금 -> 예치금에서 뺀다
대여중 -> 대여 가능
댓글 입력
댓글 수 ++ 

 

 

//autocommit

SQL> create table txt_tx(
  2  data int
  3  );
package Lecture.Week2;

import java.sql.DriverManager;
import java.sql.*;

/*conn을 통해서 executeUpdate를 하면 LOG를 거쳐 TABLE에 저장된다
* JDBC는 AUTOCOMMIT을 지원한다
* executeUpdate 시에 무조건 commit이 자동으로 먹는다
* 원래 커밋이 자동으로 먹게 되어있다. -> 로그에 잠시 머물다가 곧바로 커밋으로 올라감
* conn.setAutoCommit(false) // commit이 자동으로 먹지 않는다.*/

public class Test23 {
public static void main(String[] args) throws Exception{
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");

conn.setAutoCommit(false);

Statement stmt = conn.createStatement();
stmt.executeUpdate("insert into txt_tx values (101)");
stmt.executeUpdate("insert into txt_tx values (102)");
stmt.executeUpdate("insert into txt_tx values (103)");
stmt.executeUpdate("insert into txt_tx values (104)");

stmt.close();
conn.commit();//테이블에 올려버린다
// conn.rollback();//로그를 그냥 비운다 => 테이블에 반영이 안된다
conn.close();
}
}
SQL> select * from txt_tx;

      DATA
----------
       100
       101
       102
       103
       104
package Lecture.Week2;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class Test23_2 {
        public static void main(String[] args) throws Exception{
            Class.forName("oracle.jdbc.driver.OracleDriver");
            Connection conn= null;
            Statement stmt = null;

//            conn.setAutoCommit(false); -> 있으면 롤백 에러 잡고 아니면 commit되서 올라감

            try{
                conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");

                stmt = conn.createStatement();
                stmt.executeUpdate("insert into txt_tx values (105)");
                stmt.executeUpdate("insert into txt_tx values (106)");
                stmt.executeUpdate("insert into txt_tx values (107)");
                stmt.executeUpdate("insert into txt_tx values (108)");

                conn.commit();//테이블에 올려버린다

                //에러가 나면 앞에있는 것도 몽땅 다 롤백

            }catch (Exception e){//try 에서 에러가 안나면 catch에서 안잡힘
                if(conn != null){ conn.rollback();}
                throw e;
            }finally {
                if(stmt != null) stmt.close();
                if(conn != null)conn.close();
            }
        }
    }


//향상된 코드 
반응형

'Language Study > Java' 카테고리의 다른 글

제주에서 자바_Week3_2  (0) 2019.07.30
제주에서 자바_Week3_1  (0) 2019.07.29
제주에서 자바_Week2_2  (0) 2019.07.24
제주에서 자바_Week2_1  (0) 2019.07.22
제주에서 자바_Week1  (0) 2019.07.20

+ Recent posts