반응형

spring mvc로 했다.

hello 파일을 설명 했다.

mybatis1 import

mybatis2

 

<select>

           <option></option>

</select>

그래소 option에 내용을 추가하면 change할때 option추가하는 방식으로

구글에서 select동적으로 option추가 이렇게 검색해야 되요

 

아래 이방식으로 하는 것 한번도 못봤음

<select>

           html파일

</select>

 

 

 

이렇게 동작하는 것은 부분 화면 변경해야 하는 것이라서 ajax방식으로

그래서 json - ajax이런식으로 하면 됨

* 계정 생성법

 

1. totoro 계정 생성

    관리자 계정(system)으로 접속한다

    c:\> sqlplus  system/ora123

    SQL>  create user totoro identified by totoro123;

 

2. totoro 계정에게 role을 부여한다.

    SQL> grant  connect, resource to totoro;

 

3. totoro 계정으로 전환한다.

     SQL> conn totoro/totoro123

     SQL>  show user

 

create user spring identified by spring123;

grant  connect, resource to spring;

 

conn spring/ spring123'

 

 

 

 

--게시판 테이블

create table board(

           no number primary key,

           writer varchar2(20),

           subject varchar2(50),

           content varchar2(100),

           readcount number,

           register date

);

 

--시퀀스 생성

create sequence board_seq;

 

select * from board;

 

 

 

 

반응형

'Study > spring' 카테고리의 다른 글

spring-7  (0) 2020.10.26
spring-6  (0) 2020.10.26
spring-5  (0) 2020.10.23
spring-4  (0) 2020.10.23
spring-3  (0) 2020.10.23
반응형

**기본키 중복 검사

=>기본키를 직접 입력받는 경우에는 중복검사를 해주는 것이 좋습니다.

이벤트는 포커스가 잃어버릴 때를 많이 이용하고 이 때 ajax websocket을 이용해서 서버에게 기본키 입력 값을 전송하고 서버는 넘어온 기본키 입력 값을 가지고 데이터베이스에서 조회해서 그 결과를 json 이나 xml 형태로 클라이언트에게 알려주며 클라이언트는 그 값을 가지고 중복 여부를 판단해서 처리를 합니다.

 

=>기본키를 일련번호 형태로 자동 생성하는 경우는 auto_increment sequence를 이용하기도 하고 현재 입력된 번호 중 가장 큰 번호를 찾고 여기에 +1을 해서 생성하는 방법도 있습니다.

이 방법은 일반적으로 비추천하고 되도록이면 숫자나 문자의 조합을 이용해서 분류의 기능을 갖도록 만드는 것을 권장합니다.

대표적으로 주민번호나 학번

 

**폼의 데이터 전송 시 유효성 검사

=>클라이언트에서의 유효성 검사

클라이언트에서 유효성 검사를 하게되면 서버로 전송하지 않고 수행을 하기 때문에 속도나 트래픽 면에서 유리하지만 보안이 되지 않기 때문에 클라이언트가 유효성 검사 로직을 파악할 수 있습니다.

=>폼의 경우는 submit 이벤트에서 유효성검사하고 유효성 검사를 통과하지 못하면 서버로 전송하지 못하도록 이벤트객체의 preventDefault()를 호출하면 됩니다.

=>가장 많이 수행하는 유효성 검사는 필수 입력, 중복 검사 통과 여부, 패턴 일치, 2개의 값일치 등이 있습니다.

 

실습:insert.jsp 파일에 유효성 검사를 위한 스크립트 코드를 추가

          

                       //폼의 데이터를 전송할 때 발생하는 이벤트 처리

           document.getElementById("myform").addEventListener("submit",function(e){

                                  //중복 체크 통과여부 확인

                                  if(idcheck.value == false){

                                              iddiv.innerHTML = '아이디 중복검사를 하세요';

                                              iddiv.style.color = 'red';

                                              itemid.focus();

                                              //폼의 데이터를 전송하지 않도록 하기

                                              e.preventDefault();

                                             return;

                                  }

                                 

                                  var price = document.getElementById("price");

                                  //price 입력 란의 숫자만 입력되었는지 체크

                                  //+ - 기호를 앞에 붙일 수 있는지

                                  //,의 경우는 어떻게 할것인지

                                  for(var i=0; i<price.value.length; i=i+1){

                                              var ch = price.value.charAt(i);

                                              if(i == 0){

                                                         if(!(ch == '+' || ch == '-' || (ch >= '0' && ch <= '9'))){

                                                                     price.focus();

                                                                     alert("가격의 첫번째 자리는 숫자나 +, - 기호여야 합니다.")

                                                                     //폼의 데이터를 전송하지 않도록 하기

                                                                     e.preventDefault();

                                                                     return;

                                                         }

                                              }else{

                                                         if(!(ch >= '0' && ch <= '9')){

                                                                     price.focus();

                                                                     alert("가격은 숫자로만 입력하세요!!!")

                                                                     //폼의 데이터를 전송하지 않도록 하기

                                                                     e.preventDefault();

                                                                     return;

                                                         }

                                              }

                                  }

                       });

 

**Spring에서의 File Upload 처리

=>MultipartFile 타입으로 처리

1.준비사항

1)commons-fileupload 라이브러리의 의존성 설정

2)CommonsMultipartResolver 클래스의 bean을 생성

 

2.MultipartFile

=>파라미터를 직접 이 타입으로 받아도 되고 HttpServletRequest 대신에 MultipartHttpServletRequest를 이용해서 요청을 받고 getFile(String parameterName)을 이용해서 가져올 수 있습니다.

 

3.실습

1)파일 업로드 처리를 위한 라이브러리의 의존성을 pom.xml 파일에 추가

<!-- 파일 업로드 처리를 위한 의존성 라이브러리 -->

<dependency>

           <groupId>commons-fileupload</groupId>

           <artifactId>commons-fileupload</artifactId>

           <version>1.3.1</version>

</dependency>

 

2)파일 업로드를 처리해 줄 수 있는 CommonsMultipartFile 클래스의 bean을 추가

=>servlet-context.xml 파일에 추가

<!-- 파일 업로드를 처리할 Bean(spring이 생성하고 관리하는 Instance)을 생성 -->

<beans:bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver"

           id = "multipartResolver">

</beans:bean>

 

3)DAO 클래스에 데이터를 삽입하기 위한 메소드를 생성하고 추가

//데이터 1개를 삽입하는 메소드

public int insertItem(Item item) {

           sessionFactory.getCurrentSession().save(item);

           return 1;

}

 

4)ItemService 인터페이스에 데이터를 삽입하기 위한 메소드를 선언

//데이터 삽입(파일 업로드) 처리를 위한 메소드

public int insertItem(MultipartHttpServletRequest request);

 

5)ItemServiceImpl 클래스에 데이터를 삽입하기 위한 메소드를 구현

           @Override

           @Transactional

           public int insertItem(MultipartHttpServletRequest request) {

                       //파라미터 읽기

                       String itemid = request.getParameter("itemid");

                      String itemname = request.getParameter("itemname");

                       String price = request.getParameter("price");

                       String description = request.getParameter("description");

                      

                       //Dao 객체의 파라미터 만들기

                       Item item = new Item();

                       item.setItemid(Integer.parseInt(itemid));

                       item.setItemname(itemname);

                       item.setPrice(Integer.parseInt(price));

                       item.setDescription(description);

                      

                       //파일 읽기

                       MultipartFile mf = request.getFile("pictureurl");

                       //업로드할 파일이 있는 경우에만

                       if(mf.isEmpty() == false) {

                                  //원본 파일이름 가져오기

                                  String originName =

                                             request.getFile("pictureurl").getOriginalFilename();

                                  //원본 파일 이름은 여러 개의 파일을 업로드 하다보면 중복될 수 있기 때문에

                                  //파일 이름을 만들 때는 동일한 디렉토리에 저장한다면 중복 되지 않도록

                                  //파일 이름을 생성할 필요가 있습니다.

                                  //기본키와 파일명을 합치는 방법이 있고 UUID 클래스를 이용해서 만드는 방법

                                  String uploadName = itemid + originName;

                                  item.setPictureurl(uploadName);

                                 

                                  //파일을 저장할 경로를 생성

                                  //프로젝트의 내의 경로를 가지고 절대경로를 생성

                                  //프로젝트 내의 경로가 아니면 직접 경로를 작성

                                  String uploadPath = request.getRealPath("/img");

                                  //Servlet 3.0 이상인 경우는

                                  //request.getServletContext().getRealPath("/img")

                                 

                                  //업로드할 File 객체 생성

                                  File file = new File(uploadPath + "\\" + uploadName);

                                  try {

                                             request.getFile("pictureurl").transferTo(file);

                                  } catch (IllegalStateException e) {

                                              // TODO Auto-generated catch block

                                              e.printStackTrace();

                                  } catch (IOException e) {

                                              // TODO Auto-generated catch block

                                              e.printStackTrace();

                                  }

                       }

                      

                       //데이터 삽입

                       return hibernateDao.insertItem(item);

           }

 

6)HomeController 클래스에 insert post 방식으로 요청했을 때 처리를 위한 메소드를 생성

@RequestMapping(value="/insert", method=RequestMethod.POST)

           public String insert(

                                  MultipartHttpServletRequest request,

                                  Model model) {

                       //서비스의 메소드를 호출

                       itemService.insertItem(request);

                      

                       //삽입, 삭제, 갱신 등 새로고침을 했을 때 이전 작업을 다시 수행하면 안되는 경우에는

                       //리다이렉트를 해야 합니다.

                       //리다이렉트를 할 때는 View 이름이 아니고 URL을 작성

                       return "redirect:./";

           }

 

 

7)실행하고 파일을 업로드 했을 때 파일을 확인해야 하는 디렉토리

=>자신의워크스페이스\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\프로젝트이름

 

=>프로젝트는 원래 모양 그대로 있고 실행이 될 때는 프로젝트의 내용을 build 해서 위의 디렉토리에 있는 내용이 실행되는 것입니다.

 

=>프로젝트를 복사해서 다른 곳에서 실행하는 경우 프로젝트를 만들 때 존재했던 파일들은 그대로 있지만 실행 중 생성한 파일들은 없습니다.

개발환경에서 운영환경으로 이전(이 작업을 이행이라고 합니다.)할 때 기존 데이터베이스 내용을 전부 삭제해야 할 때도 있습니다.

 

**WebSocket

=>http https는 연결형 프로토콜이기는 하지만 한 번 요청을 해서 응답을 받으면 연결이 끊어집니다.

=>채팅과 같은 애플리케이션을 만들 때 http https를 이용하는 것은 어렵습니다.

데이터를 여러번 주고 받고자 하는 경우 연결하고 끊고 다시 연결하고 끊고 하는 작업을 반복해야 합니다.

데이터를 주고받는 시간보다 연결과 해제에 많은 자원을 소모합니다.

그래서 등장방법 중의 하나는 애플리케이션을 설치하는 방법이었습니다.

=>순수 웹 환경에서 실시간 양방향 통신을 위한 Spec HTML5에서 추가가 되었는데 이 Spec WebSocket 입니다.

WebSocket은 한 번 연결하면 close 할 때 까지 계속 연결되어 있습니다.

 

=>최근에는 Android iOS에서도 웹 소켓에 접속하는 API가 추가

 

1.클라이언트(웹 브라우저)에서의 사용 방법(자바스크립트)

1)WebSocket 객체 생성

new WebSocket("ws://domain/demo")

 

2)데이터 전송

WebSocket객체.send("데이터")

 

3)데이터 전송받기 - 콜백 사용

WebSocket객체.addEventListener("message", function(e)){

           //매개변수 e가 전송된 데이터입니다.

}

 

4)기타 이벤트

open, close 이벤트

 

5)연결 해제

WebSocket객체.close()

 

2.Spring을 이용한 WebSocket 서버 설정

=>WebSocketHandler 인터페이스를 구현한 클래스를 생성하고 메소드 재정의

 

=>클래스 위에 @EnableWebSocket 이나 설정 파일에 websocket:handlers 태그를 이용해서 웹 소켓 서버 설정

 

3.WebSocketHandler 인터페이스를 구현한 클래스

=>TextWebSocketHandler, AbstractWebSocketHandler

 

4.의존성 라이브러리

spring-websocket

 

5.주의할 점

=>spring websocket은 서블릿 3.0부터 사용 가능

 

6.실습

1)pom.xml 파일에 spring-websocket 의존성 설정

<!-- 웹 소켓 사용을 위한 의존성 라이브러리 -->

<dependency>

           <groupId>org.springframework</groupId>

           <artifactId>spring-websocket</artifactId>

           <version>${org.springframework-version}</version>

</dependency>

 

2)WebSocket 서버 클래스를 생성

=>TextWebSocketHandler 클래스를 상속

=>기본 패키지 안에 생성

=>com.pk.db.util.ChatHandler

 

//Bean 생성을 자동으로 해주기 위한 어노테이션

@Component

//웹 소켓 채팅 서버 클래스

public class ChatHandler extends TextWebSocketHandler {

           //접속한 유저 목록을 가질 List를 생성

           private static List<WebSocketSession> users

                       = new ArrayList<WebSocketSession>();

          

           //클라이언트가 접속했을 때 호출될 메소드

           //매개변수로 대입된 데이터가 접속한 클라이언트

           @Override

           public void afterConnectionEstablished(WebSocketSession session) {

                       //List에 추가

                       users.add(session);

           }

          

           //클라이언트가 접속을 해제했을 때 호출될 메소드

           //매개변수로 대입된 데이터가 접속을 해제한 클라이언트

           @Override

           public void afterConnectionClosed(

                       WebSocketSession session, CloseStatus status) {

                       //List에서 제거

                       users.remove(session);

           }

          

           //메시지가 전송되었을 때 호출되는 메소드

           @Override

           public void handleTextMessage(

                       WebSocketSession session, TextMessage message) {

                       //전송된 메시지를 출력

                       System.out.println(message.getPayload() + "가 전송됨");

                       //전송받은 메시지를 모든 유저에게 다시 전송

                       for(WebSocketSession ses : users) {

                                  try {

                                              ses.sendMessage(new TextMessage(message.getPayload()));

                                  } catch (IOException e) {

                                              e.printStackTrace();

                                  }

                       }

           }

          

}

 

3)ChatHandler 클래스를 URL과 매핑하는 코드를 servlet-context.xml 파일에 작성

=>servlet-context.xml 파일에 websocket 네임스페이스를 추가

 

<!-- WebSocket 클래스와 URL 매핑 -->

<websocket:handlers>

<!-- handler에서 bean id를 작성하고 path는 클라이언트가 접속할 URL -->

           <websocket:mapping handler="chatHandler" path="/chat-ws"/>

</websocket:handlers>

 

4)home.jsp 파일에 채팅 페이지로 이동할 링크를 추가

<a href="chat">WebSocket을 이용한 채팅 구현</a><br/>

 

5)HomeController 클래스에 위의 요청을 처리하는 메소드를 작성

//chat 이라는 요청이 오면 chat이라는 문자열을 가지고 ViewResolver 설정을 확인해서

//뷰 페이지를 결정 - WEB-INF/views/?.jsp

@RequestMapping(value="/chat", method=RequestMethod.GET)

public String chat(HttpServletRequest request, Model model) {

           //뷰이름을 리턴

           return "chat";

}

 

6)views 디렉토리에 chat.jsp 파일을 만들고 작성

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

    pageEncoding="UTF-8"%>

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>채팅</title>

<style>

           #chatArea{

                       width:200px;

                       height:100px;

                       overflow-y:auto;

                       border:1px solid black;

           }

</style>

</head>

<body>

           <a href="./">메인화면으로 이동</a><br />

           이름<input type="text" id="nickname"/>

           <input type="button" id="enterbtn" value="입장"/>

           <input type="button" id="exitbtn" value="나가기"/>

          

           <h1>채팅 창</h1>

           <div id="chatArea">

                       <div id="chatmessagearea"></div>

           </div>

           <br />

          

           <input type="text" id="message"/>

           <input type="button" id="sendbtn" value="전송"/>

          

           <script>

                       //웹 소켓 변수

                       var wsocket

                      

                       //변수에 이름을 기재하고 함수를 대입하면

                       //이 함수를 만들고 난 후 뒤에서 사용가능해집니다.

                       //function 이름(매개변수){}로 만들면 순서에 상관없이 아무곳에서나 호출 가능

                      

                       //문자열을 출력하는 함수

                       var appendMessage = function(msg){

                                  document.getElementById("chatmessagearea").innerHTML =

                                              msg + "<br/>" +

                                             document.getElementById("chatmessagearea").innerHTML

                       }

                      

                       //이벤트 처리 함수

                       var onOpen = function(){

                                  appendMessage("연결 되었습니다.");

                       }

                       var onClose = function(){

                                  appendMessage("연결 해제되었습니다.");

                                  wsocket.close();

                       }

                       var onMessage = function(evt){

                                  var data = evt.data;

                                  appendMessage(data);

                       }

                       var send = function(){

                                  //입력한 내용을 WebSocket 서버에게 전달하고 message 란은 클리어

                                  var nickname = document.getElementById("nickname").value;

                                  var msg = document.getElementById("message").value;

                                  wsocket.send(nickname + ":" + msg);

                                  document.getElementById("message").value = '';

                       }

                      

                       //웹 소켓 연결함수

                       var connect = function(){

                                  //http://localhost:9000/db/chat-ws - 자기 컴퓨터에서만 접속

                                  wsocket = new WebSocket("ws://localhost:9000/db/chat-ws")

                                  //이벤트 핸들러 연결

                                  wsocket.addEventListener("open", onOpen);

                                  wsocket.addEventListener("message", onMessage);

                       };

                      

                       //message 입력란에서 키보드 이벤트가 발생하면

               document.getElementById("message").addEventListener("keypress",

                                              function(e){

                                  //enter를 누르면 send() 호출

                                  event = e || window.event;

                                  var keycode = (event.keyCode?event.keyCode:event.which);

                                  if(keycode == 13){

                                              send()

                                  }

                                  event.stopPropagation();

                       })

                      

                       //버튼들의 이벤트 처리

                      document.getElementById('sendbtn').addEventListener("click", function(e){

                                  send();

                       })

                      document.getElementById('enterbtn').addEventListener("click", function(e){

                                  connect();

                       })

                      document.getElementById('exitbtn').addEventListener("click", function(e){

                                  onClose();

                       })

          

           </script>

</body>

</html>

 

7)pom.xml 파일의 서블릿 설정을 2.5에서 3.1.0으로 수정

<!-- Servlet -->

<dependency>

           <groupId>javax.servlet</groupId>

           <artifactId>javax.servlet-api</artifactId>

           <version>3.1.0</version>

</dependency>

 

**로그인 기능 추가

1.데이터베이스에 접속해서 로그인 처리를 테이블을 생성하고 샘플 데이터를 입력

CREATE TABLE  member(

           num number(10),

           userid varchar2(100) UNIQUE,

           userpw varchar2(100) NOT NULL,

           nickname varchar2(100),

           PRIMARY KEY (num)

);

 

INSERT INTO MEMBER values(1, 'root', '1234', '관리자');

INSERT INTO MEMBER values(2, 'hhh', '1234', '');

INSERT INTO MEMBER values(3, 'jessica', '1234', '제시카');

 

COMMIT;

 

SELECT * FROM MEMBER;

 

2.테이블과 매핑할 DTO 클래스를 생성

=>com.pk.db.domain.Member

 

package com.pk.db.domain;

 

public class Member {

           private int num;

           private String userid;

           private String userpw;

           private String nickname;

          

           public int getNum() {

                       return num;

           }

           public void setNum(int num) {

                       this.num = num;

           }

           public String getUserid() {

                       return userid;

           }

           public void setUserid(String userid) {

                       this.userid = userid;

           }

           public String getUserpw() {

                       return userpw;

           }

           public void setUserpw(String userpw) {

                       this.userpw = userpw;

           }

           public String getNickname() {

                       return nickname;

           }

           public void setNickname(String nickname) {

                       this.nickname = nickname;

           }

          

          

}

 

3.dao 패키지와 클래스와 데이터베이스 테이블을 매핑시키는 xml 파일을 생성

=>member.hbm.xml

 

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

<!DOCTYPE hibernate-mapping PUBLIC

           "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

           "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

 

<hibernate-mapping package="com.pk.db.domain">      

           <class name="Member" table="Member">

                       <id name="num" column="num">

                       </id>

                       <property name="userid" column="userid" />

                       <property name="userpw" column="userpw" />

                       <property name="nickname" column="nickname" />

           </class>

</hibernate-mapping>

 

4.Hibernate 설정 파일을 등록하는 코드를 root-context.xml 파일에 추가

<value>com/pk/db/dao/member.hbm.xml</value>

 

5.Hibernate 사용을 위한 Dao 클래스를 만들고 로그인 관련 메소드를 작성

=>dao/MemberDao

@Repository

public class MemberDao {

           //하이버네이트 사용 관련 객체를 주입받기

           @Autowired

           private SessionFactory sessionFactory;

          

           //로그인 관련 메소드

           //id를 매개변수로 받아서 일치하는 데이터가 있는지 찾아옵니다.

           public Member login(Member member) {

                       //userid 가 기본키가 아니라서

                       //SQL을 이용해서 직접 조회

                       List<Member> list =

                                  (List<Member>)sessionFactory.getCurrentSession()

                                  .createSQLQuery("select * from member where userid=:userid")

                                  .addEntity(Member.class)

                                  .setString("userid", member.getUserid())

                                  .list();

                       //조회된 데이터가 없으면 null을 리턴하고 조회된 데이터가 있으면 데이터를 리턴

                       if(list.size() == 0) {

                                  return null;

                       }else {

                                  return list.get(0);

                       }

           }

}

 

6.home.jsp 파일에 로그인과 로그아웃 링크를 생성

=>로그인에 성공하면 member 라는 속성에 회원정보를 저장할 것임

=>로그인 여부는 session member라는 속성에 데이터가 있으면 로그인 된 것이고 그렇지 않으면 로그인이 되지 않은 것으로 간주

 

           <c:if test="${member == null}">

                       <a href="login">로그인</a><br/>

           </c:if>

           <c:if test="${member != null}">

                       ${member.nickname} <a href="logout">로그아웃</a><br/>

           </c:if>

 

7.login 요청이 GET 방식으로 오면 login 페이지로 포워딩 하도록 메소드를 HomeController에 작성

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

    pageEncoding="UTF-8"%>

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>로그인</title>

</head>

<body>

           <form method="post" id="loginform">

                       아이디<input type="text" id="userid" name="userid"

                       required="required"/><br/>

                       비밀번호<input type="text" id="userpw" name="userpw"

                       required="required"/><br/>

                       <input type="submit" value="전송"/>

           </form>

</body>

</html>

 

8.MemberService 인터페이스를 만들고 로그인 처리 메소드를 선언

public interface MemberService {

           //로그인 처리 메소드

           public Member login(HttpServletRequest request);

}

 

9.MemberService 인터페이스를 구현한 MemberServiceImpl 클래스를 만들고 로그인 처리 메소드를 구현

@Service

public class MemberServiceImpl implements MemberService {

           @Autowired

           private MemberDao memberDao;

          

           @Override

           @Transactional

           public Member login(HttpServletRequest request) {

                       Member member = null;

                      

                       //파라미터 읽기

                       String userid = request.getParameter("userid");

                       String userpw = request.getParameter("userpw");

                      

                       //member에 인스턴스를 대입하고 userid를 설정

                       member = new Member();

                       member.setUserid(userid);

 

                       //userid에 해당하는 데이터 찾아오기

                       member = memberDao.login(member);

                       //userid에 해당하는 데이터가 있다면

                       if(member != null) {

                                  if(member.getUserpw().equals(userpw)) {

                                              //로그인 성공한 경우는 session에 로그인 정보를 저장

                                              //member.setUserpw(null);

                                             request.getSession().setAttribute("member", member);

                                  }else {

                                              //로그인 실패

                                              member = null;

                                  }

                       }

                      

                       return member;

           }

 

}

 

10.HomeController에서 login 요청이 POST 방식으로 오면 처리하는 메소드를 생성

1)새로운 서비스를 주입받는 코드를 작성

@Autowired

private MemberService memberService;

 

2)요청을 처리하는 메소드를 생성

@RequestMapping(value="/login", method=RequestMethod.POST)

           public String login(HttpServletRequest request, Model model,

                                  RedirectAttributes attrs) {

                       //RedirectAttributes  redirect 할 때 1번만 사용하는 데이터를

                       //저장할 수 있는 Spring이 제공하는 클래스

                      

                       //서비스의 메소드 호출

                       Member member = memberService.login(request);

                       //로그인 처리도 redirect로 이동

                       if(member == null) {

                                  //로그인 실패의 경우 msg를 저장하고 login으로 다시 이동

                                  attrs.addFlashAttribute(

                                              "msg", "없는 아이디이거나 잘못된 비밀번호입니다.");

                                  return "redirect:login";

                       }else {

                                  //로그인 성공이면 메인 페이지로 이동

                                  return "redirect:./";

                       }

           }

 

11.login.jsp 파일에 로그인 실패 메시지를 출력할 영역을 생성

<div>${msg}</div>

 

12.로그아웃 구현

=>login 된 사실을 Session에 데이터를 저장해서 그 데이터를 확인해서 하게 됩니다.

=>logout Session에 저장한 데이터를 삭제하면 됩니다.

데이터 1개를 삭제할 때는 session.removeAttribute("key");

세션 전체를 삭제하고자 할 때는 session.invalidate();

일정 시간 동안 세션을 사용하지 않으면 세션을 자동삭제하고자 하는 경우에는 web.xml 파일에 session-config 설정을 추가하면 되는데 시간의 단위는 분입니다.

 

1)HomeController 클래스에 logout을 처리하는 메소드를 추가

//로그아웃을 처리하는 메소드

           @RequestMapping(value="/logout", method=RequestMethod.GET)

           public String logout(HttpServletRequest request,

                       HttpSession session) {

                       //Session 객체 만들기

                       //request.getSession() 해도 되고 Controller 의 요청 처리 메소드에

                       //매개변수로 추가해도 됩니다.

                      

                       //세션 초기화

                       session.invalidate();

                       //로그인 과 로그아웃도 redirect를 합니다.

                       return "redirect:./";

           }

 

2)web.xml 파일에 5분동안 세션을 사용하지 않으면 세션을 자동 초기화해주는 설정을 추가

=>모바일 페이지에서는 길게 설정하는 편이고 일반 PC 용 페이지는 조금 짧게 설정합니다.

 

           <!-- 세션을 자동 초기화 해주는 설정 -->

           <session-config>

                       <session-timeout>5</session-timeout>

           </session-config>

 

 

13.메인 화면의 데이터 출력하는 부분을 수정

1)메인화면의 데이터 출력 영역의 크기를 제한

=>출력하는 데이터를 div 태그로 감싸고 div 태그의 높이를 설정한 후 overflow 속성을 이용해서 스크롤 바가 생기도록 만들어주면 됩니다.

           <div id="display" align="center">

                       <table border="1" align="center">

                                  <tr class ="header">

                                              <th width='80'>상품ID</th>

                                              <th width='160'>상품이름</th>

                                              <th width='80'>가격</th>

                                  </tr>

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

                                              <tr class="record">

                                                         <td align='center'>${item.itemid }</td>

                                                         <td >&nbsp;&nbsp;

                                                                     <%-- <a href="detail?itemid=${item.itemid }">${item.itemname }</a> --%>

                                                                     <a href="detail/${item.itemid}">${item.itemname}</a>

                                                         </td>

                                                         <td align="right">${item.price }&nbsp;&nbsp;</td>

                                              </tr>

                                  </c:forEach>

                       </table>

           </div>

 

2)데이터베이스에서 여러 개의 데이터를 조회

=>데이터베이스는 순차적으로 저장하는 List 구조가 아닙니다.

=>여러 개의 데이터를 조회할 때는 정렬을 고려해야 합니다.

 

3)데이터베이스의 데이터를 조회하는 서비스를 구현

=>자주 변경되는 데이터가 아닌 경우 - 클라이언트가 요청할 때 마다 애플리케이션 서버가 DB서버에게 sql 을 전송해야 하는가?

=>애플리케이션 서버가 DB에게 주기적으로 query를 전송하고 클라이언트의 요청은 애플리케이션 서버의 데이터로 처리하거나 클라이언트에 저장해두고 처리 하는 방식?

 

=>ItemServiceImpl 클래스의 allItem 메소드를 수정

public List<Item> allItem(HttpServletRequest request) {

           //Dao의 메소드에 파라미터가 없는 경우는 Dao 메소드를 호출해서 리턴

           //return itemDao.allItem();

           List<Item> list = hibernateDao.allItem();

           //list의 데이터를 정렬할 때는 list.sort()를 호출하면 되는데 이 경우는

//list에 속한 데이터에 Comparable 인터페이스가 implements 되어 있어야 합니다.

//그렇지 않은 경우는 Comparator 인터페이스를 구현한 인스턴스를 대입해주어야 합니다.

                       //itemid의 내림차순 - itemid는 정수

                       Comparator<Item> comp = new Comparator<Item>() {

                                  @Override

                                  public int compare(Item arg0, Item arg1) {

                                              // TODO Auto-generated method stub

                                              return arg1.getItemid() - arg0.getItemid();

                                  }

                       };

                       list.sort(comp);

                       return list;

           }

 

 

 

 

**AOP(관점 지향 프로그래밍 - Aspect Orientied Programming)

=>공통관심사항(common - cross cutting concern) 과 비지니스로직(core concern)을 분리해서 구현한 후 설정파일이나 어노테이션을 이용해서 결합을 시켜나가는 프로그래밍 방식

=>복잡한 로직을 구현할 때 이 방식을 취합니다.

파이썬에서도 어노테이션을 이용해서 이러한 구현이 어느정도 가능합니다.

=>spring에서는 url에 반응하는 HandlerInterceptor method 호출에 반응하는 AOP 2가지 형태로 구현

 

**HandlerInterceptor

=>AOP 구현을 위해 제공되는 인터페이스

1.메소드

1)preHandle: Controller의 요청 처리 메소드를 호출하기 전에 호출되는 메소드로 이 메소드에서 true를 리턴하면 Controller의 요청 처리 메소드로 이동하고 false를 리턴하면 Controller의 요청 처리 메소드로 가지 않습니다.

 

2)postHandle: Controller의 요청 처리 메소드가 처리를 전부 수행하고 View로 이동하기 직전에 호출되는 메소드로 예외가 발생하면 호출되지 않습니다.

 

3)afterCompletion: 요청을 전부 처리하고 난 후 호출되는 메소드로 예외 발생여부에 상관없이 무조건 호출되는 메소드

 

2.설정

1)모든 요청에 반응

<mvc:interceptors>

           <ref bean="인터셉터의 id"/>

</mvc:interceptors>

 

2)특정 URL 패턴에 반응

<mvc:interceptors>

           <mvc:interceptor>

                       <mvc:mapping path="URL 패턴"/>

                       <ref bean="인터셉터의 id"/>

           </mvc:interceptor>

</mvc:interceptors>

 

=>mvc:mapping ref bean 의 순서를 변경하면 안됨

 

3.chat 요청으로 이동할 때 로그인이 되어 있지 않으면 로그인 페이지로 이동하도록 interceptor를 생성

1)HandlerInterceptor 인터페이스를 implements 한 클래스를 기본 패키지 안에 생성

=>com.pk.db.util.AuthInterceptor

//클래스 이름에 Adapter가 붙는 클래스는

//Adaptor를 제외한 인터페이스가 존재하는데

//인터페이스는 모든 메소드를 재정의 해야 하고 Adapter 클래스는 필요한 메소드만

//재정의하면 됩니다.

//Bean을 자동 생성해주는 어노테이션

@Component

public class AuthInterceptor extends HandlerInterceptorAdapter {

           @Override

           public boolean preHandle(

                       HttpServletRequest request,

                       HttpServletResponse response,

                       Object handle) {

                       boolean result = false;

                      

                       //로그인이 안된 것을 확인

                      if(request.getSession().getAttribute("member") != null) {

                                  result = true;

                       }else {

                                  try {

                                              //로그인이 되어 있지 않으면 로그인 페이지로 이동

                                              response.sendRedirect("login");

                                  } catch (IOException e) {

                                              // TODO Auto-generated catch block

                                              e.printStackTrace();

                                  }

                       }

                       return result;

           }

          

           @Override

           public void postHandle(

                       HttpServletRequest request,

                       HttpServletResponse response,

                       Object handle,

                       ModelAndView mav) {

                       System.out.println("Controller의 요청을 정상적으로 처리");

                       //로그 기록하는 경우가 많습니다.

           }

}

 

2)servlet-context.xml 파일에 interceptor 설정하는 코드를 추가

<!-- interceptor 설정 : chat으로 이동할 때 interceptor가 동작하도록 설정 -->

           <interceptors>

                       <interceptor>

                                  <mapping path="/chat"/>

                                  <beans:ref bean="authInterceptor" />

                       </interceptor>

           </interceptors>

 

4.chat.jsp파일에서 이름을 입력하지 않고 로그인 한 유저의 nickname을 이용하기

=>로그인을 하면 sessionmember라는 이름으로 Member객체가 저장되어 있음

자바스크립트에서 메시지를 전송하는 send메소드를 수정

           <!-- 이름<input type="text" id="nickname"/> --> 주석처리

 

 

                       var send = function(){

                                  //입력한 내용을 websocket서버에게 전달하고 message 란은 클리어

                                  //var nickname = document.getElementById("nickname").value;

                                  var nickname = '${member.nickname}';

                                  var msg = document.getElementById("message").value;

                                  wsocket.send(nickname+":"+msg);

                                  document.getElementById("message").value="";

                       }

 

5.chat으로 이동할려고 했는데 로그인이 되어 있지 않아서 로그인 페이지로 이동한 후 로그인에 성공하면 chat으로 이동하도록 해주는 설정을 추가

=>로그인 페이지로 이동할 때 메시지 저장해서 이동

=>인터셉터에서 이동할려고 했던 주소를 세션에 저장

=>로그인 성공했을 때 세션에 저장된 데이터를 확인해서 그 페이지로 이동하도록 해주어야 합니다.

 

1)    인터셉터의 preHandle메소드 수정

AuthInterceptor.java

           // Controller 가기 전에 호출되는 메소드

           @Override

           public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handle) {

                       boolean result = false;

                       // 로그인 안된 것을 확인

                       if (request.getSession().getAttribute("member") != null) {

                                  // true를 리턴하도록 만들면 원래 처리를 하러 이동

                                  result = true;

                       } else {

                                  try {

                                             

                                              //로그인 페이지로 이동할 때 메시지 저장

                                              request.getSession().setAttribute("msg", "로그인이 되어야 가능한 서비스입니다.");

                                              //요청 url을 확인

                                              String requestURI = request.getRequestURI();

                                              String contextPath = request.getContextPath();

                                              String command = requestURI.substring(contextPath.length());

                                             

                                              //파라미터 가져오기

                                              String queryString = request.getQueryString();

                                              //파라미터가 있으면 command뒤에 붙이기

                                              if(queryString != null) {

                                                         command = command +"?"+queryString;

                                              }

                                              //세션에 command저장

                                              request.getSession().setAttribute("dest", command);

                                              // 로그인 되어 있지 않으면 로그인 페이지로 이동

                                              response.sendRedirect("login");

                                  } catch (IOException e) {

                                              e.printStackTrace();

                                  }

 

                       }

                       return result;

           }

 

클릭시 =>

 

2)HomeControllerloginPOST로 처리하는 메소드를 수정

=>login성공했을 때 sessiondest값이 있으면 dest로 이동하도록 만들어 주저야 합니다.

이동한 후에는 dest값을 삭제해야 합니다.

           @RequestMapping(value = "/login", method = RequestMethod.POST)

           public String login(HttpServletRequest request, Model model, RedirectAttributes attrs) {

                       // RedirectAttributes redirect를 할 때 한번만 사용하는 데이터를 저장할 수 있는 spring이 제공하는 클래스

 

                       // 서비스의 메소드를 호출

                       Member member = memberService.login(request);

                       // 로그인 처리도 redirect로 이동

                       if (member == null) {

                                  // 로그인 실패의 경우

                                  attrs.addFlashAttribute("msg", "없는 아이디이거나 잘못된 비밀번호입니다.");

                                  return "redirect:login";

                       } else {

                                  //이동할 url이 있는지 확인

                                  String dest = (String) request.getSession().getAttribute("desc");

                                  if(dest != null) {

                                              return "redirect:"+dest;

                                  }

                                  // 로그인 성공이면 메인 페이지로 이동

                                  return "redirect:./";// main페이지로 이동

                       }

 

           }

 

 

**springaop

=>메소드의 수행 전이나 수행 후에 공통된 내용을 수행하고자 하는 경우 사용

=>InterceptorURL에 대해서 반응하기 때무에 웹 프로그래밍에서만 사용이 가능하지 만 AOP는 메소드에 반응하기 떄문에 모든 프로그래밍에서 사용이 가능

AOP를 적용한 클래스를 상속받아서 SPRING이 별도의 클래스를 만들고 인스턴스를 만들어서 메소드 호출을 하도록 합니다.

FINAL CLASS에는 AOP 적용이 안됩니다.

 

=>구현 가능한 Advice(메소드 호출 시점)

Before Advice:메소드 호출전

After Returing Advice:메소드가 수행을 종료하고 리턴 한 후

After Throwing Advice:메소드 수행중 예외가 발생한 경우

After Advice:메소드 수행 후

Around Advice: 메소드 수행 전과 수행 후

 

 

=>구현 방법

xml기반의 pojo클래스 또는 MethodInterceptor 인터페이스를 이용한 구현

@Aspect Annotation을 이용하는 방법

 

 

=>xml 기반이 먼저 만들어 졌고 나중에 어느테이션이 추가된 것입니다.

 

=>필요한 의존성 라이브러리

aspectjweaver, spring-aop, spring-aspects

 

1.xml 스키마를 이용한 aop 설정 방법

1)pom.xml 파일에 aop를 위한 의존성을 추가

2)공통관심 사항을 가진 클래스를 생성해서 메소드를 추가

3)spring설정 파일에 <aop:config>태그를 이용해서 aspect를 설정

4)Advice를 어떤 point cut에 설정을 할 것인지를 지정

 

2.실습

1). aspectjweaver, spring-aop, spring-aspects

 

                       <!-- aop사용을 위한 의존성 라이브러리 -->

                       <dependency>

                                  <groupId>org.aspectj</groupId>

                                  <artifactId>aspectjweaver</artifactId>

                                  <version>1.8.8</version>

                       </dependency>

                       <dependency>

                                  <groupId>org.springframework</groupId>

                                  <artifactId>spring-aop</artifactId>

                                  <version>${org.springframework-version}</version>

                       </dependency>

                       <dependency>

                                  <groupId>org.springframework</groupId>

                                  <artifactId>spring-aspects</artifactId>

                                  <version>${org.springframework-version}</version>

                       </dependency>

 

 

2)Advice(공통 관심 사항을 가진 객체)로 사용할 클래스를 생성하고 메소드 작성

=>기본 패캐지 안에 생성

=>com.pk.db.util.LoggingAdvice

//spring에서는 dto클래스를 제외하고는 클래스 이름 위에 어노테이션을 추가해서

//bean을 자동 생성하도록 합니다.

@Component

public class LoggingAdvice {

           //리턴 타입과 매개변수는 변경할 수 없습니다.

           public Object invoke(ProceedingJoinPoint joinPoint) {

                       //현재 시간을 출력

                       Calendar cal = new GregorianCalendar();

                       Date date = new Date(cal.getTimeInMillis());

                       System.out.println(date+" 요청이 발생함");

                      

                       Object obj = null;

                      

                       try {

                                  obj = joinPoint.proceed();

                       } catch (Throwable e) {

                                  // TODO Auto-generated catch block

                                  e.printStackTrace();

                       }

                       return obj;

           }

}

 

3)servlet-context.xml파일에 aop 네임스페이스를 추가

 

4)servlet-context.xml파일에 aop설정 태그를 추가

       <!-- aop설정

           com.pk.db패키지  내에 있는 Controller 라는 이름으로 끝나는 클래스의

           메소드이름은 상관없고 매개변수갯도 상관없이 호출만 되면

           LoggingAdvice클래스의 invoke메소드가 호출됩니다.-->

           <aop:config>

                       <!-- <aop:aspect id="traceAspect" ref ="Advice 클래스의 bean id"></aop:aspect> -->

                       <aop:aspect id="traceAspect" ref ="loggingAdvice">

                                  <!-- <aop:pointcut expression="동작할 advice " id=""/> -->

                                  <aop:pointcut expression="execution(public * com.pk.db.*Controller.*(..))" id="publicMethod"/>

                                  <aop:around pointcut-ref="publicMethod" method="invoke"/>

                       </aop:aspect>

           </aop:config>

 

 

3.Aspect어노페이션을 이용하는 방법

1)java 클래스에 @Aspect 라는 어노테이션을 추가

2)수행할 메소드 위에 execution을 작성

 

3)스프링 설정 파일에 aop:aspectj-autoproxy태그를 설정

 

4.실습

=>Dao 클래스의 메소드를 호출할 때 현재 시간과 데이터베이스에 접근했다고 로그를 기록

 

 

1)기본 패키지 안에 Advice로 사용할 클래스를 생성 하고 메소드 작성

=>기본패키지.util.LoggingDao

@Component

//aop 클래스라는 어노테이션

@Aspect

public class LoggingDao {

          

           @Around("execution(public * com.pk.db..*Dao.*(..)")

           public Object invoke(ProceedingJoinPoint joinPoint) {

                       // 현재 시간을 출력

                       Calendar cal = new GregorianCalendar();

                       Date date = new Date(cal.getTimeInMillis());

                       System.out.println(date + "  데이터베이스에 접근");

 

                       Object obj = null;

                       try {

                                  obj = joinPoint.proceed();

                       } catch (Throwable e) {

                                  e.printStackTrace();

                       }

                       return obj;

           }

}

 

 

 

2)servlet-context.xml파일에 autoproxy설정 추가

       <!-- 어노테이션을 추가한 aop 클래스가 동작하도록 해주는 설정 -->

           <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

 

 

 

vue,angular.react ->출력

 

openAPI 활용 - 날씨 ,지도

 

자료구조

알고리즘

 

MONGO DB  + node.js

자바에서 mongo db사용할 빠에는 카산들라 로 사용하는 것이 좋다.

 

빅데이터 처리

java ->scala

è  kotlin -안드로이드 / 서버

scala는 안드로이드 를 못한다. 빅데이터 처리쪽은 사용한다.

pythonc-python이다.

 

 

 

python지우고 anaconda 설치

 

 

형상관리 - 변경 사항을 관리

형상관리 -TOOL -GIT HUB

 

SERVELTE:JAVA클래스에 HTML을 추가하는 방식., 첫번째 요청이 오면 컴파일을 해서 클래스를 만들고 인스턴스를 만들어서 이 인스턴스 1개를 자기고 모든 요청을 처리

 

JSP: HTML페이지에 JAVA코드를 추가하는 방식 , 요청이 올 때마다 SERVLET클래스를 만들고 인스턴스를 만들어서 요청을 처리하고 삭제됩니다.

 

REQUEST: 클라이언트의 요청

RESPONSE: 클라이언트의 요청에 대한 서버의 응답

 

파라미터 : 웹 프로그래밍에서 요청한 클라이언트가 넘겨준 데이터

 

JUNIT

AOP-관점 지향 크로그래밍 비즈니스 로직과 공통 관심 사항을 분리해서 프로그래밍 하자는 프로그래밍 방식은 ?

 

 

 

웹표준 : 누구나 동일한 콘텐츠를 사용할 수 있어야 한다.

크로스 브라우징 모든 브라우저에서 동일한 콘텐츠를 사용할 수 있어야 한다.

반응형 웹 디자인: 화면 크기에 상관없이 동일한 콘텐츠를 사용할 수 있어야 한다.

 

N- screen :디바이스 종류에 상관없이 동일한 콘텐츠를 사용할 수 있어야 한다.

 

 

ajax : 비동기적으로 서버에서 데이터를 받아오는 자바스크립트 기술

화면 전체를 갱신하지 않고 데이터를 받아서 화면의 일부분만 갱신하는 기술

 

 

open api 의 표준 데이터 포맷

 

-json: 자바스크립트의 데이터 표현 방법

-xml: 태그를 이용한 데이터 표현 방법

 

내부보안 : 건물안에서

시설보안 : 건물

운영보안 : 운영하면서

 

 

소프트웨어는 비용으로 썬다.

 

white box test:내부 구조를 테스트, 반복문이나 조건문 등을 테스트

black box test:기능 테스트 ., 입력이 주어지면 올바른 결과가 나왔는지만 테스트

 

validation test(검증 시험)

alpha test :개발자의 장소에서 사용자가 테스트

beta test : 사용자의 장소에서 사용자가 테스트

 

 

sqlmapper: sql과 자바코드의 분리 - 대표적으로 mybatis

orm: 테이블과 클래스를 매핑, 테이블의 행과 객체를 매핑 - 대표적으로 hiberante

 

=>si업계는 sqlmapper솔루션 업체는 orm

si는 남들이 제작해달라고 하는 소프트웨어를 개발 - erp(전사적 자원관리)

solution:특정 문제를 해결하기 위한 소프트웨어

           비슷한 유형의 프로젝트를 여러번 했기 때문에 솔루션을 개발

 

@Controller

 

websocket: web에서 연결형 통신(tcp)을 구현하기 위한 html5 api

 

authentication(인증 ) : 로그인과 관련된 부분

 

authorization: (인가) : 사용권한과 관련된 부분

 

di(의존성 주입)내부에서 사용할 데이터를 외부에서 생성해서 대입받아서 사용

@Autowird가 의존성 주입을 위한 어노테이션

 

개체 무결성 : 기본키는 null이거나 중복될 수 없다.

 

springbean을 자동생섷해주는 어노테이션 4

 

 

어노테이션은 클래스이다.

첫글자 대문자 : class 생성자 예: Sa() -> 생성자

첫글자 소문자 : 메소드        sa()->일하는 것

 

 

텐스플로는 64bit용이여야 한다.

 

 

 

 

python개발환경 3가지 방법

python

anaconda

테노피

 

 

python은 버전이 다르면 계속 설치된다. 자바도 그렇다.

 

idespyder 혹은 / pycharm

jupyter

 

 

반응형

'Study > spring' 카테고리의 다른 글

spring-8  (0) 2020.10.26
spring-6  (0) 2020.10.26
spring-5  (0) 2020.10.23
spring-4  (0) 2020.10.23
spring-3  (0) 2020.10.23
반응형

id, email : 입력

상품번호 : 자동생성

입력 받는 것은 중복체크를 해야 한다.

글번호 -> 일련번호

기본키로 분류나 검색 인덱싱

분류코드 + 일련번호

 

 

**기본키

기본키를 직접 입력받는 경우에는 중복검사를 해주는 것이 좋습니다.

이벤트는 포커스가 잃어버릴 때를 많이 이용하고 이 때 ajaxwebsocket을 이용해서 서버에게 기본키 입력값을 전송하고 서버는 넘어온 기본키 입력 값을 가지고 데이터베이스에서 조회하고 그 결과를 json이나 xml 형태로 클라이언트에게 알려주며 클라이언트느느 그 값을 가지고 중복 여부를 판단해서 처리를 합니다.

 

=>기본키를 일련번호 형태로 자동 생성하는 경우는 auto_incrementsequence를 이용하기도 하고 현재 입력된 번호 중 가장 큰 번호를 찾고 여기에 +1를 해서 생성하는 방법도 있습니다.

이 방법은 일반적으로 비 추천하고 되도록이면 숫자나 문자의 조합을 이용해서 분류의 기능을 갖도록 만드는 것을 권장합니다.

대표적으로 주민번호나 학번

 

**폼의 데이터 전송 시 유효성 검사

=>클라이언트에서의 유효성 검사

클라이언트에서 유효성 검사를 하게 되면 서버로 전송하지 않고 수행을 하기 떄문에 속도나 트래픽 면에서 유리하지만 보안지 되지 않기 때문에 클라이어느가 유효성 검사 로직을 파악할 수 있습니다.

=>폼의 경우는 submit이번트에서 유효성검사하고 유효성 검사를 통과하지 못하면 서버로 전송하지 못하도록 이벤트 객체의 preventDefault()를 호출하면 됩니다

=>가장 많이 수행하는 유효성 검사는 필수 입력 , 중복 검사 통과 여부 , 패턴 일치 , 2개의 값 일치 등이 있습니다.

필수 입력은 ->required에서 해서 sumit에서 안해도 된다.

 

 

실습insert.jsp에 유효성 검사를 위한 코드를 추가

//폼의 데이터를 전송할 때 발생하는 이벤트 처리

           document.getElementById("myform").addEventListener("submit",function(e){

                                  //중복 체크통과 여부 확인

                                  if(idcheck == false){

                                              iddiv.innerHTML = '아이디 중복검사를 하세요.';

                                              iddiv.style.color ='red';

                                              itemid.focus();

                                              //화면 이동을 안한다.

                                              e.preventDefault();

                                              return;

                                  }

                                 

                                  //price 입력란의 숫자만 입력되었는지 체크

                                  //+ - 기호를 앞에 붙일 수 있는지

                                  //,의 경우는 어떻게 할것인지

                                  //number은 모바일만 가능

                                  //길이는 - length, 개수는count

                                  var price = document.getElementById('price');

                                  for(var i = 0; i < price.value.length;i++){

                                              var ch = price.value.charAt(i);

                                              //console.log(ch);

                                              if(i == 0){

                                                         if(!(ch == '+' || ch == '-' || (ch >= '0' && ch <= '9'))){

                                                                     price.focus();

                                                                     alert("가격의 첫번째 자리는 숫자나 +,- 기호여야 합니다.")

                                                                     //화면 이동을 안한다.

                                                                     e.preventDefault();

                                                                     return;

                                                         }

                                              }else if(!(ch>= '0'  && ch <= '9')){

                                                         price.focus();

                                                         alert("가격은 숫자로만 입력하세요.")

                                                         //화면 이동을 안한다.

                                                         e.preventDefault();

                                                         return;

                                              }

                                  }

                       });

 

 

 

 

**spring에서의 file upload처리

=>MultipartFile 타입으로 처리

1. 준비사항

1)comons-fileupload: 라이브러리의 의존성 설정

2) CommonsMultipartResoulver 클래스의 bean을 생성

 

2.MultipartFile

=>파라미터를 직접 이 타입으로 받아도 되고 HttpServletReques대신에

MultipartHttpServletRequst를 이용해서 요청을 받고 getFile(String parameterName)을 이용해서 가져올 수 있습니다.

 

3.실습

1)파일 업로드 처리를 위한 라이브러리의 의존성을 pom.xml 파일에 추가

                       <!-- 파일 업로드 처리를 위한 의존성 라이브러리 -->

                       <dependency>

                                  <groupId>commons-fileupload</groupId>

                                  <artifactId>commons-fileupload</artifactId>

                                  <version>1.3.1</version>

                       </dependency>

                      

2)파일 업로드를 처리해 줄 수 있는 CommonsMultipart

=>servlet-context.xml파일에 추가

 

3)Dao클래스에 데이터를 삽입하기 위한 메소드를 생성하고 추가

          

           //데이터 1개를 삽입하는 메소드

           public int insertItem(Item item) {

                       sessionFactory.getCurrentSession().save(item);

                       return 1;

           }

 

4)ItemService에 인터페이스에 데이터를 삽입하기 위한 메소드를 선언

           //데이터 삽입(파일업로드 ) 처리를 위한 메소드

           public int insertItem(MultipartHttpServletRequest request);

 

5)ItemServiceImpl 클래스에 데이터를 삽입하기 위한 메소드를 구현

annotation자주 사용하는 것이 길거나 할 때 사용한다.

호출할 때 앞뒤에 코드가 들어간다.

           @Override

           @Transactional

           public int insertItem(MultipartHttpServletRequest request) {

                       // 파라미터 읽기

                       String itemid = request.getParameter("itemid");

                       String itemname = request.getParameter("itemname");

                       String price = request.getParameter("price");

                       String description = request.getParameter("description");

                      

                       //Dao 객체의 파라미터 만들기

                       Item item = new Item();

                       item.setItemid(Integer.parseInt(itemid));

                       item.setItemname(itemname);

                       item.setPrice(Integer.parseInt(price));

                       item.setDescription(description);

                      

                       //파일 읽기

                       MultipartFile mf = request.getFile("pictureurl");

                       //업로드할 파일이 있는 경우에만

                       if(mf.isEmpty() == false) {

                                  //원본 파일 이름 가져오기

                                  String originalName = request.getFile("pictureurl").getOriginalFilename();

                                  //원본 파일 이름은 여러개의 파일을 업로드 하다모변 중복될 수 있기 때문에

                                  //파일이름을 만들 때는 동일한 디렉토리에 저장한다면 중복되지 않도록

                                  //파일 이름을 생성할 필요가 있습니다.

                                  //기본키와 파일염을 합치는 방법이 있고 uuid클래스를 이용해서 만드는 방법

                                  String uploadName = itemid + originalName;

                                  item.setPictureurl(uploadName);

                                 

                                  //파일을 저장할 경로를 생성

                                  //프로젝트의 내의 경로를 가지고 절대경로를 생성

                                  //프로젝트 내의 경로가 아니면 직접 경로를 작성

                                  String uploadPath = request.getRealPath("./img");

                                  //servlet 3.0 이을 사용하면 request.getServletContext().getRealPath("./img")

                                 

                                  //업로드할 file객체 생성

                                  File file = new File(uploadPath + "\\" + uploadName);

                                  try {

                                             request.getFile("pictureurl").transferTo(file);

                                  } catch (IllegalStateException e) {

                                              e.printStackTrace();

                                  } catch (IOException e) {

                                              e.printStackTrace();

                                  }

                       }

                      

                       //데이터 삽입

                       return hibernateDao.insertItem(item);

           }

 

 

3)HomeController클래스에 insertfpost방식으로 요청했을 때 처리를 위한 메소드를 생성

 

 

7)실행하고 파일을 업로드 했을 때 파일을 확인해야 하는 디렉토리

자신의 워크스 페이스 \ 프로젝트 이름

 

=>프로젝트는 원래 모양 그대로 있고 실행이 될때는 프로젝트의 내용을 build해서 위의 디렉토리에 있는 내용이 실행되는 것입니다.

 

=>프로젝트를 복사해서 다른 곳에서 실행하는 경우 프로젝트를 만들 때 존재했던 파일들은 그대로 있지만 실행 중 생성한 파일들은 없습니다.

개발환경에서 운영환경으로 이전(이 작업을 이행이라고 합니다.) 할 때 기존 데이터베이스 내용을 전부 삭제해야 할 때도 있습니다.

 

 

 

 

 

applicataion server

db server

file server

 

 

 

**websocket

=>httphttps는 연결형 프로토콜이기는 하지만 한 번 요청을 해서 응답을 받으면 연결이 끊어집니다.

=>채팅과 같은 애플리케이션을 만들 때 httphttps를 이용하는 것은 어려운 작업입니다.

데이터를 여러번 주고 받고자 하는 경우 연결하고 끊고 다시 연결하고 끊고 하는 작업을 반복해야 합닏.

데이터를 주고받는 시간보다 연결과 해제에 많은 자원을 소모합니다.

그래서 등장방법 중의 하나는 애플리케이션을 설치하는 방법이었습니다.

=>순수 웹 환경에서 실시간 양방향 통신을 위한 Spec  HTML5에서 추가가 되었는데 Spec WebSocket입니다.

websocket은 한 번 연결하면 close할 때 까지 계속 연결되어 있습니다.

 

=>최근에는 Andriod ios 에서도 웹 소켓에 접속하는 api가 추가

 

1.클라이언트(웹 브라우저)에서의 사용 방법(자바스크립트)

1)websocket 객체 생성

new WebSocket("ws://domain/demo")

 

2)데이터 전송

websocket객체.send("데이터")

 

3)데이터 전송받기 - 콜백 사용

WebSocket객체.addEventListener("message",function(e){

           //매개변수 e가 전송된 데이터입니다.

});

 

4)기타 이벤트

open, close이벤트

 

 

5)연결 해제

WebSocket객체.close()

 

 

2.spring 을 이용한 websocket서버 설정

=>websocketHandler인터페이스를 구현한 클래스를 생성하고 메소드 재정의

 

=>클래스 위에 @EnableWebScocket이나 설정 파일에 websocket:handlers태그를 이용해서 웹 소켓 서버 설정

 

3.websockethandler인터페이스르 구현한 클래스

=>TextWebSocketHandler, AbstractWebSocketHandler

 

4.의존성 라이브러리

spring-websocket

 

5.주의할점

=>springwebsocket은 서블릿 3.0부터 사용 가능

 

6.실습

1)pom.xml파일에 spring-websocket의존성 설정

                       <dependency>

                                  <groupId>org.springframework</groupId>

                                  <artifactId>spring-websocket</artifactId>

                                  <version>${org.springframework-version}</version>

                       </dependency>

 

 

2)websocket 서버 클래스를 생성

=>TextWebSocketHandler클래스를 상속

=>기본 패지키 안에 생성

=>com.pk.util.ChatHandler

연결 되면 유저 정보 연결하고 연결이 끊어질때 유저정보 끊고 메세지를 왔을 때 전부 다 보내주면 된다.

//Bean생성을 자동으로 해주기 위한 어노테이션

@Component

//웹 소켓 채팅 서버 클래스

public class ChatHandler extends TextWebSocketHandler {

           //접속한 유저 목록을 가질 List를 생성

           private List<WebSocketSession> users = new ArrayList<WebSocketSession>();

          

           //클라이언트가 접속했을 때 호출될 메소드

           //매개변수로  대입된 데이터가 접속한 클라이언트

           @Override

           public void afterConnectionEstablished(WebSocketSession sesssion) {

                       //List에 추가

                       //접속을 했으면 추가

                       users.add(sesssion);

           }

          

           //클라이언트가 해제했을 때 호출될 메소드

           //매개변수로  대입된 데이터가 접속한 클라이언트

           @Override

           public void afterConnectionClosed(WebSocketSession sesssion,CloseStatus status) {

                       //해제된 이후

                       //List에 제거

                       users.remove(sesssion);

           }

          

           //메시지가 전송되었을 대 호출되는 메소드

           @Override

           public void handleTextMessage(WebSocketSession session, TextMessage message) {

                       System.out.println(message.getPayload()+"가 전송됨");

                       for(WebSocketSession ses: users) {

                                  try {

                                              ses.sendMessage(new TextMessage(message.getPayload()));

                                  } catch (IOException e) {

                                              e.printStackTrace();

                                  }

                       }

           }

}

 

3)ChatHandler클래스를 url과 매핑하는 코드를 servlet-context.xml파일에 작성

=>servlet-context.xml파일에 websocket넴임스페이스를 추가

           <!-- websocket 클래스와  url매핑 -->

           <websocket:handlers>

                       <!-- handler에서 bean id를 작성하고 path는 클라이언트의 접속할 url -->

                       <websocket:mapping handler="chatHandler" path="/chat-ws"/>

           </websocket:handlers>

 

 

4)home.jsp 파일에 채팅페이지로 이동할 링크를 추가

           <a href="chat">websocket을 이용한 채팅 구현</a><br/>

 

5)HomeController클래스의 위의 요청을 처리하는 메소드를 작성

           //chat이라는 요청이 오면 chat이라는 문자열을 가지고 ViewResolver설정을 확인해서

           //뷰 페이지를 결정 -web-inf/views/?.jsp

           @RequestMapping(value="/chat",method = RequestMethod.GET)

           public String chat(MultipartHttpServletRequest request, Model model) {

                       return "chat";

           }

 

6) views디렉토리에 chat.jsp파일을 만들고 작성

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

    pageEncoding="UTF-8"%>

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>채팅</title>

<style type="text/css">

           #chatArea{

                       width: 200px;

                       height: 100px;

                       overflow-y : auto;

                       border : 1px solid black;

           }

</style>

</head>

<body>

           <!--  -->

           <a href ="./">메인화면으로 이동</a>

           이름<input type="text" id="nickname"/>

           <input type="button" id="enterbtn" value="입장"/>

           <input type="button" id="exitbtn" value="나가기"/>

          

           <h1>채팅창</h1>

           <div id="chatArea">

                       <div id="chatmessagearea"></div>

           </div>

           <br/>

          

           <input type="text" id="message"/>

           <input type="button" id="sendbtn" value="전송" />

          

           <script type="text/javascript">

                       //웹 소켓 변수

                       var wsocket;

                      

                       //변수에 ㅇ이름을 기재하고 함수를 대입합면

                       //이 함수를 만들고 난 후 뒤에서 사용가능해집니다.

                       //function이름(매개변수){}로 만들면 순서에 상관없이 아무곳에서나 호출가능

                      

                       //문자열을 출력하는 함수

                       var appendMessage = function(msg){

                                  document.getElementById("chatmessagearea").innerHTML = msg+"<br/>" + document.getElementById("chatmessagearea").innerHTML;

                       }

                      

                       //이번체 처리 함수                    

                       var onOpen = function(){

                                  appendMessage("연결 되었습니다.");

                       }

                      

                       var onClose = function(){

                                  appendMessage("연결 해지되었습니다.");

                                  wsocket.close();

                       }

                      

                       var onMessage = function(evt){

                                  var data = evt.data;

                                  appendMessage(data);

                       }

                      

                       var send = function(){

                                  //입력한 내용을 websocket서버에게 전달하고 message 란은 클리어

                                  var nickname = document.getElementById("nickname").value;

                                  var msg = document.getElementById("message").value;

                                  wsocket.send(nickname+":"+msg);

                                  document.getElementById("message").value="";

                       }

                      

                      

                       //웺 소켓 연결함수

                       var connect = function(){

                                  //http://localhost:9000/db/chat-ws - 자기 컴퓨터에서만 접속

                                  wsocket = new WebSocket("ws://ip주소:9000/db/chat-ws");

                      

                                  //이벤트 핸들러 연결

                                  wsocket.addEventListener("open",onOpen);

                                  wsocket.addEventListener("message",onMessage);

                                  //wsocket.addEventListener("close",onClose);

                       }

                      

                       //message 입력란에어 키보드 이벤트가 발생하면

           document.getElementById("message").addEventListener("keypress",function(e){

                                  //enter를 누르면 send()호출

                                  event = e || window.event;

                                  var keycode = (event.keyCode?event.keyCode:event.widch);

                                  if(keycode == 13){

                                              send();

                                  }

                                  event.stopPropagation();

                       });

                       //버튼 들의 이번트 처리

               document.getElementById('sendbtn').addEventListener('click',function(){

                                  send();

                       });

               document.getElementById('enterbtn').addEventListener('click',function(){

                                  connect();

                       });

                 document.getElementById('exitbtn').addEventListener('click',function(){

                                  onClose();

                       });

           </script>

</body>

</html>

 

7)pom.xml파일의 서블릿 설정을 2.53.1.0으로 수정

                       <dependency>

                                  <groupId>javax.servlet</groupId>

                                  <artifactId>javax.servlet-api</artifactId>

                                  <version>3.1.0</version>

                       </dependency>

 

 

 

**로그인 기능 추가

1.데이터베이스에 접속해서 로그인 처리를 테이블을 생성하고 샘플 데이터를 입력

CREATE TABLE MEMBER(

num NUMBER(10),         

userid varchar2(100) UNIQUE,

userpw varchar2(100) NOT NULL,

nickname varchar2(100),

           PRIMARY KEY (num)

);

 

 

INSERT INTO MEMBER VALUES (1,'root','1234','관리자');

INSERT INTO MEMBER VALUES (2,'hhh','1234','김');

INSERT INTO MEMBER VALUES (3,'jessica','1234','제시카');

 

COMMIT;

 

 

2.테이블과 매핑할 dto클래스를 생성

=>com.pk.db.domain.Member

@Data

public class Member {

           private int num;

           private String userid;

           private String userpw;

           private String nickname;

}

 

3.dao 패키지와 클래스와 데이터베이스 테이블을 매핑시키는 xml파일을 생성

=>member.hbm.xml

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

<!DOCTYPE hibernate-mapping PUBLIC

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.pk.db.domain">

           <class name="Member" table="MEMBER">

                       <id name="num" column="NUM">

                       </id>

                       <property name="userid" column="USERID" />

                       <property name="userpw" column="USERPW" />

                       <property name="nickname" column="NICKNAME" />

           </class>

</hibernate-mapping>

 

4.Hibernate설정 파일을 등록하는 코드를 root-context.xml파일에 추가

                                             <value>com/pk/db/dao/member.hbm.xml</value>

 

5.hibernate 사용을 위한 dao클래스를 만들고 로그인 관련 메소드를 작성

=>dao.MemberDao

@Repository

public class MemberDao {

 

           @Autowired

           private SessionFactory sessionFactory;

          

           //로그인 관련 메소드

           //idpw를 매개변수로 받아서 일치하는 데이터가 있는지 찾아옵니다.

           public Member login(Member member) {

                      

                       //setString(0,member.getUserid())

                       //userid가 기보ㄴ키가 아니라서 sql을 이용해서 직접 조회

                       List<Member> list = sessionFactory.getCurrentSession().createSQLQuery("select * from Member where userid=:userid").addEntity(Member.class).setString("userid",member.getUserid()).list();

                       if(list == null || list.size() < 1) return null;

                       return list.get(0);

           }

}

 

6.home.jsp 파일에 로그인과 로그아웃 링크를 생성

=>로그인에 성공하면 member라는 속성에 회원정보를 저장할 것임

=>로그인 여부는 sessionmember라는 속성에 데이터가 있으면 로그인 된것이고 그렇지 않으면 로그인이 되지 않은 것으로 간주

빨간 표시가 나면 지우고 다시 입력하면 된다.예쩐 jsp에서 나오는 것이 남을 수 있다.

           <c:if test ="${member == null} ">

                       <a href="login">로그인</a>

           </c:if>

           <c:if test = "${member != null }">

                       ${member.nickname} <a href="logout">로그아웃</a>

           </c:if>

 

7.login요청이 Get방식으로 오면 login페이지로 포워딩 하도록 메소드를 HomeController에 작성

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

    pageEncoding="UTF-8"%>

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>로그인</title>

</head>

<body>

           <form method="post" id="loginform">

                       아이디 <input type="text" id="userid" name ="userid" required="required">

                       비밀번호 <input type ="text" id="userpw" name ="userpw" required="required">

                       <input type="submit" value="전송">

           </form>

</body>

</html>

 

8.MemberService인터페이스를 만들고 로그인 처리 메소드를 선언

public interface MemberService {

           //로그인 처리 메소드

           public Member login(HttpServletRequest request);

}

 

 

9.MemberService implements를 한 MemberServiceImpl클래스를 만들고 로그인 처리 메소드를 구현

package com.pk.db.service;

 

import javax.servlet.http.HttpServletRequest;

import javax.transaction.Transactional;

 

import org.apache.ibatis.executor.ReuseExecutor;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

 

import com.pk.db.dao.MemberDao;

import com.pk.db.domain.Member;

 

@Service

public class MemberServiceImpl implements MemberService {

          

           @Autowired

           public MemberDao memberDao;

          

           @Override

           @Transactional

           public Member login(HttpServletRequest request) {

                       Member member = null;

                      

                       //파라미터 읽기

                       String userid= request.getParameter("userid");

                       String userpw = request.getParameter("userpw");

                      

                       //userid에 해당하는 데이터 찾아오기

                       member = memberDao.login(member);

                       //userid에 해당하는 데이터가 있다면

                       if(member != null) {

                                  if(member.getUserpw().equals(userpw)) {

                                              //로그인 성공한 경우는 session에 로그인 정보를 저장

                                              member.setUserpw(null);//비밀번호를 저장하고 싶지 않았을 경우

                                             request.getSession().setAttribute("member", member);

                                  }else {

                                              //로그인 실패

                                              member  = null;

                                  }

                       }

                      

                       return member;

           }

 

}

 

10. HomeController에서 login요청이 post방식으로 오면 처리하는 메소드를 생성

1)새로운 서비스를 주입받는 코드를 작성

@Autowired

private MemberService memberService;

 

 

2)요청을 처리하는 메소드를 생성

           @RequestMapping(value="/login",method = RequestMethod.POST)

           public String login(HttpServletRequest request, Model model,RedirectAttributes attrs) {

                       //RedirectAttributes redirect를 할 때 한번만 사용하는 데이터를 저장할 수 있는 spring이 제공하는 클래스

                      

                       //서비스의 메소드를 호출

                       Member member = memberService.login(request);

                       //로그인 처리도 redirect로 이동

                       if(member == null) {

                                  //로그인 실패의 경우

                                  attrs.addFlashAttribute("msg", "없는 아이디이거나 잘못된 비밀번호입니다.");

                                  return "redirect:login";

                       }else {

                                  //로그인 성공이면 메인 페이지로 이동

                                  return "redirect:./";//main페이지로 이동

                       }

                      

           }

 

 

11. login.jsp파일에 로그인 실패 메시지를 출력할 영역을 생성

 

 

반응형

'Study > spring' 카테고리의 다른 글

spring-8  (0) 2020.10.26
spring-7  (0) 2020.10.26
spring-5  (0) 2020.10.23
spring-4  (0) 2020.10.23
spring-3  (0) 2020.10.23
반응형

이전 프로젝트

 

pom.xml->web.xml->각종 설정

 

**하이버네이트 설정

1.    하이버네티으를 사용하는 Dao클래스 생성

=>기본 패키지.dao.HibernateDao

package com.pk.db.dao;

 

import java.util.List;

 

import org.hibernate.SessionFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Repository;

 

import com.pk.db.domain.Item;

 

//Bean(스프링이 생성하는 인스턴스)을 자동생성해주고

//데이터 관련된 클래스라는 알려주기 위한 어노테이션

@Repository

public class HibernateDao {

           //하이버네이트를 사용할 수 잇는 인스턴스를 주입

           @Autowired

           private SessionFactory sessionFactory;

          

           //전체 데이터 가져오는 메소드

           public List<Item> allItem(){

                       return sessionFactory.getCurrentSession().createCriteria(Item.class).list();

           }

          

           //데이터를 1개를 가져오는 메소드

           public Item getItem(int itemid) {

                       return sessionFactory.getCurrentSession().get(Item.class, itemid);

           }

}

 

2.    ItemServiceImpl클래스를 수정

=>hibernatedao를 주입받고 itemdao자리를 hibernateDao로 수정

package com.pk.db.service;

 

import java.util.List;

 

import javax.servlet.http.HttpServletRequest;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

 

import com.pk.db.dao.HibernateDao;

import com.pk.db.dao.ItemDao;

import com.pk.db.domain.Item;

 

//bean을 자동생성해주는 어노테이션

@Service

public class ItemServiceImpl implements ItemService {

 

      //ItemDao타입의 bean이 있으면 자동으로 주입시켜주는 어노테이션

      @Autowired

      private ItemDao itemDao;

     

      //hibernate 전송하는 bean을 사용 주입

      //동일한 자료형의 bean이 있으면 자동 주입

      @Autowired

      private HibernateDao hibernateDao;

     

      @Override

      public List<Item> allItem(HttpServletRequest request) {

                 //Dao의 메소드에 파라미터가 없는 경우는 Dao 메소드를 출력해서 리턴

                 //return itemDao.allItem();

                 return hibernateDao.allItem();

      }

 

      @Override

      public Item getItem(HttpServletRequest request) {

                 //파라미터 읽어오기

                 String itemid = request.getParameter("itemid");

                 //파라미터를 정수로 변환해서 Dao 메소드를 호출

                 //return itemDao.getItem( Integer.parseInt(itemid));

                return hibernateDao.getItem( Integer.parseInt(itemid));

      }

 

      @Override

      public Item getItem(HttpServletRequest request, int itemid) {

                 //return itemDao.getItem(itemid);

                 return hibernateDao.getItem(itemid);

      }

 

}

 

 

 

 

트랜잭션 오류가 난다.

그래서 serviceimpl@Transactional 추가하기

 

=>처리하는 메소드 위에 트랜잭션 적용을 위한 @Transactional추가

package com.pk.db.service;

 

import java.util.List;

 

import javax.servlet.http.HttpServletRequest;

import javax.transaction.Transactional;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

 

import com.pk.db.dao.HibernateDao;

import com.pk.db.dao.ItemDao;

import com.pk.db.domain.Item;

 

//bean을 자동생성해주는 어노테이션

@Service

public class ItemServiceImpl implements ItemService {

 

      //ItemDao타입의 bean이 있으면 자동으로 주입시켜주는 어노테이션

      @Autowired

      private ItemDao itemDao;

     

      //hibernate 전송하는 bean을 사용 주입

      //동일한 자료형의 bean이 있으면 자동 주입

      @Autowired

      private HibernateDao hibernateDao;

     

      @Override

      @Transactional

      public List<Item> allItem(HttpServletRequest request) {

                 //Dao의 메소드에 파라미터가 없는 경우는 Dao 메소드를 출력해서 리턴

                 //return itemDao.allItem();

                 return hibernateDao.allItem();

      }

 

      @Override

      @Transactional

      public Item getItem(HttpServletRequest request) {

                 //파라미터 읽어오기

                 String itemid = request.getParameter("itemid");

                 //파라미터를 정수로 변환해서 Dao 메소드를 호출

                 //return itemDao.getItem( Integer.parseInt(itemid));

                return hibernateDao.getItem( Integer.parseInt(itemid));

      }

 

      @Override

      @Transactional

      public Item getItem(HttpServletRequest request, int itemid) {

                 //return itemDao.getItem(itemid);

                 return hibernateDao.getItem(itemid);

      }

 

}

 

3.    실행했는데 트랜잭션 적용이 안되면 root-context.xml파일이 있는 트랜잭션 관련 설정을 servlet-context.xml로 이동하고 수정

=>servlet-context.xml에 파일에 tx네임스페이스를 추가

                       <!-- 하이버네이트는 트랜잭션 사용이 필수이기 때문에 추가 -->

           <tx:annotation-driven />

           <beans:bean id="transactionManager"

           class="org.springframework.orm.hibernate5.HibernateTransactionManager">

                       <beans:property name="sessionFactory" ref="sessionFactory" />

      </beans:bean>

 

 

sessionFactoctory가 고리가 생긴다.

 

 

controller 하는 것은 라우팅이다.

알고리즘만 바꾸고 싶으면 service에서 바꾸면 된다.

디비를 바꾸고 싶으면 dao만 수정하면 된다.

 

재사용 할 생각이 있으면  함수

class->배포할 생각

함수는 배포가 안된다. class는 배포가 된다.

여러 사람이 같이 쓸수 있다는 것

함수는 나 혼자 여러번 사용할 려고 한다.

 

파이썬  ->함수

           ->클래스

 

 

iBatis 버전 엎 해서 mybatis로 작성한다.

javaspring -> 이것은 이상한 것이다.

java를 못하면 spring을 잘 할 수 없다.

상중하로 사용하면 안된다.

 

 

스프링 컨트롤러는 뷰에 의존적이지 않습니다.

 

contentType="text/html; charset=UTF-8" =>html하면 html

 

엑셀 파일 뷰를 만들기 위해서는 apache poi 라이브러리를 이용합니다.

엑셀 파일로 출력 결과를 만들고자 하는 경우에는 AbstractXlsView 클래스로부터

상속받은 View 클래스를 이용하면 됩니다.

 AbstractExcelView 클래스는 poi.jar 파일에 포함되어 있습니다.

이 파일을 이용하면 엑셀 파일을 읽을 수 있고 엑셀 파일로 내보낼 수 있습니다.

 AbstractExcelView 클래스로 부터 상속받는 클래스를 만들고 메소드를 재정의 해야

합니다.

protected void buildExcelDocument(Map<String, Object> model, Workbook

workbook, HttpServletRequest request,

HttpServletResponse response) throws Exception

Model은 넘어온 데이터입니다.

Workbook을 이용해서 엑셀파일을 생성됩니다.

Workbook 안에는 Sheet 가 있고 시트 안에는 Row가 있고 row 안에 다시 Cell

있솟니다.

 

poi.jar 파일을 사용하기 위한 dependency pom.xml 파일에 추가

<dependency>

<groupId>org.apache.poi</groupId>

<artifactId>poi</artifactId>

<version>3.16</version>

</dependency>

 

요청이 다운로드 받는 파일이름

 

 

**html 이외의 출력

=>html 이외의 출력을 하고자 하는 경우에는 spring설정 파일에 beanNameViewResolver를 추가해야 합니다.

이 때 기존의 InternalResourceViewResolver의 우선순위를 조정해야 합니다.

=><bean id="Controller에서 리턴한 뷰 이름" class="View 클래스 경로"/>

Controller에서 id에 해당하는 View이름을 리턴하면 class에 설정된 View클래스를 이용해서 내용을 출력하게 됩니다.

 

**Excel출력

=>appache poi라이브러리를 이용

=>AbstractXlsView 클래스를 상속받는 클래스를 만들어서 출력

=>Excel은 파일을 WorkBook이라고 하고 하나의 화면을 Sheet그리고 하나의 행을 Row하나의 칸을 Cell이라고 합니다.

실제 데이터 출력은 Cell에 합니다.

 

 

 Excel출력 실습

1.    html이외의 vIew를 출력할 수 있도록 설정

servlet-context.xml

1)    기존의 ViewReolver를 수정

      <!-- Controller에서 리턴하는 뷰 이름을 가지고 실제 출력할 뷰를 선택하도록 해주는 설정 -->

      <beans:bean

      class="org.springframework.web.servlet.view.InternalResourceViewResolver">

                 <beans:property name="prefix" value="/WEB-INF/views/" />

                 <beans:property name="suffix" value=".jsp" />

                 <!-- 우선순위를 수정 -->

                 <beans:property name="order" value="1"></beans:property>

      </beans:bean>

2)    새로운 ViewResoulver를 추가

<!-- html이외의 출력을 위한 ViewResolver설정 -->

      <beans:bean class="org.springframework.web.servlet.view.BeanNameViewResolver">

                 <beans:property name="order" value="0"></beans:property>

      </beans:bean>

 

2.    Excel 사용을 위한 의존성 라이브러리 설정을 pom.xmldependency에 추가

pom.xml

 

                       <!-- excel출력 라이브러리 -->

                       <dependency>

                                  <groupId>org.apache.poi</groupId>

                                  <artifactId>poi</artifactId>

                                  <version>3.16</version>

            </dependency>

                 

 

3.    home.jsp파일에 엑셀 요청을 생성

<a href="./item.xls">엑셀로 내려받기</a>

 

 

 

4.    HomeContrller클래스에 item.xls처리를 위한 메소드를 추가

     

           @RequestMapping(value="/item.xls",method = RequestMethod.GET)

           public String excel(HttpServletRequest request, Model model) {

                       //서비스 메소드 호출

                       List<Item> list = itemService.allItem(request);                   

//데이터 저장

                       model.addAttribute("list", list);

                       //뷰이름을 리턴

                       return "excel";

      }

5.    Excel출력 뷰를 생성

=>com.pk.db.view.ExcelView

=>AbstractXlsView로 부터 상속

package com.pk.db.view;

 

import java.util.List;

import java.util.Map;

 

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import org.apache.poi.ss.usermodel.Cell;

import org.apache.poi.ss.usermodel.Row;

import org.apache.poi.ss.usermodel.Sheet;

import org.apache.poi.ss.usermodel.Workbook;

import org.springframework.web.servlet.view.document.AbstractXlsView;

 

import com.pk.db.domain.Item;

 

public class ExcelView extends AbstractXlsView {

          

           //엑셀 데이터 출력을 위한 View

           @Override

           //첫번때 매개변수는 COntroller Model에 저장한 데이터를 가진 Map

           //두번째 매개변수는 실제 출력할 파일

           //세번째 매개변수는 request response객체

           protected void buildExcelDocument(Map<String, Object> model, Workbook workbook, HttpServletRequest request,

                                  HttpServletResponse response) throws Exception {

                       //데이터 찾아오기 -Controller에서 저장한 이름으로 찾아옵니다.

                       //항상 형변환 작업을 해야 한다.

                       List<Item> list = (List<Item>) model.get("lists");

                      

                       //시트 만들기

                       Sheet sheet = workbook.createSheet();

                       workbook.setSheetName(0, "item");

                       //각 열의 너비 설정

                       sheet.setColumnWidth(0, 5120);

                      

                       //첫번째 행에 제목 출력

                       Row firstRow = sheet.createRow(0);

                       Cell cell = firstRow.createCell(0);

                       cell.setCellValue("아이디");

                       cell = firstRow.createCell(1);

                       cell.setCellValue("이름");

                       cell = firstRow.createCell(2);

                       cell.setCellValue("가격");

                       cell = firstRow.createCell(3);

                       cell.setCellValue("효과");

                      

                       //데이터 출력

                       int idx = 1;

                       for(Item item:list) {

                                  Row row = sheet.createRow(idx);

                                  cell = row.createCell(0);

                                  cell.setCellValue(item.getItemid());

                                 

                                  cell = row.createCell(1);

                                  cell.setCellValue(item.getItemname());

                                  cell = row.createCell(2);

                                  cell.setCellValue(item.getPrice());

                                  cell = row.createCell(3);

                                  cell.setCellValue(item.getDescription());

                                  idx += 1;

                       }

           }

 

}

 

 

 

6.    HomeController에서 요청후에 리턴한 뷰 이름과 엑셀 뷰 클래스를 연결하는 코드를 servlet-context.xml파일에 작성

      <!-- Controller가 리턴한 뷰이름과 뷰 클래스 매핑 -->

      <beans:bean id="excel" class="com.pk.db.view.ExcelView"></beans:bean>

     

 

 

**csvExcel파일 읽기

=>csvsupercsv라이브러리를 이용

=>excelpoi-ooxml이라는 라이브러리를 이용

 

**pdf출력 -엑셀 처름 테이블에 데이터를 출력

=>itext api를 주로 이용

=>의존성 설정을 해야 합니다.

<dependency>

           <groupId>com.lowagie</groupId>

           <artifactId>itext</artifactId>

           <version>2.1.7</version>

</dependency>

=>pdf는 기본적으로 한글 출력이 안됩니다.

한글 출력이 가능한 폰트를 설정해야 합니다.

 

windowsfont -> C:\Windows\Fonts

font 가 한글을 지원해야 한다.

 

1.pdf출력을 위한 의존성 라이브러리 설정

=>pom.xml파일의 dependencies태그에 추가

<dependency>

           <groupId>com.lowagie</groupId>

           <artifactId>itext</artifactId>

           <version>2.1.7</version>

</dependency>

 

2.home.jsp파일에 pdf출력 링크를 추가

<a href="./item.pdf">pdf로 내려받기</a>

 

3.HomeController클래스에 item.pdf요청을 처리해주는 메소드를 생성

           @RequestMapping(value="/item.pdf",method = RequestMethod.GET)

           public String pdf(HttpServletRequest request, Model model) {

                       //서비스 메소드 호출

                       List<Item> list = itemService.allItem(request);

                       //데이터 저장

                       model.addAttribute("list", list);

                       //뷰이름을 리턴

                       return "pdf";

           }

 

4.pdf 출력을 위한 view를 생성

=>AbstractPdfView로 부터 상속

package com.pk.db.view;

 

import java.util.List;

import java.util.Map;

 

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import org.springframework.web.servlet.view.document.AbstractPdfView;

 

import com.lowagie.text.Cell;

import com.lowagie.text.Document;

import com.lowagie.text.Font;

import com.lowagie.text.Paragraph;

import com.lowagie.text.Table;

import com.lowagie.text.pdf.BaseFont;

import com.lowagie.text.pdf.PdfWriter;

import com.pk.db.domain.Item;

 

public class PdfView extends AbstractPdfView {

          

           //pdf출력을 위한 메소드

           //model controller가 넘겨준 데이터

           //document는 출력한 문서 파일

           //writer는 직접 그려서 출력하고자 할 때 사용하는 객체

           //request response는 이전과 동일

           @Override

           protected void buildPdfDocument(Map<String, Object> model, Document document, PdfWriter writer,

                                  HttpServletRequest request, HttpServletResponse response) throws Exception {

                       //데이터 찾아오기

                       List<Item> list = (List<Item>) model.get("list");

                       //한글 츨력을 하고자 하는 경우에는 한글을 ㅇ지원하는 폰트를 설정

                       BaseFont dfKorean = BaseFont.createFont("c:\\windows\\fonts\\malgun.ttf",BaseFont.IDENTITY_H,BaseFont.EMBEDDED);

                       Font font = new Font(dfKorean);

                      

                       //테이블을 생성 - 첫번째 매겹ㄴ수는 열의 갯 , 두번째 행의 개수

                       Table table = new Table(4, list.size()+1);

                       table.setPadding(10);//여백

                      

                       //제목 만들기

                       Cell cell = new Cell(new Paragraph("코드",font));

                       cell.setHeader(true); //제목 일 경우

                       table.addCell(cell);

                       cell = new Cell(new Paragraph("이름",font));

                       cell.setHeader(true); //제목 일 경우

                       table.addCell(cell);

                       cell = new Cell(new Paragraph("가격",font));

                       cell.setHeader(true); //제목 일 경우

                       table.addCell(cell);

                       cell = new Cell(new Paragraph("설명",font));

                       cell.setHeader(true); //제목 일 경우

                       table.addCell(cell);

                       table.endHeaders();

                      

                       //데이터 출력하기

                       for(Item item:list) {

                                  Cell imsi = new Cell(new Paragraph(item.getItemid()+"",font));

                                  table.addCell(imsi);

                                  imsi = new Cell(new Paragraph(item.getItemname(),font));

                                  table.addCell(imsi);

                                 

                                  imsi = new Cell(new Paragraph(item.getPrice()+"",font));

                                  table.addCell(imsi);

                                  imsi = new Cell(new Paragraph(item.getDescription(),font));

                                  table.addCell(imsi);

                       }

                      

                       //테이블을 문서에 추가

                       document.add(table);

                      

           }

 

}

 

 

5.servlet-context.xml파일에 controller가 리턴한 뷰 이름과 출력할 뷰 클래스를 연결

           <beans:bean id="pdf" class="com.pk.db.view.PdfView"></beans:bean>

 

 

** json출력

=>json: 자바 스크립트 객체 표현법으로 데이터를 표현하느느 방식(스마트 폰의 push메시지,  센서의 데이터 등을 json표현법으로 주고 받고 mongo db와 같은 NoSQL에서도 데이터를 json방식으로 표현 - 자바스크립트나 파이썬은 json현식의 데이터를 쉽게 읽을 수 있습니다.)

=>json은 이전의 html,excel,pdf와 다르게 데이터를 전달하는 것입니다.

=>json출력을 위해서는 jackson-databind라이브러리가 필요

                       <!-- json출력을 위한 라이브러리 -->

                       <dependency>

                                  <groupId>com.fasterxml.jackson.core</groupId>

                                  <artifactId>jackson-databind</artifactId>

                                  <version>2.9.4</version>

                       </dependency>

 

=>출력하는 방법은 여러 가지

1.출력하는 뷰를 MappingJacksonJsonView로 출력하면 데이터를 json으로 출력해줍니다.

 

1)home.jsp파일에 json출력 요청을 생성

           <a href="item1.json">json으로 내려받기</a><br/>

 

2).HomeControoler클래스에 item1.json요청을 처리하는 메소드를 작성

           @RequestMapping(value="/item1.json",method = RequestMethod.GET)

           public String item1json(HttpServletRequest request, Model model) {

                       //서비스 메소드 호출

                       List<Item> list = itemService.allItem(request);

                       //데이터 저장

                       model.addAttribute("list", list);

                       //뷰이름을 리턴

                       return "item1json";

           }

 

3)servlet-context.xml파일에 item1jsonjson View와 연결

           <beans:bean id="item1json" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"></beans:bean>

 

 

2.Restful(Representational State Transfer) API

=>접속하는 기기에 상관없이 동일한 데이터를 요구하는 요청은 하나의  URL로 만들어지는ㄴ 개념

=>url을 요청하면 View대신에 Data를 주자는 개념

출력은 Data를 받은 클라이언트에서 자신에게 맞게 파싱해서 사용

 

 

3.RestController

=>요청을 처리하는 크랠스인데 이 클래스는 문자열을 리턴하면 csv 형식의 문자열로 출력하고 기본 자료형을 제외한 자료형으로 리턴하면 json형시긍로 출력

=>sprng 4.0 이상에서만 사용 가능

=>클래스 위에 @RestController만 추가하면 됩니다.

=>Jackson-Dating라이브러리는 추가되어 있어야 합니다.

 

4.RestController를 이용해서 문자열과 json출력

1)home.jsp파일에 문자열과 json을 요청하는 링크를 추가

           <a href="item.csv">csv로 내려받기</a><br/>

           <a href="item2.json">json으로 내려받기</a><br/>

 

2)프로젝트에 RestController로 사용할 클래스를 추가하고 작성

=>com.pk.db.JSONController

           //기본형 이나String또는 Data클래스를 제외한 형태로 리턴하면 json으로 응답

           //데이터만 return해주면 된다.

           @RequestMapping(value="/item2.json" , method = RequestMethod.GET)

           public List<Item> json(HttpServletRequest request) {

                       List<Item> list = itemService.allItem(request);

                       //실제 csv형식의 파일을 만들려면 문자열을 편집

                       return list;

           }

 

 

**ajax(Asynchronous Javascript XML)

=>자바스크립트를 이용해서 비동기적으로 데이터를 받아오는 기술

=>전체 화면을 갱신하지 않고 데이터를 받아서 일부분만 갱신하는 용도로 많이 사용

아이디 중복 체크, 댓글을 작성하고 전체화면 갱신없이 댓글이 업데이트

 

실습 - ajaxitem2.json이 리턴한 데이터를 받아서 화면에 출력

1.home.jsp파일에 ajax요청을 할 링크 추가

<a href="#" id="ajax">ajaxjson 데이터 사용하기</a><br/>

 

2.home.jsp에서 데이터를 출력할 영역을 생성

<div align="center" id="disp"></div>

 

3.home.jsp파일에 idajax인 링크를 클릭하면 동작하는 스크립트 코드를 추가

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

    pageEncoding="UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<link rel="stylesheet" href="./css/item.css">

<title>Insert title here</title>

</head>

<body>

${list }

           <h2 align='center'>상품목록</h2>

           <table border="1" align="center">

                       <tr class ="header">

                                  <th width='80'>상품ID</th>

                                  <th width='160'>상품이름</th>

                                  <th width='80'>가격</th>

                       </tr>

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

                                  <tr class="record">

                                              <td align='center'>${item.itemid }</td>

                                              <td >&nbsp;&nbsp;

                                                         <%-- <a href="detail?itemid=${item.itemid }">${item.itemname }</a> --%>

                                                         <a href="detail/${item.itemid}">${item.itemname}</a>

                                              </td>

                                              <td align="right">${item.price }&nbsp;&nbsp;</td>

                                  </tr>

                       </c:forEach>

           </table>

          

           <a href="item.xls">엑셀로 내려받기</a><br/>

           <a href="item.pdf">pdf로 내려받기</a><br/>

           <a href="item1.json">json으로 내려받기</a><br/>

           <a href="item.csv">csv로 내려받기</a><br/>

           <a href="item2.json">json으로 내려받기</a><br/>

           <a href="#" id="ajax">ajaxjson 데이터 사용하기</a><br/>

           <div align="center" id="disp"></div>

           <!-- javascript:html 내에서 동적으로 변화를 주기 위한 언어 -->

           <script type="text/javascript">

                   document.getElementById("ajax").addEventListener("click",function(){

                                  //alert("클릭");

                                  //ajax객체 만들기

                                  request = new XMLHttpRequest();

                                  //요청 생성

                                  request.open('GET','item2.json');

                                  //요청 전송

                                  request.send('');

                                  //요청에 대한 처리를 위한 콜백 메소드 등록

                                  request.onreadystatechange = function(){

                                              //정상 응답

                                              if(request.readyState == 4 && request.status >= 200  && request.status < 300){

                                                         //데이터 확인

                                                         //alert(request.responseText);

                                                         //responseText, responseXML

                                                         //받아온 데이터를 json 파싱을 해서 배열로 만들기

                                                         list = JSON.parse(request.responseText);

                                                         //배열을 순회

                                                         msg =  '';

                                                         msg += "<table border='1'>";

                                                         msg += "<tr class='header'>";

                                                         msg += "<th width ='80'>코드</th>";

                                                         msg += "<th width ='160'>상품영</th>";

                                                         msg += "<th width ='80'>가격</th>";

                                                         msg += "</tr>";

                                                         for(i in list){

                                                                     //alert(list[i]);

                                                                     msg += "<tr class='record'>";

                                                                     msg += "<td align='center'>"+list[i].itemid+"</td>";

                                                                     msg += "<td align='left'>"+list[i].itemname+"</td>";

                                                                     msg += "<td align='right'>"+list[i].price+"</td>";

                                                                     msg += "</tr>";

                                                         }

                                                         msg += "</table>";

                                                         document.getElementById('disp').innerHTML =msg;

                                              }

                                  }

                       });

                      

           </script>

</body>

</html>

 

**xml 출력

=>xml(extensible markup language) : 데이터를 태그를 이용해서 표현하는 방식

xml은 브라우저가 해석하지 않고 개발자 또는 dto 설정에서 해석하는 마크업 언어

=>예전에 실시간 데이터 전송에 많이 사용했고 아직도 프로젝트 설정 파일로 사용됩니다.

twitter등이 얘전에는 xml서비스를 제공했지만 최근에는 json으로 많이 변경되고 있습니다.

=>서버 개발자가 아니라면 xml 은 생성보다는 파싱이 중요합니다.

=>spring-oxm, jaxb-api, jaxb-impl, jaxb-core라이브러리가 필요

=>출력은 MarchallingView를 사용

=>RPC(Remote Procedure call- 원격 프로시저 호출) 를 닷넷 계열에서는 Mashalling이 라고 합니다.

웹 서버나 클라우드 사용하는 것이 RPC입니다.

http://ip주소:9000/db를 브라우저에 입력하면  ip주소 컴퓨터에 있는 어떤 메소드가 호출되서 작업을 한 후 결과를 브라우저에 전송합니다.

이러한 기술을 rpc라고 하는데 spring이 중간 통신 작업을 다 해주기 때문에 rpc를 어떻게 만들어야 하는지 몰라두 구현이 가능

 

=>ItemList xml로 출력

1. xml관련 의존성을 pom.xml 파일의 dependencies 태그에 추가

                       <!-- xml출력을 위한 라이브러리 -->

                       <dependency>

                                  <groupId>org.springframework</groupId>

                                  <artifactId>spring-oxm</artifactId>

                                  <version>${org.springframework-version}</version>

                       </dependency>

                       <dependency>

                                  <groupId>javax.xml.bind</groupId>

                                  <artifactId>jaxb-api</artifactId>

                                  <version>2.1</version>

                       </dependency>

                       <dependency>

                                  <groupId>com.sun.xml.bind</groupId>

                                  <artifactId>jaxb-impl</artifactId>

                                  <version>2.2.11</version>

                       </dependency>

                       <dependency>

                                  <groupId>com.sun.xml.bind</groupId>

                                  <artifactId>jaxb-core</artifactId>

                                  <version>2.2.11</version>

                       </dependency>

 

 

2. home.jsp파일에 xml요청을 생성

           <a href ="item.xml">xml로 내려받기</a></br>

 

3.Item클래스를 xml으로 출력할 수 있도록 어노테이션을 추가

 

@Data

@XmlAccessorType(XmlAccessType.FIELD)

@XmlType(name ="",propOrder= {"itemid","itemname","price" ,"descripttion","pictureurl"})

public class Item {

           private int itemid;

           private String itemname;

           private int price;

           private String description;

           private String pictureurl;

}

 

4.xmldto만을 출력할 수 없어서 dto listproperty로 갖는 클래스가 필요합니다.

ItemListproperty로 갖는 크랠스를 생성

=>com.pk.db.domain.ItemReport

//xml로 출력하는 것을 알려줄 것이다.

@XmlAccessorType(XmlAccessType.FIELD)

//루트 태그 설정

@XmlRootElement(name="itemlist")

public class ItemReport {

           //객체 1개만다 출력되는 태그 설정

           @XmlElement(name="item")

           private List<Item> list;

 

           public List<Item> getList() {

                       return list;

           }

 

           public void setList(List<Item> list) {

                       this.list = list;

           }

}

 

5.HomeController 클래스에 item.xml요청을 처리하는 메소드를 생성

           @RequestMapping(value="/item.xml",method = RequestMethod.GET)

           public String xml(HttpServletRequest request, Model model) {

                       //서비스 메소드 호출

                       List<Item> list = itemService.allItem(request);

                       //xml 출력 데이터 생성

                       ItemReport itemReport = new ItemReport();

                       itemReport.setList(list);

                      

                       //데이터 저장

                       model.addAttribute("list", itemReport);

                       //뷰이름을 리턴

                       return "xmlreport";

           }

 

 

6.servlet-context.xml 파일에 xml출력을 위한 생성을 추가

           <beans:bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller" id="marshaller">

                       <beans:property name="classesToBeBound">

                                  <beans:list>

                                             <beans:value>com.pk.db.domain.ItemReport</beans:value>

                                  </beans:list>

                       </beans:property>

           </beans:bean>

           <!-- xml뷰 설정

           id COntroller가 티런한 View 이름이고

           modelKey에 설정하는 것은 model에 저장한 데이터 이름입니다.-->

           <beans:bean id="xmlreport" class="org.springframework.web.servlet.view.xml.MarshallingView">

                       <beans:property name="marshaller" ref="marshaller"></beans:property>

                       <beans:property name="modelKey" value="list"></beans:property>

           </beans:bean>

 

**file upload

=>파일을 업로드 위한 form은 반드시 methodpost 이어야 하고 enctypemultipart/form-data로 설정해야 합니다.

=>springmultipart기능을 지원하기 때문에 별다른 설정없이도 multipart form의 데이터를 받을 수 있습니다.

 

=>spring에서는 fileserver에 저장할 떄 commons-fileupload의 의존성이 필요하고 CommonsMultipartResolver Bean이 필요합니다.

 

=>Spring에서는 3가지 방법으로 File Upload를 처리 할 수  있습니다.

HttpServeltRequest 대신에 MultipartHttpServletRequest를 이용해서 getFiles메소드를 처리

 

파라미터의 자료영을 multipartFile로 해서 처리하는 방법이 있습니다.

(@RequestParam, COmmand객체 이용도 가능)

 

=>MultipartFile에서 업로드하는 방법

getBytes()메소드로 파일의 내용을 바이트 배열로 리턴받아서 직접 전송하는 방법

 

transferTo(File dest)메소드에게 File객체를 대입해서 업로드 하는 방법

 

=>파일을 업로드 할 때 주의할 점은 동일한 파일명은 ?

uuid클래스를 이용해서 중복되지 않은 이름을 만들던가 업로드하는 유저의 id를 붙여서 동일한 파일명을 만들지 않도록 하는 방법이 있습니다.

 

이미지는 user마다 디렉토리를 따로따로 만든다.

 

=>삽입의 처리 과정

삽입링크 클릭 -> 삽입할 수 있는 페이지로 포워딩 ->입력을 하고 전송을 누르면 유효성 검사를 해서 유효성 검사를 통과하면 서버에게 전송 ->서버는 처리를 하고 결과 페이지로 리다이렉트를 합니다.

포워딩을 하면 새로고침하면 에러가 나든가 아니면 똑같은 것 2개 있는 가 한다.

 

=>서버가 처리를 하고 포워딩을 하게 되면 에러가 발생하던지 동일한 데이터가 중복해서 삽입되게 됩니다.

 

=>새로고침을 했을 때 이전에 수행한 작업이 다시 발생해도 되면 포워딩을 해도 되고 다시 발생하면 안되는 경우는 반드시 리다이렉트를 해야 합니다.

삽입.삭제, 갱신 ->리다이렉트 검색 -> 포워딩

로그인 리다이렉트

 

 

1.    데이터 삽입을 위한 링크를 home.jsp에 추가

      <a href="insert">데이터 삽입</a><br/>

 

2.    HomeController에서 insert요청을 처리하는 메소드를 추가

      @RequestMapping(value="/insert",method = RequestMethod.GET)

      public String insert(HttpServletRequest request, Model model) {

 

                 //뷰이름을 리턴

                 return "insert";//단순한 이름 만 포워딩 하는 것이다.

      }

 

3.    views디렉토리에 insert.jsp파일을 마들고 데이터 삽입 폼을 작성

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

    pageEncoding="UTF-8"%>

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>데이터 삽입</title>

</head>

<body>

      <div align="center">

                 <h3>데이터 삽입</h3>

                 <form method="post" enctype="mulipart/form-data" id ="myform">

                             <table border="1">

                                        <tr>

                                         <td rowspan="5" align="center">

                                                   <p></p>

                                                   <img id="img" width="100" height = "100" border ="1" />

                                                   <br/>

                                                   <input type="file" id="pictureurl" name="pictureurl" accept=".jps,.jpeg,.gif,.png" /><br/>

                                         </td>

                                        </tr>

                                        <tr>

                                                   <td align="right">코드</td>

                                                   <td><input type="text" name="itemid" id="itemid" required="required"/><div id="iddiv"></div></td>

                                        </tr>

                                        <tr>

                                                   <td align="right">이름</td>

                                                   <td><input type="text" name="itemname" id="itemname" required="required"/></td>

                                        </tr>

                                        <tr>

                                                   <td align="right">가격</td>

                                                   <td><input type="text" name="price" id="price" required="required"/></td>

                                        </tr>

                                        <tr>

                                                   <td align="right">효과</td>

                                                   <td><input type="text" name="description" id="description" required="required"/></td>

                                        </tr>

                                        <tr>

                                                   <td colspan="3" align="center">       

                                                               <input type="submit" value="전송">

                                                               <input type="button" value="메인" id="mainbtn">

                                                   </td>

                                        </tr>

                             </table>

                 </form>

      </div>

</body>

</html>

 

4.    insert.jsp파일에 이미지 미리보기 기능 구현

=>javascript에서 파일을 불러오는 동작은 비동기적(순서대록 동작하지 않는다. -콜백)으로 처리됩니다.

       <script>

                       //이미지 미리보기

                       var pictureurl = document.getElementById("pictureurl");

                       var img = document.getElementById("img");

                      

                       //이미지 선택이 변경되면

                       pictureurl.addEventListener("change",function(){

                                  //업로드한 이미지 파일의 내용을  img에 출력

                                  //파일 객체 생성

                                  var reader = new FileReader();

                                  // 선택한 파일이 있다면

                                  if(pictureurl.files && pictureurl.files[0]){

                                              //파일 읽기

                                             reader.readAsDataURL(pictureurl.files[0]);

                                             //출력

                                              ///img.src = reader.target.result;

                                              //비동기를 할 때는 파일의 내용을 전부 읽으면 출력

                                             reader.addEventListener("load",function(e){

                                                         img.src  = e.target.result;

                                              })

                                  }

                       });

      </script>

 

 

5.    itemid중복 검사

1)    itemid를 받아서 중복 여부를 판별해서 리턴할 서버의 요청 처리 메소드를 생성

=>itemid를 파라미터로 받아서 서버에 가서 데이터가 존재하는지 확인하면 된다.

Service클래스의

=>jsoncontroller클래스에 itemid중복 검사를 위한 메소드를 생성

 

       //itemid를 파라미터로 받아서 중복체크를 해서 리턴하는 메솓,

           @RequestMapping(value="/itemidcheck",method =RequestMethod.GET)

           public Map<String, Object> itemIdCheck(HttpServletRequest request,@RequestParam("itemid") int itemid){

                       //서비스 메소드 호출

                       Item item = itemService.getItem(request, itemid);

                       //리턴할 Map을 생성

                       Map<String , Object> map = new HashMap<String, Object>();

                       if(item == null) {

                                  map.put("result", "true");

                       }else {

                                  map.put("result","false");

                       }

                       return map;

}

 

 

 

 

상세보기는 중복검사 할 때도 사용이 된다. 로그인할때도 사용이 된다.

 

 

2)insert.jsp에서 중복 체크 하는 코드 작성

 

 

**.Validatation(유효성 검사)

=>데이터를 삽입하거나 삭제 또는 갱신 및 조회를 할 때 올바를 데이터인지 호가인하는 작업

웹 애플리케이션에서는 클라이언트 (웹 브라우저 - 자바스크립트)와 서버의 service클래스 그리고 데이터베이스에서  할 수 있습니다.

할 수 있는 모든 곳에서 하는 것이 좋습니다.

클라이언트 측에서만 하는 경우에는 데이터를 전송할 때 헤더를 변경해서 자바스크립트에서는 올바른 데이터였지만 서버에 도달 할 때는 다른 데이터 일 수 있습니다.

ipuserAgent값을 변경해서 전송하는 경우가 많습니다.

서버에서 header값들을 읽어서 확인해야 합니다.

데이터에비으세어 제약조건을 이용해서 다시 한 번 검사를 하는 것이 안전합니다.

 

보안 이 필요한 유효성 검사는 클라이언트에서 하면 안됩니다.

 

 

 

 

반응형

'Study > spring' 카테고리의 다른 글

spring-7  (0) 2020.10.26
spring-6  (0) 2020.10.26
spring-4  (0) 2020.10.23
spring-3  (0) 2020.10.23
spring-2  (0) 2020.10.22
반응형

**Spring MVC Project

=>Spring Web Project

=>Legacy Project 에서 선택해서 생성 - 전자정부 프레임워크나 기업이 프레임워크에서 선택해서 만드는 프로젝트의 기본 모양으로 전자정부 프레임워크에서는 여기에 데이터베이스 연동하는 코드가 추가되어 있습니다.

=>spring mvc project android, iOS 프로젝트에서는 기본 패키지이름을 3level 이상으로 만들도록 강제합니다.

회사도메인을 역순으로 기재하고 프로젝트이름나 기술이름을 추가합니다.

회사도메인이 없을 때는 이메일 주소를 이용하는 것을 권장합니다.

 

 

kr.co.pk.springmvc

패키지 이름을 만들면 패키지의 3번째 부분이 도메인이 됩니다.

 

1.디렉토리 구조

=>src/main/java: 컴파일 되어야 하는 java 파일이 위치해야 하는 디렉토리

패키지가 생성되어 있고 그 안에 HomeController가 생성되어 있습니다.

패키지 안에 클래스를 만들 때 @Controller, @Service, @Repository, @Component를 붙이면 bean이 자동 생성되도록 설정되어 있습니다.

 

=>src/main/resources: 컴파일 할 필요가 없는 파일들이 위치하는 디렉토리

이 디렉토리와 java 디렉토리는 나중에 합쳐집니다.

이 디렉토리의 내용들은 컴파일하지 않습니다.

이 디렉토리에 만든 파일들은 java 디렉토리에 만들어도 되지만 java 디렉토리에 만드는 .java 파일은 이 디렉토리에 만들면 안됩니다.

여기에는 설정 파일들이 위치합니다.

 

=>src/test/java resources : 테스트 용 자바파일과 설정파일을 저장하는 디렉토리인데 이 디렉토리는 배포할 때 없어집니다.

이 디렉토리는 소스 차원에서만 존재합니다.

 

=>src/main/webapp: html, css, js, jsp 등 뷰와 관련된 파일들이 위치하는 디렉토리

이 디렉토리가 배포될 때는 WebContent 와 같은 역할

 

2.생성된 파일

1)web.xml

           <!-- 웹 애플리케이션이 시작되면 WEB-INF 디렉토리의

           applicatonContext.xml 파일의 내용을 읽어서 수행한다는 설정 -->

           <listener>

                       <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

           </listener>

           <!-- applicationContext.xml 파일의 경로를 변경하는 설정 -->

           <context-param>

                       <param-name>contextConfigLocation</param-name>

                       <param-value>/WEB-INF/spring/root-context.xml</param-value>

           </context-param>

          

 

 

           <!-- / .jsp를 제외한 모든 요청

           .jsp를 제외한 모든 요청을 param-value에 설정된 파일에서 만드는

           Controller가 처리하도록 하는 설정

           FrontController의 역할을 수행하는 설정 파일의 경로를 설정-->

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

 

2)root-context.xml

=>애플리케이션 내의 모든 곳에서 사용할 수 있는 bean을 생성

=>데이터베이스 연동하는 bean을 이 파일에서 생성

 

3)servlet-context.xml

           <!-- spring mvc 프로젝트에서 사용해야 하는 여러 설정을 한꺼번에 해주는 태그 -->

           <annotation-driven />

 

           <!-- location에 파일을 위치시키면 자동으로 캐싱이 되도록 해주는 태그 -->

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

 

           <!-- Controller 가 리턴한 뷰 이름을 가지고 prefix를 앞에 붙이고

           suffix를 뒤에 추가해서 실제 출력할 뷰 파일을 선택하도록 해주는 태그 -->

           <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">

                       <beans:property name="prefix" value="/WEB-INF/views/" />

                       <beans:property name="suffix" value=".jsp" />

           </beans:bean>

          

           <!-- 어노테이션이 붙은 클래스의 bean을 자동으로 생성해주는 패키지 설정 -->

           <context:component-scan base-package="com.pk.springmvc" />

          

4)HomeController

=>기본적으로 제공되는 Controller

@Controller

public class HomeController {

          

           private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

          

           // / 요청이 GET 방식으로 오면 처리하는 메소드 설정

          @RequestMapping(value = "/", method = RequestMethod.GET)

           public String home(Locale locale, Model model) {

                       //model attribute를 저장하면 request 객체에 저장됩니다.

                       //문자열을 리턴하면 이 문자열이 view 이름입니다.

                       // /(기본 요청)요청이 오면 serverTime이라는 attribute request에 저장해서

                       // home -> WEB-INF/views/home.jsp 로 포워딩합니다.

                       logger.info("Welcome home! The client locale is {}.", locale);

                       Date date = new Date();

                       DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);

                      

                       String formattedDate = dateFormat.format(date);

                      

                       model.addAttribute("serverTime", formattedDate );                      

                       return "home";

           }

          

}

3.실행

=>프로젝트를 선택하고 [Run As] - [Run on Server]를 선택

=>처음 실행하는 경우에는 WAS를 선택해야 합니다.

 

4.pom.xml : Maven Project의 설정 파일

=>라이브러리 의존성이나 build 옵션을 설정하는 파일

=>properties: 자주 사용하는 버전을 이름으로 저장해놓은 설정

=>repositories: 중앙 저장소 이외의 곳에서 다운로드 받을 수 있도록 해주는 설정

=>dependencies: 다운로드 받아서 프로젝트에서 사용할 라이브러리를 설정

 

=>java spring 버전을 properties 태그에서 설정하고 외부 라이브러리를 사용해야 하는 경우가 생기면 repositories dependencies 태그에 설정

 

5.요청을 만들고 Controller를 이용해서 처리해서 결과를 보여주는 페이지 작성

1)home.jsp 파일을 지우고 새로 생성한 후 작성

<a href="display">jsp 출력</a><br/>

 

2)HomeController 클래스에 display 요청을 처리하는 메소드 추가

           //display라는 요청이 왔을 때 처리하는 메소드

           @RequestMapping(value="/display", method=RequestMethod.GET)

           public String display(Model model) {

                       String msg = "Spring MVC Project";

                       //데이터 저장 - request.setAttribute 와 동일

                       model.addAttribute("msg", msg);

                      

                       //출력할 View 이름을 설정

                       return "display";

           }

 

3)WEB-INF/views 라는 디렉토리에 display.jsp 파일을 추가하고 작성

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

    pageEncoding="UTF-8"%>

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>Insert title here</title>

</head>

<body>

           데이터 : ${msg}

</body>

</html>

 

 

4)과정

Web Application 실행 -> pom.xml(필요한 라이브러리를 다운로드 받아서 사용할 수 있도록 해 줍니다.) ->web.xml 파일을 읽어서 애플리케이션 설정을 합니다. -> /WEB-INF/spring/root-context.xml 파일을 읽어서 필요한 작업을 수행 -> /WEB-INF/spring/appServlet/servlet-context.xml 파일을 읽어서 필요한 작업을 수행 -> HomeController 설정에 따라서 / 요청이 오면 home.jsp를 출력

 

display 라는 요청을 전송 -> web.xml 설정에 따라서 servlet-context.xml 이 만든 HomeController에서 요청을 처리해주는 메소드를 찾고 없으면 404에러가 발생하고 메소드가 있으면 메소드의 내용을 수행하고 return 하는 문자열을 가지고 servlet-context.xml ViewResolver 설정을 읽고 실제 출력할 view의 이름을 결정해서 출력

 

 

6.Spring에서 web.xml에 설정할 수 있는 URL Pattern

1)/* : 모든 요청

2)/ : .jsp를 제외한 모든 요청 - spring에서만 사용 가능

3)/디렉토리/* : 디렉토리가 포함된 모든 요청 - 최근에 디렉토리를 이용해서 서비스를 구분하는 경우가 많습니다.

4)*.확장자 : 확장자로 끝나는 모든 요청 - 이전에 *.do 로 많이 사용

5)/경로명 : 경로명에 해당하는 하나의 요청

 

=>기본 설정이 /로 되어 있는데 작은 규모의 웹 애플리케이션에서는 변경하지 않고 사용합니다.

서비스가 많아져서 하나의 웹 애플리케이션으로는 처리하기 힘든 경우 설정을 변경합니다.

=>url-pattern 은 여러 개 설정 가능

 

7.파라미터 인코딩 설정

=>parameter: 클라이언트가 서버에게 전달하는 데이터

1)파라미터 작성 방법

=>URL 뒤에 ?를 추가하고 이름=&이름=.. 의 형태로 작성 가능 - GET

=>form 에서 name을 갖는 객체를 생성하면 form submit 될 때 파라미터로 만들어서 전달 - GET, POST

=>ajax 와 같은 요청에서 parameter를 별도로 만들어서 전송

프로그래밍언어에서 Web Application에게 요청을 보낼때도 ajax 와 유사한 방식 - GET, POST

 

2)파라미터 전송 방식

=>GET: URL 뒤에 파라미터를 붙여서 전송하는 방식, 자동 재전송 기능이 있지만 보안이 되지 않고 파라미터 길이에 제한이 있습니다.

=>POST: 파라미터를 header에 숨겨서 전송하는 방식, 파라미터가 URL에서 보이지 않아서 보안이 GET 보다는 우수하고 파라미터 길이에도 제한이 없습니다.

=>password, textarea, file 이 있는 경우는 반드시 POST 방식을 사용

최근에는 form 의 데이터는 대부분 POST 방식으로 전송하는 것을 권장

검색을 요청하는 form을 제외하고 대부분 POST 방식

링크를 이용해서 전송하는 경우는 대부분 GET 방식을 사용

 

3)파라미터 인코딩

=>GET 방식은 WAS 가 처리하고 POST 방식은 서버의 코드가 처리

=>spring에서는 web.xml 파일에 filter를 이용해서 처리가 가능

           <!-- 스프링에서 파라미터 인코딩 설정 -->

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

=>Spring Web Project에서 무조건 설정

 

 

**Controller

=>URL 요청이 오면 필요한 서비스를 호출하고 그 결과를 저장해서 View를 선택해주는 클래스

 

1.Controller 생성

=>spring에서는 POJO 클래스 위에 @Controller를 추가하면 됩니다.

=>Bean의 생성은 설정 파일의 Component-Scan을 이용

 

2.요청 처리 메소드의 기본 모양

- 포워딩으로 처리

@RequestMapping(value="처리할 URL", method=RequestMethod.전송방식)

public String 이름(Model model){

           //전달할 데이터

           model.setAttribute("이름", 데이터);

           //출력할 View

           return "뷰이름";

}

 

- 여러 개의 요청 처리

value={"URL1", "URL2"...}

 

 

@Controller

public class HomeController{

                       @RequestMapping(value="/display", method=RequestMethod.GET)

           public String display(Model model) {

                       String msg = "Spring MVC Project";

                       //데이터 저장 - request.setAttribute 와 동일

                       model.addAttribute("msg", msg);

                      

                       //출력할 View 이름을 설정

                       return "display";

           }

}

=>display 라는 요청이 GET 방식으로 오면 request msg라는 이름으로 데이터를 저장해서 display라는 곳으로 포워딩

 

3.Spring에서의 파라미터 처리

1)HttpServletRequest 이용

2)@RequestParam 이용

3)Command(DTO 와 유사) 객체 이용

=>HttpServletRequest를 이용하는 방법은 java 의 모든 web project에서 사용가능하지만 나머지 방법은 Spring Project에서만 가능

 

4.HttpServletRequest를 이용한 파라미터 처리

1)String getParameter("파라미터이름")

2)String [] getParameterValues("파라미터이름")

 

5.@RequestParam을 이용하는 방식

=>Controller의 요청 처리 메소드 안에 @RequestParam("파라미터이름") 자료형 변수명 으로 설정

=>변수에 파라미터의 값을 대입주는데 형변환은 자동

 

6.Command 객체를 이용하는 방식

=>모든 파라미터 이름으로 구성된 DTO 클래스를 생성

Controller의 요청 처리 메소드 안에 클래스이름 변수명 을 작성하면 모든 파라미터들이 변수에 대입

 

7.파라미터 처리 실습

1)home.jsp 파일에 링크를 생성

<a href="param?num=10">Request를 이용한 파라미터 처리</a><br/>

 

2)HomeController param 요청을 처리하는 메소드를 생성

           @RequestMapping(value="/param", method=RequestMethod.GET)

          public String param(Model model, HttpServletRequest request) {

                       String num = request.getParameter("num");

                       System.out.println(num);

                       return "";

           }

 

3)home.jsp 파일에 form을 생성

           <form action="get" method="get">

                       검색어:<input type="text" name="keyword" />

                       <input type="submit" value="검색"/>

           </form>

 

4)HomeController 클래스에 get 요청을 처리하는 메소드를 생성

           @RequestMapping(value="/get", method=RequestMethod.GET)

           public String get(Model model,

                                  @RequestParam("keyword") String keyword) {

                       System.out.println(keyword);

                       return "";

           }

 

5)home.jsp 파일에 아이디 와 비밀번호를 입력받는 form을 생성

<form action="login" method="post">

           <input type="text" name="id"

                       placeholder="아이디를 입력하세요!" required='required'/><br/>

                       <input type="password" name="pw"

                       placeholder="비밀번호를 입력하세요!" required='required'/><br/>

                       <input type="submit" value="로그인"/>

</form>

 

6)id pw를 저장할 수 있는 클래스 생성

package com.pk.springmvc.domain;

 

public class User {

           private String id;

           private String pw;

          

           public String getId() {

                       return id;

           }

           public void setId(String id) {

                       this.id = id;

           }

           public String getPw() {

                       return pw;

           }

           public void setPw(String pw) {

                       this.pw = pw;

           }

          

           @Override

           public String toString() {

                       return "User [id=" + id + ", pw=" + pw + "]";

           }

          

          

}

 

7)Controller 에 요청을 처리하는 메소드를 생성

           @RequestMapping(value="/login", method=RequestMethod.POST)

           public String login(Model model,

                                  User user) {

                       System.out.println(user);

                       return "";

           }

 

8.최근에 파라미터가 1개인 경우 처리

=>상세보기가 이러한 형태로 많이 구현

최근에는 파라미터가 1개이면 파라미터로 만들지 않고 URL의 마지막에 추가하는 형태를 많이 사용합니다.

 

https://hht/304

304가 글번호입니다.

 

=>spring에서는 위와 같은 파라미터를 @PathVariable 이라는 어노테이션을 이용해서 처리

@RequestMapping(value="/경로/{num}")

public String ?(@PathVariable 자료형 num) 형태로 처리

{ }안에 입력한 이름과 변수명은 일치해야 합니다.

 

1)home.jsp 파일에 요청을 생성

<a href="article/20">20번글</a><br/>

 

2)HomeController에 위의 요청을 처리하는 메소드를 생성

@RequestMapping(value="/article/{num}", method=RequestMethod.GET)

           public String detail(Model model,

                                  @PathVariable int num) {

                       System.out.println(num);

                       return "";

           }

 

**View에게 데이터 전달

=>Controller의 요청 처리 메소드에 HttpServletRequest를 추가해서 전달

이 방식은 포워딩 할 때만 유효

request.setAttribute("이름", 데이터)

 

=>Controller의 요청 처리 메소드에 HttpSession을 추가해서 전달

이동 방법에 상관없이 데이터를 직접 삭제할 때 까지 유효

session.setAttribute("이름", 데이터)

 

=>Controller의 요청 처리 메소드에 Model을 추가해서 전달

이 방식은 포워딩 할 때만 유효

model.addAttribute("이름", 데이터)

 

=>Controller의 요청 처리 메소드에 RedirectAttributes를 추가해서 전달

리다이렉트로 이동할 때 한번만 사용할 수 있는 데이터를 저장

attr.addFlashAttribute("이름", 데이터)

 

**출력할 View 선택

요청 처리 메소드에서 String을 리턴해서 View을 결정

void로 리턴이 없도록 만들면 요청 URL View 이름이 됩니다.

리다이렉트 하고자 하는 경우에는 redirect:URL 로 작성하면 됩니다.

 

 

**Oracle 데이터베이스를 연동하는 spring mvc project

1.Oracle접속해서 샘플데이터를 생성

--drop table item;

CREATE TABLE ITEM(

itemid number(5),

itemname VARCHAR2(20),

price number(6),

description VARCHAR2(50),

pictureurl VARCHAR2(20),

PRIMARY KEY (itemid)

);

insert into item values(1, 'Lemon', 500, 'Vitamin-A', 'lemon.jpg');

insert into item values(2, 'Orange', 1500, 'Vitamin-B', 'orange.jpg');

insert into item values(3, 'Kiwi', 2000, 'Vitamin-C', 'kiwi.jpg');

insert into item values(4, 'Grape', 1000, 'Vitamin-D', 'grape.jpg');

insert into item values(5, 'Strawberry', 2000, 'Vitamin-E', 'strawberry.jpg');

insert into item values(6, 'Mandarin', 300, 'Vitamin-F', 'mandarin.jpg');

commit;

select * from ITEM;

 

 

 

2.Spring MVC Project생성

=>프로젝트 이름은 springmvc

=>패키지 이름은 com.pk.db

spring legacy project ->spring mvc project

 

지금 까지 다른 점은 템플릿이 있다.

 

 

 

3. pom.xml파일에 의존성을 설정

spring mvc project에서 설정 파일 순선

pom.xml -> web.xml

->root-context.xml -> appServlet.xml

 

 

 

=>위의 2개는 파일이름이 고정

아래 2개는 사용하는 프레임워크에 따라 다른 이름이 될 수 있습니다ㅣ.

 

2)dependencies 태그 바깥에 추가

<!-- 중앙 저장소 이외의 곳에서 라이브러리를 다운로드 받을 때

           다운로드 받는 위치를 설정하는 태그 -->

           <repositories>

                       <repository>

                                  <id>oracle</id>

                                  <name>ORACLE JDBC Repository</name>

                                  <url>http://maven.jahia.org/maven2</url>

                       </repository>

           </repositories>

 

3)dependencies 태그 안에 작성

<!-- 오라클 라이브러리 -->

                       <dependency>

                                  <groupId>com.oracle</groupId>

                                  <artifactId>ojdbc7</artifactId>

                                  <version>12.1.0.2</version>

                       </dependency>

                      

                       <!-- spring에서 데이터베이스를 사용할 때 설정 -->

                       <dependency>

                                  <groupId>org.springframework</groupId>

                                  <artifactId>spring-jdbc</artifactId>

                                  <version>${org.springframework-version}</version>

                       </dependency>

 

                       <!-- MyBatis -->

                       <dependency>

                                  <groupId>org.mybatis</groupId>

                                  <artifactId>mybatis</artifactId>

                                  <version>3.4.6</version>

                       </dependency>

 

                       <!-- Spring-MyBatis -->

                       <dependency>

                                  <groupId>org.mybatis</groupId>

                                  <artifactId>mybatis-spring</artifactId>

                                  <version>1.3.2</version>

                       </dependency>

 

                       <!-- 롬북 Dto를 편리하게 만들 수 있도록 해주는 라이브러리-->

                       <dependency>

                                  <groupId>org.projectlombok</groupId>

                                  <artifactId>lombok</artifactId>

                                  <version>1.18.8</version>

                       </dependency>

                       <!-- 로그를 츨력하기 위한 라이브러리 -->

                       <dependency>

                                  <groupId>org.bgee.log4jdbc-log4j2</groupId>

                                  <artifactId>log4jdbc-log4j2-jdbc4</artifactId>

                                  <version>1.16</version>

                       </dependency>

 

                       <!-- 하이버네이트 사용을 위한 라이브러리 -->

                       <dependency>

                                  <groupId>org.springframework</groupId>

                                  <artifactId>spring-orm</artifactId>

                                  <version>${org.springframework-version}</version>

                       </dependency>

 

                       <dependency>

                                  <groupId>org.hibernate</groupId>

                                  <artifactId>hibernate-entitymanager</artifactId>

                                  <version>5.4.2.Final</version>

                       </dependency>

 

                       <!-- json출력을 위한 라이브러리 -->

                       <dependency>

                                  <groupId>com.fasterxml.jackson.core</groupId>

                                  <artifactId>jackson-databind</artifactId>

                                  <version>2.9.4</version>

                       </dependency>

 

 

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

 

          

           <!-- Creates the Spring Container shared by all Servlets and Filters -->

           <!--웹 앱플리캐이션이 시작할 때 실행할 스프링 설정파일을

           web-inf/application-context.xml로 설정 -->

           <listener>

                       <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

           </listener>

          

           <!-- 위의 파일 경로를 변경하는 설정 -->

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

 

           <!-- Processes application requests -->

           <!-- jsp를 제이한 요청이 왔을 떄 처리를 위한 스프링 설정 파일의 경로를 실행 -->

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

           <!-- .jsp를 제외한 요청은 appServlet이 처리 -->   

           <servlet-mapping>

                       <servlet-name>appServlet</servlet-name>

                       <url-pattern>/</url-pattern>

           </servlet-mapping>

 

</web-app>

 

5. 데이터베이스 를 연동할 때는 하나의 행을 나타낼 dto클래스를 생성

=>기본패키지.domain.Item

=>변수를 만들 때 되도록이면 테이블에서 사용하는 컬럼이름과 일치시키는 것을 권장

getters and setters , toString()

package com.pk.db.domain;

 

import lombok.Data;

 

@Data

public class Item {

           private int itemid;

           private String itemname;

           private int price;

           private String description;

           private String pictureurl;

}

 

6.mybatis mapper 인터페이스를 만들고 필요한 sql을 생성

=>기본 패키지 com.pk.db.dao.ItemDao

package com.pk.db.dao;

 

import java.util.List;

 

import org.apache.ibatis.annotations.Select;

 

import com.pk.db.domain.Item;

 

public interface ItemDao {

           //Item테이블의 모든 데이터를 가져오는 메소드

           @Select("select * from item")

           public List<Item> allItem();

          

           //Item 테이블에서 Itemid를 이용해서 데이터 1개를 찾아오는 메소드

           @Select("select * from item wehre itemid = #{itemid}")

           public Item getItem(int itemid);

}

 

7. root-context.xml 파일에 mybatis 연동을 위한 설정을 추가

=>Datasource:데이터베이스 연동할 떄 필수

=>SqlSessionFactoryBean, MapperFactoryBean: 인터페이스를 이용한 mybatis 사용하는 경우 생성

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

<beans xmlns="http://www.springframework.org/schema/beans"

           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

           xmlns:context="http://www.springframework.org/schema/context"

           xmlns:tx="http://www.springframework.org/schema/tx"

       xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd

                       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd

                       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

          

           <!-- Root Context: defines shared resources visible to all other web components -->

           <!-- 애플리케이션 모든 곳에서 사용할 bean을 생성 -->      <!-- 스프링에서 데이터베이스를 사용할 때 접속 정보를 저장할 bean -->

           <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">

                       <!-- 데이터베이스 종류 -->

                       <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>

                       <!-- 데이터베이스 위치 -->

                       <!-- 데이터베이스 응용법 마다 다르다. -->

                       <property name="url" value="jdbc:oracle:thin:@ip주소1521:xe"></property>

                       <property name="username" value="user29"></property>

                       <property name="password" value="user29"></property>

           </bean>

          

           <!-- MyBatis를 인터페이스를 이용해서 사용할 떄 필요한 Bean -->

           <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">

                       <property name="dataSource" ref="dataSource"></property>

           </bean>

          

           <bean class="org.mybatis.spring.mapper.MapperFactoryBean" id="itemDao">

                       <property name="sqlSessionFactory" ref ="sqlSessionFactory"></property>

                       <property name="mapperInterface" value="com.pk.db.dao.ItemDao"></property>

           </bean>

          

 

</beans>

 

 

 

**DaosERVICE가 가져다가 사용합니다.

=>Service를 만들 때는 탬플릿 메소드 패턴 사용

=>인터페이스를 생성하고 메소드를 선언한 후 클래스에서 메소드를 구현

 

8.Service인터페이스를 만들고 전체 데이터를 전부 가져오는 메소드를 선언

=>기본패키지.service.ItemService

=>Service인터페이스의 메소드는 기본적으로 HttpServletRequest는 매개변수로 무조건 갖도록 만듭니다.

package com.pk.db.service;

 

import java.util.List;

 

import javax.servlet.http.HttpServletRequest;

 

import com.pk.db.domain.Item;

 

public interface ItemService {

           //전체 데이터를 가져오는 메소드

           public List<Item> allItem(HttpServletRequest request);

}

 

 

9.Service 인터페이스를 implements Service 클래스를 만들고 메소드를 구현

=>기본패키지.service.ItemServiceImpl

package com.pk.db.service;

 

import java.util.List;

 

import javax.servlet.http.HttpServletRequest;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

 

import com.pk.db.dao.ItemDao;

import com.pk.db.domain.Item;

 

//bean을 자동생성해주는 어노테이션

@Service

public class ItemServiceImpl implements ItemService {

 

           //ItemDao타입의 bean이 있으면 자동으로 주입시켜주는 어노테이션

           @Autowired

           private ItemDao itemDao;

          

           @Override

           public List<Item> allItem(HttpServletRequest request) {

                       //Dao의 메소드에 파라미터가 없는 경우는 Dao 메소드를 출력해서 리턴

                       return itemDao.allItem();

           }

 

}

 

10.Controller 클래스 수정

package com.pk.db;

 

import java.util.List;

 

import javax.servlet.http.HttpServletRequest;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

 

import com.pk.db.domain.Item;

import com.pk.db.service.ItemService;

 

@Controller

public class HomeController {

           //service객체르르 주입

           @Autowired

           private ItemService itemService;

          

          

           @RequestMapping(value="/", method = RequestMethod.GET)

           public String home(HttpServletRequest request,Model model) {

                       //서비스 메소드 호출

                       List<Item> list = itemService.allItem(request);

                       //데이터 저장

                       model.addAttribute("list", list);

                       return "home";

           }

}

 

11. webapp/WEB-INF/views디텍토리의 home.jsp를 삭제하고 새로 생성

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

    pageEncoding="UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>Insert title here</title>

</head>

<body>

${list }

           <h2 align='center'>상품목록</h2>

           <table border="1" aling="center">

                       <tr class ="header">

                                  <th width='80'>상품ID</th>

                                  <th width='160'>상품이름</th>

                                  <th width='80'>가격</th>

                       </tr>

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

                                  <tr class="record">

                                              <td align='center'>${item.itemid }</td>

                                              <td >&nbsp;&nbsp;${item.itemname }</td>

                                              <td align="right">${item.price }&nbsp;&nbsp;</td>

                                  </tr>

                       </c:forEach>

           </table>

</body>

</html>

 

 

css파일 ->html, jsp적용

<style> 스타일 </style>

웹 어플리캐이션은 파일의 경로가 아니고고 url의 경로이다.

webapp에 해야 한다.

 

 

 

**cssjs 이외의 기타 자원의 경로 설정

=>출력되는 파일의 위치가 기준이 아니고 url이 기준입니다.

 

 

12. webapp(WebContent) 디렉토리에 css디렉토리를 생성하고 item.css 파일을 만들어서 작성

css.item.css

.header{

           background: #C98FED;

          

}

.record{

           background: #EDEDED;

}

 

13. home.jsp파일에 css 파일의 링크 설정

 

 

14. mvc:default-servlet-handler

=>spring 프로젝트에서 servleturl-pattern//*로 하는 경우 모든 요청을 controller가 처리 할려고 합니다.

cssjs 등의 확장자를 가진 링크도 controller가 처리 할려고 합니다.

이런 이유로 404 에러가 발생합니다.

=>cssjs등의 확장자를 가진 파일의 링크를 사용하고자 할 때는 servlet-context.xml파일에 태그를 추가해서 controller가 처리할 수 없는 요청은 was가 대신 처리하도록 해주어야 합니다.

이 설정도 필수 입니다.

<link rel="stylesheet" href="./css/item.css">

 

15. servelt-context.xml파일에 아래 태그 추가

       <!-- controller가 처리하지 못하도록 하는 요청은 was가 처리하도록 해주는 요청 -->

           <default-servlet-handler/>

 

urlfile path 안 같다.

url이라고 파일의 경로는 다르다.

 

 

16. 상세보기 구현을 위해서 home.jsp파일에서 이름을 출력하는 부분을 수정

//파라미터로 기본키의 값이 itemid를 넘겨줍니다.

<a href="detail?itemid=${item.itemid }">${item.itemname }</a>

 

17.Servide 인터페이스에 상세보기를 위한 메소드를 선언

       //데이터 1개를 가져오는 메소드

           public Item getItem(HttpServletRequest request);

 

 

18. ItemServiceImpl클래스에 상새보기를 위한 클래스를 구현

           @Override

           public Item getItem(HttpServletRequest request) {

                       //파라미터 읽어오기

                       String itemid = request.getParameter("itemid");

                       //파라미터를 정수로 변환해서 Dao 메소드를 호출

                       return itemDao.getItem( Integer.parseInt(itemid));

           }

 

19. HomeController클래스에 detail요청을 처리하는 메소드를 생성

       @RequestMapping(value = "/detail", method = RequestMethod.GET)

           public String detail(HttpServletRequest request, Model model) {

                       // 서비스 메소드 호출

                       Item item = itemService.getItem(request);

                       // 데이터 저장

                       model.addAttribute("item", item);

                       return "detail";///출력할 페이지 이름

           }

 

20. views디렉토리에 deetail.jsp파일을 만들고 출력하는 코드를 작성

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

    pageEncoding="UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>Insert title here</title>

</head>

<body>

${item}

</body>

</html>

 

 

요청이 발생하면 Controller로 이동 ->

Service메소드로 이동

Dao메소드로 이동 ->sql확인 ->

Service메소드로 이동 ->

Controller메소드로 이동

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

    pageEncoding="UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>${item.itemname }</title>

<link rel ="stylesheet" href="./css/item.css">

</head>

<body>

           <%-- ${item } --%>

           <div align="center">

                       <h2>상품 상세보기</h2>

                       <table border="1">

                                  <tr>

                                              <td><img src="./img/${item.pictureurl}"/></td>

                                              <td>

                                                         <table>

                                                                     <tr height='50'>

                                                                                <td width="80">상품명</td>

                                                                                <td width="160">${item.itemname}</td>

                                                                     </tr>

                                                                     <tr height='50'>

                                                                                <td width="80">가격</td>

                                                                                <td width="160">${item.price}</td>

                                                                     </tr>

                                                                     <tr height='50'>

                                                                                <td width="80">효능</td>

                                                                                <td width="160">${item.description}</td>

                                                                     </tr>

                                                                     <tr height='50'>

                                                                                <td colspan="2" align="center">

                                                                                           <a href="./" >목록보기</a>

                                                                                </td>

                                                                     </tr>

                                                         </table>

                                              </td>

                                  </tr>

                       </table>

           </div>

</body>

</html>

 

21.이미지를 다운로드 받아서 압축을 해제한 후 webapp 디렉토리에 복사

 

최근에는 http://www.naver.net/archives/371849이런식으로 한다.

 

 

**itemidparameter 가 아니라 path variable로 처리하기

1.Service인터페이스에서 detail을 처리해주는 메소드를 추가로 선언

파라미터를 읽을 수 없기 때문에 Controller 로 부터 itemid를 받아야 합니다.

           //파라미터를 읽지 않고 받는 메소드

           public Item getItem(HttpServletRequest request,int itemid);

 

 

 

2.ItemServiceImpl클래스의 메소드 구현

       @Override

           public Item getItem(HttpServletRequest request, int itemid) {

                       return itemDao.getItem(itemid);

           }

 

3.HomeController 메소드 구현

             

       @RequestMapping(value = "/detail/{itemid}", method = RequestMethod.GET)

           public String detail(HttpServletRequest request, Model model,@PathVariable int itemid) {

           System.out.println("===================================="+itemid);

                       // 서비스 메소드 호출

                       Item item = itemService.getItem(request,itemid);

                       // 데이터 저장

                       model.addAttribute("item", item);

                       return "detail";///출력할 페이지 이름

           }

 

 

4.home.jsp에 제목 링크 수정

<a href="detail/${item.itemid}">${item.itemname}</a>

 

5.detail.jsp 모두 .을 하나 더 추가해야 한다.

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

    pageEncoding="UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>${item.itemname }</title>

<link rel ="stylesheet" href="../css/item.css">

</head>

<body>

           <%-- ${item } --%>

           <div align="center">

                       <h2>상품 상세보기</h2>

                       <table border="1">

                                  <tr>

                                              <td><img src="../img/${item.pictureurl}"/></td>

                                              <td>

                                                         <table>

                                                                     <tr height='50'>

                                                                                <td width="80">상품명</td>

                                                                                <td width="160">${item.itemname}</td>

                                                                     </tr>

                                                                     <tr height='50'>

                                                                                <td width="80">가격</td>

                                                                                <td width="160">${item.price}</td>

                                                                     </tr>

                                                                     <tr height='50'>

                                                                                <td width="80">효능</td>

                                                                                <td width="160">${item.description}</td>

                                                                     </tr>

                                                                     <tr height='50'>

                                                                                <td colspan="2" align="center">

                                                                                           <a href="../" >목록보기</a>

                                                                                </td>

                                                                     </tr>

                                                         </table>

                                              </td>

 

                                  </tr>

                       </table>

           </div>

</body>

</html>

 

 

hibernateTransaction을 이용해야 한다.

트랜잭션은 dao에 하는 것이 아니라

 

 

 

 

 

 

**하이버네이트 적용

1.    pom.xml파일에 hibernatespring-orm라이브러리 의존성 설정

           <!-- 하이버네이트 사용을 위한 라이브러리 -->

                 <dependency>

                             <groupId>org.springframework</groupId>

                             <artifactId>spring-orm</artifactId>

                             <version>${org.springframework-version}</version>

                 </dependency>

 

                 <dependency>

                             <groupId>org.hibernate</groupId>

                             <artifactId>hibernate-entitymanager</artifactId>

                             <version>5.4.2.Final</version>

                 </dependency>

 

2.    dao패키지에 테이블과 dto매핑하는 xml파일을 생성하고 작성

=>기본패키지.dao(이름.hbm.xml) : 하이버네이트 설정 파일이라는 것을 알려주기 위해서 중간에 hbm을 추가

 

 

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

<!DOCTYPE hibernate-mapping PUBLIC

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.pk.db.domain">

           <class name="Item" table="ITEM">

                       <id name="itemid" column="ITEMID">

                       </id>

                       <property name="itemname" column="ITEMNAME" />

                       <property name="pictureurl" column="PICTUREURL" />

                       <property name="price" column="PRICE" />

                       <property name="description" column="DESCRIPTION" />

           </class>

</hibernate-mapping>

 

3.    root-context.xml파일에 하이버네이트 사용을 위한 설정을 추가

=>tx 네임스페이스에서 추가하고 작성

 

 

              <!-- 하이버네이트 사용을 위한 설정 -->

           <bean id="sessionFactory"

                class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">

                       <property name="dataSource" ref="dataSource" />

                       <property name="mappingResources">

                                  <list>

                                             <value>com/pk/db/dao/item.hbm.xml</value>

                                  </list>

                       </property>

                       <property name="hibernateProperties">

                                  <value>

                                             hibernate.dialect=org.hibernate.dialect.Oracle10gDialect

                                  </value>

                       </property>

           </bean>

          

           <!-- 하이버네이트는 트랜잭션 사용이 필수이기 때문에 추가 -->

          

           <tx:annotation-driven />

           <bean id="transactionManager"

           class="org.springframework.orm.hibernate5.HibernateTransactionManager">

                       <property name="sessionFactory" ref="sessionFactory" />

           </bean>

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형

'Study > spring' 카테고리의 다른 글

spring-6  (0) 2020.10.26
spring-5  (0) 2020.10.23
spring-3  (0) 2020.10.23
spring-2  (0) 2020.10.22
spring-1  (0) 2020.10.22
반응형

**@Autowired

=>동일한 자료형의 bean이 있으면 자동으로 주입시켜주는 어노테이션

=>클래스 안에서 변수를 선언하고 위에 @Autowired를 추가하는 형태로 작성

=>이 어노테이션 아래 선언한 변수는 setter메소드를 만들지 않아도 자동으로 주입이 됩니다.

=>이 어노테이션이 작성되면 반드시 동일한 자료형이 bean이 생성되어야 합니다.

bean이 없으면 bean이 없다고 예외가 발생

동일한 자료형의 bean2개 이상이어도 예외가 발생

=>나중에 bean을 생성할 거라면 @Autowired(required= false)를 설정하면 예외가 발생하지 않음

=>동일한 자료형의 bean2개 이상인 경우에는@Autowired아래에 @Qulifier(beanid)를 추가하면됩니다.

 

 

=>jdk 1.8 이상을 사용하는 경우에는 @Resource(name=빈의 아이디)를 이용해서도 설정 가능

=>inject라는 라이브러리를 추가하면 @Inject로도 주입을 받을 수 있습니다

 

 

Maven- build tool

spring-java Framework

 

실습

1.spring을 사용하는 maven프로젝트 생성- java application프로젝트

=>stseclipsests 플러그 인을 설치하고 [Spring Legacy Project]- [Spring Simple Mavern]프로젝트를 생성

프로젝트가 제대로 만들어지지 않고 MF파일만 생성

1)    Project를 선택하고 Mavern프로젝트로 변환

=>프로젝트를 선택하고 마우스 오른쪽을 클릭한 후 [Cofigure]-[Convert to Maven Project]

=>프로젝트에 M이 보이고 pom.xml파일이 생성

 

2)    Project에서 spring을 사용할 수 있는 설정을 추가

=>pom.xml파일의 project태그 안에 추가

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <groupId>spring</groupId>

  <artifactId>spring</artifactId>

  <version>0.0.1-SNAPSHOT</version>

 

  <!-- 이 코드를 pom.xml 파일에 붙여 넣습니다. -->

           <!-- 자주 사용하는 버전들의이름을 변수로 등록해두는 것이 properties입니다.

           없다고 해서 되지 않는 것은 아니다.-->

           <properties>

                       <!-- Generic properties -->

                      <!-- 자바 버전 -->

                       <java.version>1.8</java.version>

                       <!-- 소스 코드와 출력되는 결과의 인코딩 설정 -->

                       <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

                       <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

 

                       <!-- Spring -->

                       <!-- spring 버전 3-5까지  4.0.1, 5.0.7 -->

                       <spring-framework.version>5.0.7.RELEASE</spring-framework.version>

 

                       <!-- Hibernate / JPA(요즘에는 ) :하이버네이트-->

                       <hibernate.version>4.2.1.Final</hibernate.version>

 

                       <!-- Logging -->

                       <!-- 로그 라이브러리 버전 -->

                       <logback.version>1.0.13</logback.version>

                       <slf4j.version>1.7.5</slf4j.version>

 

                       <!-- Test -->

                       <!-- junit버전을 4.12이상 사용하는 것을 권장 -->

                       <junit.version>4.12</junit.version>

           </properties>

          

           <!-- 중앙 저장소 이외에서 다운로드 받아야 할 때 설정: 다운로드 받는 서버를 설정 -->

           <repositories>

          

           </repositories>

          

           <!-- 실제 사용할 라이브러리를 설정`-->

           <dependencies>

                       <!-- Spring and Transactions -->

                       <!-- Spring 기본 라이브러리 -->

                       <dependency>

                                  <groupId>org.springframework</groupId>

                                  <artifactId>spring-context</artifactId>

                                  <version>${spring-framework.version}</version>

                       </dependency>

                       <!-- spring트랜잭션 라이브러리 -->

                       <dependency>

                                  <groupId>org.springframework</groupId>

                                  <artifactId>spring-tx</artifactId>

                                  <version>${spring-framework.version}</version>

                       </dependency>

 

                       <!-- Logging with SLF4J & LogBack -->

                       <!-- 로그  라이브러리  -->

                       <!-- compile할때만 사용한다. 끝나면 없어진다. -->

                       <dependency>

                                  <groupId>org.slf4j</groupId>

                                  <artifactId>slf4j-api</artifactId>

                                  <version>${slf4j.version}</version>

                                  <scope>compile</scope>

                       </dependency>

                       <!-- runtime 실행할 때  -->

                       <dependency>

                                  <groupId>ch.qos.logback</groupId>

                                  <artifactId>logback-classic</artifactId>

                                  <version>${logback.version}</version>

                                  <scope>runtime</scope>

                       </dependency>

 

                       <!-- Hibernate -->

                       <dependency>

                                  <groupId>org.hibernate</groupId>

                                  <artifactId>hibernate-entitymanager</artifactId>

                                  <version>${hibernate.version}</version>

                       </dependency>

 

                       <!-- Test Artifacts -->

                       <!-- spring test -->

                       <!-- 이 라이브러리들은 test할 때만 존재하고 배포할 때는 자동으로 없어집니다. -->

                       <dependency>

                                  <groupId>org.springframework</groupId>

                                  <artifactId>spring-test</artifactId>

                                  <version>${spring-framework.version}</version>

                                  <scope>test</scope>

                       </dependency>

          

                       <!-- junit -->

                       <dependency>

                                  <groupId>junit</groupId>

                                  <artifactId>junit</artifactId>

                                  <version>${junit.version}</version>

                                  <scope>test</scope>

                       </dependency>

 

           </dependencies>

</project>

 

2     하는 자바 버전 변경

=>프로젝트를 선택하고 마우스 오른쪽을 클릭해서 [Build Path]-[Condigure Build Path]를 선택

=>JRE System Libarry를 선택하고 Edit를 눌러서 원하는 버전으로 변경 - 1.8 이상으로 변경

 

3     일반 프로젝트 구조

Dao -> service ->controller

 

1)    Dao클래스를 만들고 메소드 1개를 추가

=>di.Dao

public class Dao {

           public void insert() {

                       System.out.println("데이터 삽입 성공");

           }

}

 

2)    Service 클래스를 만들고 메소드를 1개 추가

=>di.Service

=>Dao 클래스의 인스턴스를 생성

           package di;

 

public class Service {

           //서비스가 Dao를 사용

           private Dao dao;

 

           public Dao getDao() {

                       return dao;

           }

 

           public void setDao(Dao dao) {

                       this.dao = dao;

           }

          

           public void insert() {

                       dao.insert();

           }

 

}

 

3)    Controller클래스를 추가하고 작성

package di;

 

public class Controller {

      private Service service;

 

      public Service getService() {

                 return service;

      }

 

      public void setService(Service service) {

                 this.service = service;

      }

     

      public void insert() {

                 service.insert();

      }

}

 

4)    Main메소드릉를 소유함 Main클래스를 만들고 작성

 

 

 

5 Spring에서는 개발자가 직접 생성자를 호출해서 인스턴스 만드는 것을 권장하지 않음

=>개발자가 클래스를 만들 때 디자인 패턴을 적용해서 만들고 수명 주기를 직접 관리해야 합니다.

클라이언트는 필요할 때 만들어야 한다.

1)    Spring bean configuration파일을 추가하고 작성

app.xml

      <!-- id는 개발자가 정하는 구별하기 위한 이름이고 class는 인스턴스를 생성할 클래스이름 -->

      <bean id ="dao" class="di.Dao"></bean>

      <bean id="service" class="di.Service"/>

      <bean id="controller" class="di.Controller"/>

 

2)    main 메소드 수정

                 //spring Bean설정 파일의 내용 가져오기

                 GenericXmlApplicationContext context = new GenericXmlApplicationContext("classpath:app.xml");

                 //설정 파일에서 bean 가져오기

                 Dao dao = context.getBean("dao",Dao.class);

                

                 Service service = context.getBean("service", Service.class);

                 service.setDao(dao);

                

                 Controller controller = context.getBean("controller", Controller.class);

                 controller.setService(service);

                 controller.insert();

                

                 context.close();

 

 

6 DI(Dependency Injdection -의존성 주입)

=>다른 클래스의 객체를 외부에서 생성해서 대입해주는 것

=>생성자를 이용하는 방법과 프로퍼티(setter)를 이용하는 방법

=>Spring 에서는 의존성 주입도 자바 코드가 아니라 설정에서 가능합니다.

 

<bean id="아이디" class="클래스경로">

      <constructor-arg value ="" />또는

<constructor-arg><ref bean ="다른 bean아이디"></constructor-arg>

 

<property name ="프로퍼티이름" value ="" /> 또는

<property name ="프로퍼티이름"><ref bean="다른 bean 아이디"/></propery>

</bean>

 

1)    app.xml을 수정

      <bean id ="dao" class="di.Dao"></bean>

      <bean id="service" class="di.Service">

                 <property name="dao">

                            <ref bean ="dao"/>

                 </property>

      </bean>

      <bean id="controller" class="di.Controller">

                 <property name="service">

                            <ref bean="service"/>

                 </property>

      </bean>

 

2)    main 메소드 수정

                 //spring Bean설정 파일의 내용 가져오기

                 GenericXmlApplicationContext context = new GenericXmlApplicationContext("classpath:app.xml");

                 //설정 파일에서 bean 가져오기

                 Dao dao = context.getBean("dao",Dao.class);

                

                 Service service = context.getBean("service", Service.class);

                 //설정 파일에서 주입을 했다면 주입하는 코드가 필요 없습니다.

                 //자바 코드는 없어지고 중간과정은 코드에서 사용하지 말자

                 //필요한 것만 사용

                 //service.setDao(dao);

                

                 Controller controller = context.getBean("controller", Controller.class);

                 //controller.setService(service);

                 controller.insert();

                

                 context.close();

 

 

7 Autowired

=>변수 위에 @Autowird를 추가하면 동일한 자료형의 bean이 있으면 자동으로 주입

setter도 필요없습니다.

=>어노테이션을 이용한 설정을 사용할려면 spring설정파일에 <context:annotaion-config/>가 추가되어야 합니다.

 

1)service클래스 수정

public class Service {

           //서비스가 Dao를 사용

           @Autowired //Dao가 클래스 타입의 bean이 있으면 자돋으로 주입

           private Dao dao;

           /*

           public Dao getDao() {

                       return dao;

           }

 

           public void setDao(Dao dao) {

                       this.dao = dao;

           }

           */

           public void insert() {

                       dao.insert();

           }

 

}

 

2)controller클래스 수정

public class Controller {

           @Autowired

           private Service service;

 

           /*

            * public Service getService() { return service; }

            *

            * public void setService(Service service) { this.service = service; }

            */

          

           public void insert() {

                       service.insert();

           }

}

 

3) app.xml수정

=>context namespace를 추가

 

           <bean id ="dao" class="di.Dao"></bean>

           <bean id="service" class="di.Service"></bean>

           <bean id="controller" class="di.Controller"></bean>

          

           <!-- namespace가 있어야 한다. -->

           <!-- 어노테이션 설정을 적용하기 위한 태그 -->

<context:annotation-config></context:annotation-config>

 

8 bean의 자동 생성

<context:component-scan base-package ="패키지이름" />

=>패키지에 속한 클래스 중에서 클래스 선언 위에 @Componet, @Controller, @Service, @Repository어노테이션이 추가된 클래스의 beam을 자동 생성

이 때 beanid는 클래스 이름의 첫글자를 소문자로 변경한 것입니다.

bean 을 만드는 코드를 쓸 필요없다.

 

1)controller, service, dao클래스 위에 @Component추가

 

2) app.xml수정

 

3)Main 클래스 수정

                       //spring Bean설정 파일의 내용 가져오기

                       GenericXmlApplicationContext context = new GenericXmlApplicationContext("classpath:app.xml");

                       //설정 파일에서 bean 가져오기

                       //Dao dao = context.getBean("dao",Dao.class);

                      

                       //Service service = context.getBean("service", Service.class);

                       //설정 파일에서 주입을 했다면 주입하는 코드가 필요 없습니다.

                       //자바 코드는 없어지고 중간과정은 코드에서 사용하지 말자

                       //필요한 것만 사용

                       //service.setDao(dao);

                      

                       Controller controller = context.getBean("controller", Controller.class);

                       //controller.setService(service);

                       controller.insert();

                      

            context.close();

 

 

**spring Mavern Project 의 테스트

=>Sprigng Project에서 테스트는 JUnit Spring-test 라이브러리를 이용

=>테스트는 점점 중요하게 평가받는데 최근에는 TDD(Test Driven Development)라는 개발 방법론도 등장

예전에는 어떤 기능을 전부 완성하고 테스트를 수행했습니다.

에러나 예외가 발생하면 디버깅하기가 어려웠고 웹 프로젝트 같은 경우는 거의 모든 부분을 완성해야 테스트를 할 수 있었음

 

어떤 기능이 있으면 작은 부분으로 쪼개서 가장 작은 부분 부터 제대로 수행되는지 테스트를 하고 이 코드가 테스트를 통과하면 다음 부분을 붙이는 형태로 프로그래밍을 하는 방식이 TDD입니다.

 

생년월일을 입력받아서 나이 계산

=>생년월일을 입력받기

=>올해 년도 가져오기

=> 올해 년도에서 생년월일 빼서 계산

 

내가 할 수 있는 최소한 부분을 나누어서 하기

***

**

*

**

***

SPRING TEST어려운 것은 설정파일이다. APP.XML

설정파일의 내용을 실행하도록 해야 한다.

 

 

=>SPRING에서 설정 파일에 있는 내용을 읽어서 테스트하는 방법

1. Test클래스를 생성하고 상단에 작성

@RunWith(SpingJUnit4ClassRunner.class)

@ContextConfiguration("설정파일의 경로를 작성")

=>설정 파일의 내용을 읽어서 사용이 가능

 

 

2.Service클래스의 insert메소드를 테스트

1)jnit버전에 4.10 이상인지 확인 -pom.xml파일에서 확인

 

 

2)spring-test라이브러리의 의존성이 설정되어있는지 확인

dependenciest->spring-test

 

test에서 하면 배포될때 없어질것이다.

 

C:\Users\admin\.m2\repository

eclipse 끄고 repository에 잇는 것을 전부 삭제하기

삭제한다음 07. spring\03. repository에 복사해서 옇기

 

 

lombok =>dto클래스

DTO ->속성들을 묶어서 표현하기 위한 클래스

class DTO{

           변수

           생성자

           접근자

}

 

**lombok

1.DTO클래스 -관계형 데이터베이스에서 테이블을 표현하기 위한 클래스

=>여러 개의 속성들을 묶어서 하나로 표현하기 위한 클래스

=>속성들을 private변수로 생성

=>매개변수가 없는 생성자와 매개변수가 있는 생성자를 생성

=>접근자 메소드를 생성

=>toStrin g메소드 재정의

 

2.DTO클래스를 만들 때 속성만 정의하고 어노테이션을 이용해서 나머지 작업을 수행해주는 라이브러리

 

 

3.설치

1)https://projectlombok.org/download에서 jar파일을 다운로드

 

2)jar파일을 생성 -command창에서 실행

java -jar lombok.jar

 

 

3)사용할 ide목록이 나오면 ide를 선택하고 [install/updata]를 ㅅ클릭

 

4)eclipse재시작

 

5)프로젝트 rebuild

이클립스 Lombok 사용시 Warning 문제 해결

 

 

4.lombok사용

1)pom.xml파일에 lombok 의 의존성 추가

                       <!-- lombok의 의존성 -->

                       <dependency>

                                  <groupId>org.projectlombok</groupId>

                                  <artifactId>lombok</artifactId>

                                  <version>1.18.8</version>

                       </dependency>

 

 

2)dto클래스 위에 작성

@Getter:모든 변수들의 getter메소드 생성

@Setter:모든 변수들의 setter 메소드 생성

@ToString

@Data: 생성자 , 접근자 메소드 ToString 전부 생성

 

 

 

**데이터베이스 사용

1.    프로그래밍 언어에서 데이터베이스를 사용하는 방법

1)    언어가 제공하는 코드를 이용

2)    프레임워크를 이용하는 방법

 

=>언어를 이용해서 작성하면 프레임워크의 영향을 받지 않기 때뭄에 프레임워크를 종속되지 않음

프레임워크를 사용하면 중북된 코드등을 제거하기 때문에 개발속도가 빠릅니다.

 

2.데이터베이스 연동 프레임워크의 종류

1) SQL Mapper:SQL과 프로그래밍 언어 코드를 분리시켜서 작성

=>sql을 작성하는 별도의 파일이나 클래스를 만들고 프로그래밍 언어가 호출하는 방식

=>개발이 쉽지만 성능은 떨어짐

 

2ORM(Object Relation Mapping) :프로그래밍언어의 클래스와 관계형 데이터베이스의 테이블을 매핑하는 방식으로 sql없이 작업

=>별도의 설정 파일을 이용해서 테이블과 클래스를 매핑시키고 실제 작업을 할 때는 클래스의 인스턴스를 가지고 작업

=>최근의 거의 모든 언어에서 지원을 하는 방식인데 sql mapper보다는 어렵지만 성능이 좋습니다.

 

 

 

3.Java의 데이터베이스 프레임워크

1)Mybatis: sql mapper방식

=>sqlxml파일이나 인터페이스에 작성하고 클래스에서 호출하는 방식

=>쉬워서 si업계에서 많이 사용

 

2)HIbernate:orm

=>sql을 이용하지 않고 자신만의 문법으로 관계형 데이터베이스를 사용하는 방법

=>어렵지만 성능이 좋아서 솔루션 업체에서 선호

=>최근에는 jpa와 같이 사용

 

 

**Mybatis

1.특징

=>javasql mapper framework

=>다른 언어 버전도 존재

 

2.spring project에서 mybatis를 사용할 때 필요한 라이브러리

=>spring-jdbc, mybatis, mybatis-spring

 

3.spring에서 데이터베이스를 사용할 떄는 데이터베이스 접속 정보를 반드시 bean으로 만들어야 합니다.

코드로 직접 설정하는 것은 안됩니다ㅏ.

 

4.spring에서 데이터베이스 접속정보를 저장하는 bean생성

org.springframework.jdbc.datasource.DriverManagerDataSource 클래스의 bean을 생성

 

=>필수

=>driverClassName 프로퍼티 : 데이터베이스 종류

=>url프로퍼티: 데이터베이스 접속 위치

 

 

=>username 프로퍼티: 계정 설정

=>password 프로퍼티: 비밀번호

 

usernamepassword는 입력하지 않아도 되는 경우가 있습니다.

 

 

 

5. 오라클 사용 준비와 접속 확인

=>url: ip주소

=>username:user01~ user30

=>password : user01 ~ user30

 

 

1)java에서 오라클을 사용할 려면 오라클 라이브러리를 다운로드 받아야 합니다.

=>pom.xml에 작성

=>오라클은 중앙 저장소에서 드라이버를 다운로드 제공하지 않기 때문에 repository를 설정해야 합니다.

 

 

=>dependencies 태그 바깥에 작성

           <!-- 중앙 저장소 이외에서 다운로드 받아야 할 때 설정: 다운로드 받는 서버를 설정 -->

           <repositories>

                       <repository>

                                  <id>codelds</id>

                                  <url>https://code.lds.org/nexus/content/groups/main-repo</url>

                       </repository>

           </repositories>

 

=>dependencies안에 작성

                       <dependency>

                                  <groupId>com.oracle</groupId>

                                  <artifactId>ojdbc6</artifactId>

                                  <version>11.2.0.3</version>

                       </dependency>

 

=>위 작업을 했는데 에러 표시가 나는 경우 - 다운로드를 반을 수 없다라는 에러

 

=>repositories수정

           <repositories>

<!--                 <repository>

                                  <id>codelds</id>

                                  https://code.lds.org/nexus/content/groups/main-repo

                       </repository> -->

                       <repository>

                                  <id>oracle</id>

                                  <name>ORACLE JDBC Repository</name>

                                  <url>http://maven.jahia.org/maven2</url>

                       </repository>

           </repositories>

 

=>dependency 수정

                       <!-- 오라클 의존성 -->

                       <dependency>

                                  <groupId>com.oracle</groupId>

                                  <artifactId>ojdbc7</artifactId>

                                  <version>12.1.0.2</version>

                       </dependency>

 

3)spring bean configuration파일을 추가하고 데이터베이스 접속 정보를 작성

            <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">

                       <property name="driverClassName"  value="oracle.jdbc.driver.OracleDriver" />

                       <property name="url" value="jdbc:oracle:thin:@ip주소:1521:xe" />

                       <property name="username"  value="user29" />

                       <property  name="password"  value="user29"/>

           </bean>

 

4) class이름에 에러

=>클래스 이름을 잘못 기재했거나 라이브러리가 다운로드 안된 겁니다.

=>pom.xml에 가서 클래스가 소속된 라이브러의 의존성을 설정했는지 확인해보고 설정했는데도 에러가 나면 다운로드가 제대로 안되는 것이므로 버전을 변경해보고 m2디렉토리를 삭제하고 다시 실행을 합니다.

 

org.springframework.jdbc.datasource.DriverManagerDataSource오류가 날 경우

=>pom.xml 파일에 spring-jdbc라이브러리의 의존성을 설정

                       <!-- spring에서 데이터베이스 사용할 때  사용할 라이브러리 의존성 -->

                       <dependency>

                                  <groupId>org.springframework</groupId>

                                  <artifactId>spring-jdbc</artifactId>

                                  <version>${spring-framework.version}</version>

                       </dependency>

 

디비 연력이 잴 먼저이다.

 

5)main 메소드를 소유한 클래스를 만들어서 데이터베이스 연결

 

 

 

6. Maven Projectgithub에서 내려받은 경우에는 마우스 오른쪽을 클릭해서 [Maven]-[Update Project]메뉴를 설정해야 합니다.

 

**MyBatis사용

1.java에서 Mybatis를 사용하는 방법

1)xml을 이용하는 방법

2)인터페이스를 이용하는 방법

 

2.xml을 이용하는 방법

1)mybatis환경 설정 파일을 생성 - 생략 가능

=>dto클래스의 패키지를 등록해서 mapper파일에서 패키지이름을 작성하지 않고 dto클래스를 사용하거나 mapkey이름과 데이터베이스의 컬럼이름 매핑등을 설정

 

2)mapper파일을 생성하고 필요한 sql을 작성

 

3)spring설정 파일에 sqlsession클래스의 bean 을 등록

 

4)dao클래스에 sqlsession을 주입받아서 sql을 생성

 

 

**실습

1.    실습에 사용할 테이블과 샘플 데이터를 생성

CREATE TABLE goods(

      code NUMBER(6) PRIMARY KEY,

      name varchar2(50) NOT NULL,

      manufacture varchar2(50),

      price number(10)

);

 

INSERT INTO goods(code, name,MANUFACTURE, PRICE)

VALUES (1,'낙지','목포',8000);

 

 

INSERT INTO goods(code, name,MANUFACTURE, PRICE)

VALUES (2,'과배기','포항',20000);

 

 

 

INSERT INTO goods(code, name,MANUFACTURE, PRICE)

VALUES (3,'인삼','금산',200000);

 

COMMIT;

 

SELECT * FROM GOODS;

 

 

2.    프로젝트에 테이블의 데이터와 매핑할 dto클래스를 생성

//접근자 메소드의 tosTRING메소드를 만들어주는 어노테이션

@Data

public class Good {

      private int code;

      private String name;

      private String manufacture;

      private int price;

}

 

 

3.    MyBatis 사용 설정

=>mybatismybstis-spring 라이브러리 설정

=>

               <dependency>

                                  <groupId>org.mybatis</groupId>

                                  <artifactId>mybatis</artifactId>

                                  <version>3.4.6</version>

                       </dependency>

                       <dependency>

                                  <groupId>org.mybatis</groupId>

                                  <artifactId>mybatis-spring</artifactId>

                       <version>1.3.2</version>

 

4.    mybatis 환경 설정 파일

=>dto클래스의 패키지이름이나 map의 컬럼 매핑 등을 설정

 

**xml

1.데이터를 표현하는 파일

=>상단에 dtd(!DOCTYPE태그)가 없음

=>개발자가 파싱해서 원하는 대로 사용

 

2.설정 파일

=>상단에 dtd(!DOCTYPE태그)가 있음

파일의 내용을 DTD에 설정한 곳에서 해석

=>정해진 규칙대로 코드를 작성

 

 

=>루트 디렉토리에 mybatis-config.xml 파일로 생성

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

<!DOCTYPE configuration

  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

  "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>

           <typeAliases>

                       <!-- sql파일에서는 sqlmapper 페키지이름을 생략할 수 있음 -->

                       <package name="sqlmapper"/>

           </typeAliases>

</configuration>

 

 

5.sql mapper파일 생성

=>실행할 sql을 작성하는 파일

1) mybatis와 테이블의 자료형 매핑

number <-> Integer , Double, Float, Byte, Short, Long, BigDecimal

char, varchar2, clob <-> String

data <-> java.sql.Date, java.util.Date

time <-> java.sql.Time, java.util.Date

timestamp <-> java.sql.Timestamp

blob <-> byte[]

 

2)select구문 작성

<select id="구분할 이름" resultType ="결과 자료형" parameterType="맥변수 자료형" >

           select

           from

           where

</select>

=>resultTypeselect절에 작성한 컬럼의 데이터를 전부 저장할 수 있는 자료형

select에서 하나의 컬럼만 가져오는 경우는 그 컬럼의 값을 저장할 수 잇는 자료형

여러 개의 컬럼을 가져오는 경우는 java.util.Map이나 dto클래스이름을 적어야 합니다.

=>parameterTypewhere절에서 값을 나중에 결정하는 것들 전체를 저장할 수 있는 자료형

select에서는 생략되는 경우도 있습니다.

=>where 절에 parameter를 만들 때는 #{컬럼이름}의 형태로 작성

 

 

3)insert,delete,update

<insert id="구분할 이름" parameterType ="매개변수 자료형">

           insert,update, delete구문

</insert>

 

4)Spring Confuguration파일에 설정 파일 등록

<bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">

           <property name ="dataSource" ref ="dataSource"/>

           <property name ="configLocation" value ="환경설정 파일 경로"/>

<property name ="mapperLocation" value ="sql 파일 경로"/>

 

</bean>

 

 

 

<bean class="org.mybatis.spring.SqlSessionTemplate" id ="sqlSession">

           <constructor-arg name ="sqlSessionFactory" ref="sqlSessionFactory"/>

</bean>

 

5)Dao클래스에 sqlSession을 주입받아서 sql메소드 호출

List<resultType> selectList("SQL id", 매개변수);

resultType selectOne("SQL id", 매개변수);

int insert("SQL id", 매개변수) //insert대신에 update, delete사용해도 결과는 같음

 

실습

=>mapper 파일들을 저장할  mappers디렉토리를 생성

 

=>mappers 디렉토리에 sql을 작성할 mapper파일을 만들고 sql을 작성

good.xml파일

 

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

<!DOCTYPE mapper

  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="good">

           <!-- goods테이블의 모든 데이터를 읽어오는 sql -->

           <!--  sqlmapper.Good를 해야 한는데 mybatis-config.xml에서 설정하였기 때문에 Good가능

           resultType select절의 컬럼들을 모두 저장할 수 잇는 자료형

           컬럼이 여러개 있 떄는 java.util.Map아니면 자기가 만든 DTO클래스  

           SELECT 에서 parameterType where절에 대입할 데터의 자료형

           없으면 지우면 된다.-->

           <select id="goodList" resultType="Good">

                       SELECT code, name, manufacture,price

                       FROM GOODS

           </select>

          

           <!-- code를 가지고 하나의 데이터를 찾아오는 sql -->

           <select id="gooddetail" resultType="Good" parameterType="java.lang.Integer">

                       SELECT code, name, manufacture,price

                       FROM GOODS

                       where code = #{code}

           </select>

          

           <!-- goods테이블을 데이터를 삽입하는 sql -->

           <insert id="goodinsert" parameterType="Good">

                       INSERT INTO goods(code, name,manufacture, price)

                       VALUES (#{code},#{name},#{manufacture},#{price})

           </insert>

          

           <!-- goods테이블을 데이터를 수정하는 sql -->

           <update id="goodupdate" parameterType="Good">

                       update

                       set name =#{name}

                         , manufacture = #{manufacture}

                         , price = #{price}

                       where code = #{code}

           </update>

          

           <!-- goods테이블에서 code를 이용해서 데이터를 삭제하는 sql -->

           <delete id="gooddelete" parameterType="java.lang.Integer">

                       delete goods where code = #{code}

           </delete>

</mapper>

 

=>spring bean configuration파일에 MyBatis를 사용할 수 있는 Bean 객체를 설정

 

           <!-- MyBatisxml을 이용해서 사용할 떄 필요한 설정 -->

           <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

                       <property name="dataSource" ref ="dataSource"></property>

                       <property name="configLocation" value="classpath:mybatis-config.xml"></property>

                       <property name="mapperLocations" value="classpath:mappers/good.xml"></property>

           </bean>

           <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">

                       <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>

           </bean>

 

=>main메소드에서 sql을 호출하는 코드 작성

 

 

=>예외

java.lang.IllegalArgumentException sql의 이름이 잘못될 경우

List<Good> list = sqlSession.selectList("goo.goodList"); =>이름이 잘못 되였을 경우

java,sql.sqlSyntaxErrorException sql이 잘못된 경우

NullPointer Exception: 파라미터를 제대로 대입하지 않아서

 

FIleNotFoundException: Mybatis 설정 잘못

 

Data 개발자

유저 도메인 지식 업무

data<-개발자 api 플랫폼 <- 도메인지식

 

**Mybatis의 장점

=>sqljava코드가 분리가 되기 때문에 유지보수가 용이

=>처음 한 번만 설정이 잘 되면 이후부터는 쉽게 추가가 가능

 

**Mybatis사용시 주의할 점

=>DTO클래스와 매핑을 시킬 때는 컬럼이름과 변수명이 같아야 쉽게 매핑이 됩니다.

이름 맞추기 잘 해야 한다.

 

=>Map을 이용하는 경우에는 오라클의 경우는 컬럼이름이 대문자로 리턴되는데 나머지 데이터베이스는 수문자로 리턴

=>오라클의 number자료형은 Map에 매핑하는 경우 BigDecimal로 매핑되기 때문에 정수나 실수로 사용하고자 할 때는 한번의 변환 과정이 더 필요합니다.

=>Map을 사용하게 되면 번거롭기 때문에 아직까지는 DTO클래스를 만들어서 작업을 하는 경우가 많습니다.

 

반응형

'Study > spring' 카테고리의 다른 글

spring-6  (0) 2020.10.26
spring-5  (0) 2020.10.23
spring-4  (0) 2020.10.23
spring-2  (0) 2020.10.22
spring-1  (0) 2020.10.22
반응형

**Mabatis -인터페이스를 이용한 사용

=>SQL Mapper(sql과 자바 코드의 분리) 방식의 데이터베이스 연동 프레임워크

=>사용법은 xml(예전 방식)을 이용하는 방법과 인터페이스 (최근의 방식)를 이용하는 방법

대부분 xml을 이용하는 방식이 초창기 방식이고 json이나 코드로 설정방식이 최근의 방식

 

1.spring프로젝트에서 MyBatis를 사용하기 위한 준비

=>spring-jdbc, mybatis, mybatis -spring 라이브러리

=>사용하고자 하는 데이터베이스 연동 라이브러리

 

=>데이터베이스 로그 기록 , lombok같은 라이브러리는 필수 사항이 아닙니다.

같이 사용을 많이 하기 때문에 필수 사항인것 처럼 여겨지는 것입니다.

 

 

2.인터페이스를 이용한 방식

=> 인터페이스를 생성

=>인터페이스 생성하고 데이터베이스 구동 메소드의 원형을 선언하고 위에 @하고자하는 sql이름(실제 sql)을 추가하해주면 됩니다.

=>spring bean configuration파일에 2개의 bean을 생성

sqlSessionFactoryBean을 생성하는데 여기에는 dataSource 프로퍼티에 사용할 데이터베이스의 DataSource를 설정

두번째는 MapperFacotryBean을 생성하는데 앞에서 만든 sqlSessionFactoryBean이 필요하고 또 하나는 인터페이스가 필요

인터페이스를 사용하는게 좀더 효율적이다 .별도 xml파일을 만들 필요가 없다.

 

=>다른 클래스에서 인터페이스를 주입받아서 사용하면 됩니다.

 

3.Goods테이블의 데이터의 crud작업을 mybatis 를 이용한 실습

1)데이터베이스 정보를 확인

-종류 : oracle

-url: ip주소 url주소:1521:xe(sid) 만약에 servicename을 이용하는 경우에는 /servicename

18c-> servivename으로 바꿨다.

-Username : user00

-password: user00

 

=>문서의 형태로 제공

 

 

 

 

popular확인하기

 

mariadb mybatis

db2 ibm

odbc ->원두어용

시각화 microsoft bi

db <-> odbc<-> ms bi tool

odbc-> 분석 을 하는데 c/c+

postgre sql->뮤료 개발자

sql server

sqlite->외부에서 접속이 안되서 embedded에서 사용한다. 프린트 등

apache hive : 하드배데이터를 에코시스템을 이용해서 일반 데이터베이스를 사용하게 끔 하는 것 java

 

mongoDB

SAP - HANADB 관계형데이터베이스

 

Oracle 대기업이 잴 많이 하는 것은 하나디비

공공기관 => tmax -> tibero

카카오는 mysql이다.

 

role 권한의 묶음

os authentication:운영체제로  서버나 cloud환경에서 하는 것

계정별로 권한이 정해진다.

mongodb는 아이디와 비밀번호 입력하지 않았다. ->os authentication

 

autocommit->하지 말아야 한다.

백업은 수시로 하기

 

 

2)프로젝트 생성

=> github에서 내려 받기

 

git연결

 

 

 

 

 

3)OralceMybatis를 사용하기 위한 이존성 라이브러리 설정

=>pom.xml 파일에 작성

           <!-- 중앙저장소 이외의 곳에서 라이브러리를 다운로드 받을 때 다운로드 받는 위치를 설정하는 태그 -->

           <repositories>

                       <repository>

                                  <id>oracle</id>

                                  <name>ORACLE JDBC Repository</name>

                                  <url>http://maven.jahia.org/maven2</url>

                       </repository>

           </repositories>

 

                       <dependency>

                                  <groupId>com.oracle</groupId>

                                  <artifactId>ojdbc7</artifactId>

                                  <version>12.1.0.2</version>

                       </dependency>

 

=>oracle, spring-jdbc,mybatis,mybatis-spring,lombok

 

4)  소스 코드를 작성할 src/main/java 디렉토리를 생성

 

5) java version1.8 로 변경

프로젝트를 선택하고 마우스 오른쪽을 클릭해서 [build path]-[configure bean path] 를 선택

 

jre system libary를 선택한 후 edit버튼을 눌러서 변경

=>배포할 때 상대방 컴퓨터에 설치된 자바의 최소 버전 설정이기도 합니다.

 

 

ios 13에서 개발하면 ios 13밖에 못 받는다.하위버전 안된다.

안드로이드는 os업데이트 잘 안한다.

 

전체 데이터 조회

select * from goods;

 

code를 가지고 하나의 데이터를 조회

select * from goods where code = 1;

 

데이터 삽입

insert into goods(code, name, manufacture, price)

values(3, '','나주',4500)

 

 

데이터 갱신 -기본키를 조건으로 해서 나머지 컬럼을 수정

update goods set name ='', manufacture ='이천',price=60000

where code = 3;

 

데이터 삭제 -기본키를 조건으로 해서 삭제

delete from goods

where code = 4;

 

6)Goods 테이블의 데이터를 표현할 DTO클래스를 생성

db.mybatis.domain.Good

@Data

public class Good {

           private int code;

           private String name;

           private String manufacture;

           private int price;

}

 

 

7)Dao역할을 수행할 인터페이스를 생성

=>db.mybatis.dao.GoodDao

 

열이 1  : 기본자료형 ,String ,Date

열이 여러개 : Map, Dto(사용자 정의 클래스)

행이 여러개 일 때는 위의 자료형의 LiST

행이 1개이면 위의 자료형 그대로

 

public interface GoodDao {

           //goods테이블의 전체 데이터를 가져오는 메소드

           //public 리턴타입 이름(매개변수);

           @Select("select * from goods")

           public List<Good> allGood();

          

           //code를 가지고 goods 테이블에서 데이터르 조회하는 메소드

           //code는 기본키

           @Select("select * from goods where code = #{code}")

           public Good detailGood(int code);

          

           //데이터를 추가하는 메소드

           @Insert("insert into goods(code, name, manufacture, price) "

                                  + "values (#{code},#{name},#{manufacture},#{price})")

           public int insertGood(Good good);

          

           //데이터를 수정하는 메소드

           //insert해도 되고 update해도 된다.

           @Update("update goods set name= #{name}, manufacture = #{manufacture}, price = #{price} "

                                  + "where code = #{code}")

           public int updateGood(Good good);

          

           //데이터를 삭제하는 메소드

           @Delete("delete goods where code=#{code}")

           public int deleteGood(int code);

}

 

8)spring설정 파일을 생성하고 GoodDaof를 위한 설정을 작성

src/main/resources

 

 

java - source(컴파일)

resource- file(컴파일 안해도 되는 것)

 

 

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

<beans xmlns="http://www.springframework.org/schema/beans"

           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

 

           <!-- 스프링에서 데이터베이스를 사용할 때 접속 정보를 저장할 bean -->

           <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">

                       <!-- 데이터베이스 종류 -->

                       <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>

                       <!-- 데이터베이스 위치 -->

                       <!-- 데이터베이스 응용법 마다 다르다. -->

                       <property name="url" value="jdbc:oracle:thin:@ip주소:1521:xe"></property>

                       <property name="username" value="user29"></property>

                       <property name="password" value="user29"></property>

           </bean>

          

           <!-- MyBatis를 인터페이스를 이용해서 사용할 떄 필요한 Bean -->

           <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">

                       <property name="dataSource" ref="dataSource"></property>

           </bean>

          

           <bean class="org.mybatis.spring.mapper.MapperFactoryBean" id="goodDao">

                       <property name="sqlSessionFactory" ref ="sqlSessionFactory"></property>

                       <property name="mapperInterface" value="db.mybatis.dao.GoodDao"></property>

           </bean>

          

           <!-- GoodDao Bean -->

           <!-- bean을 자동으로 만들어주는 작업이 있다. -->

           <!-- <bean id ="sample" class="mb.mybatis.dao.GoodDao"/> -->

</beans>

 

 

 

9)GoodDao 인터페이스의 Bean을 자동으로 생성되도록 설정

=>인터페이스 나 클래스 위에 @Component, @Controller, @Service,@Repository어노페이션 중 하나를 추가하고 spring설정 파일에 <contextannotaion-config/>,<context:component-scan base-package="패키지경로" />

 

 

 

10)main메소드를 소유한 클래스를 만들고 GoodDao객체를 사용

package db.mybatis;

 

import org.springframework.context.support.GenericXmlApplicationContext;

 

import db.mybatis.dao.GoodDao;

import db.mybatis.domain.Good;

 

public class MyBatisMain {

           public static void main(String[] args) {

                       GenericXmlApplicationContext context = new GenericXmlApplicationContext("classpath:applicationContext.xml");

          

                       //GoodDao dao = context.getBean("goodDao",GoodDao.class);

                       //아이디 없이 자료형으로 BEAN을 찾아오기

                       GoodDao dao = context.getBean(GoodDao.class);

                       //System.err.println(dao.allGood());

                      

                       //전페 데이터를 가져오는 메소드를 호출해서 확인

                       //List를 리턴하는 경우는 데이터가 없으면 List는 만들고 size 0

                       //size 0인 경우는 for문이기 깨문이다.

                       /*

                       List<Good> list = dao.allGood();

                       for(Good good:list) {

                                  System.out.println(good);

                       }

                       */

                       //code 1개의 데이터를 리턴받는 메소드를 출력

                       //1개의 행을 리턴하는 메소드는 리턴할 데이터가 있으면 데이터를 리턴하고

                       //없으면 null을 리턴합니다.

                       /*

                       Good good = dao.detailGood(2);

                       System.out.println(good);

                       */

                      

                       //삽입하는 메소드 호출

                       /*

                       Good good = new Good();

                       good.setCode(1);

                       good.setName("감귤");

                       good.setManufacture("제주");

                       good.setPrice(300);

                       try {

                                  int result = dao.insertGood(good);

                                  if(result>0) {

                                              System.out.println("데이터 삽입 성공");

                                  }else {

                                              System.out.println("데이터 삽입 실패");

                                  }

                       }catch(Exception e) {

                                  System.out.println("데이터 삽입 실패");

                                  e.printStackTrace();

                       }

                       */

                      

                       /*

                       Good good = new Good();

                       good.setCode(1);

                       good.setName("감자");

                       good.setManufacture("고성");

                       good.setPrice(3050);

                       try {

                                  int result = dao.updateGood(good);

                                  if(result>0) {

                                              System.out.println("데이터 수정 성공");

                                  }else {

                                              System.out.println("수정할 데이터가 없음");

                                  }

                       }catch(Exception e) {

                                  System.out.println("데이터 수정 실패");

                                  e.printStackTrace();

                       }

                       */

                      

                       try {

                                  int result = dao.deleteGood(3);

                                  if(result>0) {

                                              System.out.println("데이터 삭제 성공");

                                  }else {

                                              System.out.println("삭제할 데이터가 없음");

                                  }

                       }catch(Exception e) {

                                  System.out.println("데이터 삭제 실패");

                                  e.printStackTrace();

                       }

                      

                       context.close();

           }

}

 

 

**트랜잭션

=>Transaction한번에 수행되어야 하는 작업의 논리적인 단위

가게에서 물건을 구입한다변 가게 입장에서는 물건을 주고 금액을 받아야 합니다.

고객입장에서 보면 금액을 지불하고 물건을 받아야 합니다.

데이터베이스 입장에서 보면 가게는 금액을 수정하고 물건에 대한 정보를 수정해야 합니다.

가게 입장에서는 2개의 sql구문이 수행되어야 합니다.

고객입장에서보면 금액이 수정되어야 하고 물건에 대한 정보도 수정되어야 합니다.

고객입장에서도 2개의 sql문이 수행되어야 합니다.

dao sql4개를 실행해야 합니다.

이 경우 하나의 sql수행이 성공했다고 commit을 해버리면 잘못된 결과가 저장될 수 있습니다.

이런 경우는 4개의 sql이 모두 성공한 경우만 성공이고 나머지 경우는 실패라서 초기 상태로 되돌려야 합니다.

이렇게 한꺼번에 수행되어야 하는 sql을 하나로 묶은 것을 트랜잭션이라고 합니다.

 

1.트랜잭션 처리 방식

1)manual commit: 직접 commitrollback을 수행

2)auto commit:하나의 sql구문이 성공적으로 수행되면 자동으로 commit을 수행

=>javajdbcMybatis는 근본적으로 auto commit

 

 

2.mybatis 에서의 트랜잭션 처리(manual commit 사용ㅇ)

=>스프링 설정 파일에서 트랜잭션 매니져 객체를 생성

<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id ="transactionManager">

           <property name="dataSource" ref="dataSourceId" />

</bean>

=>트랜잭션 관리를 annotation으로 할 수 있도록 해주는 객체를 생성

<tx:annotation-driven transaction-manager ="앞에서 만든 beanid"/>

 

=>메소드 위에 @Transaction을 추가하면 메소드 수행도중 예외가 발생하면 rollback하고 예외가 발생하지 않으면 commit을 수행해 줍니다.

 

=>트랜잭션은 dao클래스에 적용하는 것이 아니고 Servicecontroller에 적용해야 합니다.

거래에 묶어 주어야 한다.

 

 

 

3.mybatis의 트랜잭션 처리 실습

1)service 클래스를 생성하고 데이터베이스 삽입 메소드를 2번 호출하도록 만들기

=>db.mybytis.service.GoodService

package db.mybatis.service;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

 

import db.mybatis.dao.GoodDao;

import db.mybatis.domain.Good;

 

//이 클래스의 bean은 자동 생성

@Service

public class GoodService {

          

           //동일한 자료형의 bean이 있으면 자동으로 주입해주는 어노테이션

           @Autowired

           private GoodDao goodDao;

          

           //데이터를 삽입하는 메소드

           public int insertGood(Good good) {

                       goodDao.insertGood(good);

                       return goodDao.insertGood(good);

           }

}

 

2)스프링 설정 파일에 GoodService인스턴스를 자동 생성하도록 설정

=>context네임스페이스 추가

 

 

 

=>코드 추가

           <!-- 어노테이션 설정을 사용할 수 있도록 해주는 태그 -->

           <context:annotation-config></context:annotation-config>

          

           <!-- bean자동 생성 패키지 등록 -->

           <!-- db에 어노페이션 있으면 자동으로 만들어진다. -->

           <context:component-scan base-package="db"></context:component-scan>

 

 

3) main메소드를 수정해서 호출하기

GenericXmlApplicationContext context = new GenericXmlApplicationContext("classpath:applicationContext.xml");

                      

                       //삽입할 데이터 생성

                       Good good = new Good();

                       good.setCode(1);

                       good.setName("무화과");

                       good.setManufacture("목포");

                       good.setPrice(3000);

                      

                       //GoodService 객체 가져오기

                       GoodService service = context.getBean(GoodService.class);

                       //메소드 호출

                       service.insertGood(good);

 

=>service insertGoode은 동일한 데이터를 2번 삽입하는 메소드 잆니다.

동일한 code2번 삽입할려고 해서 첫번째 데이터는 정상적으로 삽입이 되고 두번째 삽입할려고 할 때 예외가 발생합니다.

트랜잭션을 적용하지 않아서 auto-commit입니다.

첫번째 데이터가 삽입하는데 성공하면 데이터베이스에 반영되고 두번째 sql을 실행합니다.

첫번째 데이터는 삽입에 성공하고 두번쨰 삽입은 실패입니다.

 

 

4) 스프링 설정 파일에 mybatis 트랜잭션 적용을 위한 bean을 생성

=>tx 네임스페이스를 추가

 

=>코드 작성

           <!-- Mybatis 트랜잭션 적용을 위한 클래스의 객체 생성 -->

           <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">

                       <property name="dataSource"  ref="dataSource"></property>

           </bean>

          

           <!-- 트랜잭션을 어노페이션으로 설정하기 위한 설정 -->

           <tx:annotation-driven transaction-manager="transactionManager"/>

 

5) Service메소드에 트랜잭션을 적용

 

6) main메소드를 수정하고 실행

                       GenericXmlApplicationContext context = new GenericXmlApplicationContext("classpath:applicationContext.xml");

                      

                       //삽입할 데이터 생성

                       Good good = new Good();

                       good.setCode(4);

                       good.setName("무화과");

                       good.setManufacture("목포");

                       good.setPrice(3000);

                      

                       //GoodService 객체 가져오기

                       GoodService service = context.getBean(GoodService.class);

                       //메소드 호출

                       service.insertGood(good);

 

 

 

 

=>실행하면 두번째 삽입을 수행해다가 예외가 발생하면 첫번째 삽입은 성공했지만 하나의 트랜잭션으로 묶여 있어서 같이 취소됩니다.

 

**hibernate

=>ORM(Object Relation Mapper):하나의 테이블 과 클래스를 매핑하는 방식의 데이터베이스 프레임워크로 하나의 행을 하나의 인스턴스로 표현

=>sql을 이용하기도 하고 sql없이도 데이터베이스 작업이 가능

기본키를 가지고 하는 작업은 아주 쉽게 처리할 수 있습니다.

=>javaorm표준 specjpa라고 이에 대한 구현체가 hibernate

현재는 대다수의 프로그래밍 언어들에 orm 프레임워크가 구현되어 있습니다.

 

2.Hibernate의 장점

=>복잡한 jdbc코드를 제거

=>spring과의 통합 기능 제공

=>성능이 mybatis보다 우수 :카카오나 배달의 민족이 hibernate로 구현

 

3.단점

=>초기 설정이  mybatis에 비해서 어려움

=>si업계애서는 mybatis를 선택하고 솔루션 업계에서는 hibernate

 

r->데이터 통계분석

분석만 하면 r이 났다.

python

 

4.자료형 매핑

integer(number) :int, java.lang.Integer

long(number) : long, java.lang.long

double(number): double, java.lang.double

 

boolean yes/no , true/false: boolean java.lang.Boolean

 

date: java.sql.Date, java.util.Date

time: java.sql.Time, java.util.Date

timestamp: java.sql.Timestamp, java.util.Date

 

 

char, varchar(varchar2 - Oracle), string,clob- oracle, text

 

blob(파일의 내용 - 바이트 배열): java.sql.Blob

 

5.하이버네이트 Mapper만들기 - xml파일

<hibernate-mapping package="테이블과 매핑할 패키지 경로">

           <class name ="클래스이름" table ="테이블이름">

                       <id name ="변수이름" column ="컬럼이름"></id> //기본키 설정

                       <property name="변수이름" column ="컬럼이름"/>

                       ... 프로퍼티 추가

           </class>

</hibernate-mapping>

 

6) 하이버네이트 bean생성

1)PersistencyExceptionTranslationPostProcessor클래스의 bean 생성

2)LocalSessionFactoryBean클래스의 bean을 생성

=>DataSOurce, 하이버네이트 매퍼 파일, 데이터베이스 종류가 필요

 

7.하이버네이트 bean 객체 사용

=>sessionFactory 클래스의 bean 을 주입받아서 사용

getCurrenSession()을 호출하고 필요한 메소드를 호출

 

8.의존성 라이브러리

=>spring-orm, hibernate

 

**Goods테이블의 crud작업을 hibernate를 이용해서 처리

1.    Project생성

2.    pom.xml파일에 hibernate를 사용을 위한 의존성을 설정

=>oracle, spring-jdbc,spring-orm, hibernate

 

3.    테이블과  매핑할 dto클래스를 생성

=>db.hibernate.domain.Good

@Data

public class Good {

           private int code;

           private String name;

           private String manufacture;

           private int price;

}

 

4.    dto클래스와 연동할 테이블을 매핑하는 매핑 파일을 생성

=>db.hibernate.dao패키지에 good.hbm.xml

 

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

<!DOCTYPE hibernate-mapping PUBLIC

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

 

<hibernate-mapping package="db.hibernate.domain">

           <!-- 데이터베이스에서는 값만 대소문자 구분 -->

           <class name="Good" table="Goods">

                       <id name="code" column="code"></id>

                       <property name="name" column="name"></property>

                       <property name="manufacture" column="manufacture"></property>

                       <property name="price" column="price"></property>

           </class>

</hibernate-mapping>

 

 

pk가 여러개 있을 경우

class를 하나 만들거나 map을 하거나 해서

<id name="code" column="code1,code2"></id>

이런식으로 묶어면 된다.

 

5 src/main/resources디렉토리에 spring bean configuration파일을 추가

=>hibernateContext.xml

=>DataSource, hibernate관련 bean

1)context tx네임스페이스 추기

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

<beans xmlns="http://www.springframework.org/schema/beans"

           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

           xmlns:context="http://www.springframework.org/schema/context"

           xmlns:tx="http://www.springframework.org/schema/tx"

       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

                       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd

                       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

          

           <!-- 어노페이션을 이용한 bean생성을 위한 설정 -->

           <context:annotation-config/>

           <!-- 자동으로 bean을 생성할 패키지를 위한 서정 -->

           <!-- dao base-package="db" 여기 안에 만들어야 한다. -->

           <context:component-scan base-package="db"></context:component-scan>

          

           <!-- 트랜잭션을 어노페이션을 이용해서 사용할 수 있도록 해주는 설정 -->

           <tx:annotation-driven/>

          

           <!-- datasource -->

           <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">

                       <!-- 데이터베이스 종류 -->

                       <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>

                       <!-- 데이터베이스 위치 -->

                       <!-- 데이터베이스 응용법 마다 다르다. -->

                       <property name="url" value="jdbc:oracle:thin:@ip주소:1521:xe"></property>

                       <property name="username" value="user29"></property>

                       <property name="password" value="user29"></property>

           </bean>

          

           <!-- 하이버네이트 연동 Bean생성 -->

           <bean class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"

                       id="sessionFactory">

                       <property name="dataSource" ref="dataSource"></property>

                       <!-- hibernate 설정 파일 등록

                       설정 파일이 여러 개이면 value를 추가-->

                       <property name="mappingResources">

                                  <list>

                                              <!-- 테이블이 여러개면 계속 추가하면 도니다. -->

                                             <value>db/hibernate/dao/good.hbm.xml</value>

                                  </list>

                       </property>

                       <!-- 사용할 데이터베이스 종류 설정

                       데이터베이스 종류 별로 고정된 값-->

                       <property name="hibernateProperties">

                                  <value>

                                              hibernate.dialect = org.hibernate.dialect.Oracle10gDialect

                                  </value>

                       </property>

           </bean>

          

           <!-- 하이버네이트 트랜잭션 사용 bean -->

           <bean class="org.springframework.orm.hibernate5.HibernateTransactionManager"

                       id="transactionManager">

                                  <property name="sessionFactory" ref="sessionFactory"></property>

           </bean>

          

           <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor">

                      

           </bean>

          

</beans>

 

 

6.Dao클래스를 만들어서 데이터를 삽입하는 메소드 구현

=>db.hiberante.dao.GoodDao

//bean생성을 자동으로 해주는 어노테인션

@Repository

public class GoodDao {

          

           //하이버네이트 사용 변수 생성

           @Autowired

           private SessionFactory sessionFactory;

          

           //데이터 삽입 하는 매소드

           //@Transactional

           public int insertGood(Good good) {

                       sessionFactory.getCurrentSession().save(good);

                       return 1;

           }

}

 

 

7.main메소드를 소유한 HibernateMain클르새를 작성

public class HibernateMain {

           public static void main(String[] args) {

                       GenericXmlApplicationContext context = new GenericXmlApplicationContext("classpath:hibernateContext.xml");

                      

                       GoodDao dao = context.getBean(GoodDao.class);

                       Good good= new Good();

                       good.setCode(6);

                       good.setName("자동차");

                       good.setManufacture("울산");

                       good.setPrice(2000000000);

                       dao.insertGood(good);

                      

                       context.close();

                      

           }

}

 

8. 실행하고 데이터베이스 확인

오류 부분 수정:

<context:component-scan base-package="db.hibernate"></context:component-scan>

 

이 부분으로 수정

 

GoodDao.java에서

//데이터 삽입 하는 매소드

           @Transactional

           public int insertGood(Good good) {

                       sessionFactory.getCurrentSession().save(good);

                       return 1;

           }

 

정상 결과 =>

디비 확인=>

 

 

 

9.데이터 수정 기능 구현 -기본키를 가지고 조회해서 나머지 데이터 변경

1)Dao클래스에 메소드 추가

           // 데이터 수정 하는 매소드

           @Transactional

           public void updateGood(Good good) {

                       sessionFactory.getCurrentSession().update(good);

           }

 

2)main메소드 수정하고 테스트

public class HibernateMain {

           public static void main(String[] args) {

                       GenericXmlApplicationContext context = new GenericXmlApplicationContext("classpath:hibernateContext.xml");

                      

                       GoodDao dao = context.getBean(GoodDao.class);

                       Good good= new Good();

                       good.setCode(6);

                       good.setName("소고기");

                       good.setManufacture("뉴질랜드");

                       good.setPrice(150000);

                       dao.updateGood(good);

                      

                       context.close();

                      

           }

}

 

 

 

10.삭제 기능 구현

1)Dao클래스에 메소드 구현

           // 데이터 삭제 하는 매소드

           @Transactional

           public void deleteGood(Good good) {

                       sessionFactory.getCurrentSession().delete(good);

           }

 

 

2) main메소드를 수정하고 테스트

                       Good good= new Good();

                       good.setCode(6);

                       good.setName("소고기");

                       good.setManufacture("뉴질랜드");

                       good.setPrice(160000);

                       //dao.updateGood(good);

                      

                       dao.deleteGood(good);

 

3개는 정확하지 않아도 삭제가 된다.

good.setName("소고기");

good.setManufacture("뉴질랜드");

good.setPrice(160000);

기본키로 한다.

 

 

기본키로 하면 수월하는 데 그래서 잘 고려해야 한다.

 

 

 micro service ->소형 프로젝트

 

11.테이블의 데이터 전체를 가져오는 메소드

1)Dao클래스에 메소드를 추가

           // 테이블의 데이털르 전부 가져오는 메소드

           // public ? allGood(?){

           @Transactional

           public List<Good> allGood() {

                       // good클래스와 연결된 테이블의 모든 데이터 찾아오기

                       return sessionFactory.getCurrentSession().createCriteria(Good.class).list();

           }

 

           // code를 가지고 하나의 행을 찾아오는 메소드

           // public ? getGood(?){

           @Transactional

           public Good getGood(int code) {

                       return sessionFactory.getCurrentSession().get(Good.class, code);

           }

자료형을 확인하기

기본형

string date

map , (dict)

dto클래스

 

python의 분석의 결과를 주로 tuple로 준다.

dict  {"sloop":7,"interrpte":8}

python에서는 (7,8)

type로 해서 해야 한다.

 

python =>type , dir, help

 

2)main 메소드 수정 및 확인

package db.hibernate;

 

import java.util.List;

 

import org.springframework.context.support.GenericXmlApplicationContext;

 

import db.hibernate.dao.GoodDao;

import db.hibernate.domain.Good;

 

public class HibernateMain {

           public static void main(String[] args) {

                       GenericXmlApplicationContext context = new GenericXmlApplicationContext("classpath:hibernateContext.xml");

                      

                       GoodDao dao = context.getBean(GoodDao.class);

                       /*

                       Good good= new Good();

                       good.setCode(6);

                       good.setName("자동차");

                       good.setManufacture("울산");

                       good.setPrice(2000000000);

                       dao.insertGood(good);

                       */

                       /*

                       Good good= new Good();

                       good.setCode(6);

                       good.setName("소고기");

                       good.setManufacture("뉴질랜드");

                       good.setPrice(160000);

                       dao.updateGood(good);

                       */

                      

                       /*

                       Good good= new Good();

                       good.setCode(6);

                       dao.deleteGood(good);

                       */

                      

                       List<Good> list =dao.allGood();

                       for(Good good: list) {

                                  System.out.println(good);

                       }

                      

                       dao.getGood(1);

                      

                       context.close();

                      

           }

}

 

 

 

12.Dao 메소드에서 sql을 이용해서 데이터를 가져오도록 수정

 

 

r = a+b

k = r+c

 

k = a+b+c

           @Transactional

           public List<Good> allGood() {

                       // good클래스와 연결된 테이블의 모든 데이터 찾아오기

                       //return sessionFactory.getCurrentSession().createCriteria(Good.class).list();

                      

                       //sql을 이용해서 데이터 가져오기

                       //메소드에 리턴 값을 가지고 다른 메소드를 호출하느 것을

                       //메소드 체이닝이라고 합니다.

                       //r에서 %>%와 비슷하다.

                       return sessionFactory.getCurrentSession().createSQLQuery("select * from goods").addEntity(Good.class).list();

           }

 

**개발분야

=>si업체 :oracle+ mybatis조합에 View출력

=>중격기업 : mysql(Maria db)+ hibernate 조합에 데이터 출력(pdf,excel,csv, json,xml)이나 Mongo Db 사용

mongo db+hibernate =>이것은 안된다.

 

pk가 두개 있을 경우 :

<composite-id>

           <key-property name="code" column="" />

           <key-property name="code" column="" />

</composite-id>

 

 

class Inner{

           private int code;

           private String name;

}

 

class DTO{

           private Inner inner;

}

 

 

 

 

 

           @Transactional

           public Good getGood1(int code,String name) {

                       //return sessionFactory.getCurrentSession().get(Good.class, code);

                       //return sessionFactory.getCurrentSession().createSQLQuery("select * from goods where code = :code").addEntity(Good.class);

                       List<Good> list = sessionFactory.getCurrentSession().createSQLQuery("select * from Goods where code=:code and name=:name").addEntity(Good.class).setInteger("code", code).setString("name", name).list();

                       if(list == null || list.size() < 1) return null;

                       return list.get(0);

           }

 

                       dao.getGood1(1,"무화과");

반응형

'Study > spring' 카테고리의 다른 글

spring-6  (0) 2020.10.26
spring-5  (0) 2020.10.23
spring-4  (0) 2020.10.23
spring-3  (0) 2020.10.23
spring-1  (0) 2020.10.22
반응형

class A ->B

class Main ->A

class B

main메소드 있는 것을 찾아서 실행 ->Run

class들의  순서를 묶어서 하는 것이다. python에서는 __main__.py이다.

 

Main -> A -> B

실행했을 경우 B->A->MAIN

 

build는 실행가능한 파일을 만든다.

 

vs visual c가 재일 강력하다. 53기가이다.

visual statio 안에서 linux도 가능하다.

 

c언어는 외부 라이브러리를 사용하고 싶으면 직접 검색해서 다운로드 -> 파일을 include 해서 사용->

 

a.c-> b.c를 사용

b.c ->a.c를 사용

 

a.c (#include b.c)

b.c (#include a.c)

=>c언어에서는 오류가 난다.그래서 head를 잘 해야 한다.

 

 

검색->cran->다운로드 ->import 메모리에 가져오는 개념

c언어는 두번 include하면 에러 가 난다.

int a = 10;

int a = 20;

 

import는 메모리에서 가져온다.

 

import는 같은 것 있으면 덮어 씌운다.

 

str = 10 ;//python에서는 안된다. 기존의 str이 없어지는 개념이다.

 

사용가능한 라이브러리 ->repository ->개발자

                                                 ->개발자

버전 문제가 해결된다.

 

 

dependiencies ->필요한 라이브러리 가져오기

 

 

**Maven

=>java build tool

1. build

=> 컴파일(소스 코드를 운영체제나 Virtual Machine 이 이해할 수 있는 코드로 변환) 된 코드들을 가지고 실행 가능한 프로그램을 만들어내는 작업

코드들의 순서라던가 포함 관계를 파악해서 실행을 하게 되면 메모리에 순서대로 적재(로드)해서 실행해도록 해주는 것입니다.

 

2.java build tool의 종류

1) ant: build만해주는 tool

=>최근에는 거의 사용되지 않고 문법만 다른 툴에서 사용할 수 있도록 해주고 있습니다.

 

2)Maven: build tool이면서 외부 라이브러리 관리를 관리하게 해주는 tool

=>이전에 만들어진 java application들은 겅의 이 방식입니다.

 

3)gradle: build tool이면서 외부 라이브러리 관리를 관리하게 해주는 tool

=>andriod가 채택한 방식

=>build.gradle 이라는 설정 파일에 json방식으로 설정

 

3.maven

=>pom.xml파일을 이용해서 프로젝트를 관리

=>pom.xml파일에 설정을 하면 build를 할 때 그 설정에 따라 작업들을 자동으로 수행해주는 tool

 

4.maven설치

=>eclipse 계열의 IDE를 사용하면 내장되어 있습니다.

 

5.MAVEN프로젝트 생성

1)MAVEN프로젝트로 처음부터 생성

=>eclipse에서 maven프로젝트를 만들거나  spring프로젝트를 만든 경우

 

6.pom.xml 파일의 설정 태그

1)repositories

=>라이브러리를 다운로드 받을 저장소를 설정

=>설정하지 않으면 maven중앙 저장소에서 다운로드

=>오라클의 경우 오픈 소스가 아니라서 중앙 저장소에 없기 떄문에  repositories를 설정해야 만 다운로드 가능

=>공공기관이나 대기업의 경우는 별도의 저장소를 가지는 경우가 많아서 그 저장소를 설정합니다.

 

2)dependencies

=>실제 다운로드ㅡ 받을 외부 라이브러리를 설정

 

7. 라비으러리 사용 과정

1) pom.xml파일의 dependencies 태그에 라이브러리를 설정

 

2)projectbuild될 때 자신의 계정의 .p2디렉토리에서 라비브러리를 찾아서 사용

 

3)없으면 저장소에 다운로드 받아서 .p2에 저장하고 사용

 

 

8.인터넷이 느리거나 동시에 여러 컴퓨터가 접속해서 다운로드 받는 경우 제대로 다운로드가 안되는 경우가 있습니다.

이런 경우에는 다른 컴퓨터에서 reposirotyf를 복사해서 붙여넣기 한 후 사용해도 됩니다.

 

9.MySQL 라이브러리 클래스 로드 - 실습

1) java application프로젝트를 생성

 

java -> java project만들기

Main.java 만들기

 

2)Main클래스를 만들어서 실행

public class Main {

           public static void main(String[] args) {

                       try {

                                  Class.forName("com.mysql.jdbc.Driver");

                                  System.out.println("Mysql 드라이버 로드 성공");

                       }catch (Exception e) {

                                  System.out.println("MySQL 드라이버 다운로드 실패");

                       }                     

           }

}

 

 

3)실행을 하면 드라이버 파일이 없어서 예외가 발생

4) 이전의 방식으로 이 문제를 해결하고자 하는 경우

-java application: Mysql드라이버 다운로드 받고 프로젝트에 복사하고 파일을 선택한 후 builid path 에 추가를 해우저야 합니다.

 

-java web applicationL Mysql드라이버 다운로드 받고ㅗ 프로젝트의 webcontent/web-inf/lib디렉토리를 복사해서

 

5)maven프로젝트의  경우 -pom.xml 파일에 mysql의존성만 설정하면 됨. (프로젝트 종류와 상관없음)

=>프로젝트를 maven프로젝트로 변환

=> 프로젝트를 선텍히거 마우스 오른쪽을 클릭한 후

 

tensorflow -> numpy

           ->scikit-learn

 

a.c        -> b

b 를 설치하고 해야 한다

 

프로젝트를 선택하고 마우스 오른쪽을 클릭한 후 [COnfigure]- [convert to Maven Project]

=>생성된 pom.xml파일에 의존성을 설정하는 코드를 추가

 

<dependency>

    <groupId>mysql</groupId>

    <artifactId>mysql-connector-java</artifactId>

    <version>8.0.16</version>

</dependency>

 

 

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <groupId>java</groupId>

  <artifactId>java</artifactId>

  <version>0.0.1-SNAPSHOT</version>

  <build>

    <sourceDirectory>src</sourceDirectory>

    <plugins>

      <plugin>

        <artifactId>maven-compiler-plugin</artifactId>

        <version>3.8.0</version>

        <configuration>

          <source>1.8</source>

          <target>1.8</target>

        </configuration>

      </plugin>

    </plugins>

  </build>

  <dependencies>

   

           <dependency>

               <groupId>mysql</groupId>

               <artifactId>mysql-connector-java</artifactId>

               <version>8.0.16</version>

           </dependency>

 

  </dependencies>

 

 

</project>

 

6) 실행

=>프로젝트 안에  Maven Dependencies라는 디렉토리가 1개 만들어지고 mysql드라이버를 다운로드 하고 build pah에 추가를 해줍니다.

=>드라이브가 설치되어 예외가 발생하지 않습니다.

 

** STS(Spring Tool Suite)설치

=>Spring 학습을 할 때는 이 Tool을 많이 사용하고 우리나라에서는 공공기관(전자정부 프레임워크)이나 대기업 프로젝트(삼성 -Any Framework)를 할 때는 대부분 전용 프레임워크를 사용하는데 사용법이 sts랑 유사

1.sprint.io사이트에서 다운로드

 

2.eclipse plug-in으로 설치

=>[help] -[Eclipse Market Place]에서 sts를 검색

=>3.xx버전을 install

최근에는 4.xx 버전이 출시되었느느데 아직 현업에서는 3.xx버전을 이용

 

 

cloud 환경을 spring으로 많이 만든다.

빅데이터 저장 처리는 spring 으로 많이 한다.

Hadoop -> java이다. 처리 쪽은 자바만 가지고 애매하다 함수형이 안되서 그래서 java로 확정된 scala, clousure, kotlin

 

 

스프링

복잡하다. ->디자인 패턴

 

 

자바의 버전 3

java me : micro  용어가 좀 다르다. embedded할 경우 사용한다. 요부분은 iot라고 한다.

Iot(embedded) =>embedded는 피씨에서 작업을 안한다.

3개 인데 만드는 회사가 다르다. ->작제 만드는 것이다.

아트메가 128

아두이노 : 이탈리아

라즈베리파이 : 영국 linux를 깐다 .기능이 좀 더 많다.

 

 

 

java se : standard : java application

           스마트폰은 컴퓨터로 한다.

           스마트폰 applicatoin이나 피씨 application

 

java ee : enterprise web server applicatoin -> oracleeclipse에게 ee를 줬다.

instance가 잘못 만들어지면 여러가 만들 수 있고 메모리 낭비가 심하다.

특히 서버에서의 문제

 

 

 

제어의 역전 spring 에서는 class제공하는 것 만들고 

스프링에서는 개발하고 적기만 하면 알아서 해준다.

 

로그인 확인 -> 로기은 페이지

è  로그인 되여있으면 글 쓰기

 

상품

freamwork ->class제공 -------- >  ClassEX ->인스턴스 사용

 

MS  <-> JAVA

바꾸는 것인 문제이다.

 

머신러닝->알고리즘 구현 -> SCIKIT -LEARN ->TENSORFLOW->PYTORCH

tensorflow1.0, 2.0으로 바뀐다. 그래서 계속 공부하면서 적용해야 한다.

 

spring-> 큰 프로젝트를 할 경우 좀 더 쉽고 빨리 개발 하는 것이다.

 

 

스프링 프로젝트 종류

Spring Boot(Spring Starter Project): 간단하게 실행하고 배포가 가능한 수준의 애플리케이션을 만들 때 사용하는데 WAS 설정없이 실행이 가능하기 때문에 테스트 하기에 편리하지만 기존의 웹 프로젝트 설정과 다른 방법으로 사용해야 하고 JSP 설정은 별도로 수행

=>jsp도 출력하는 방식이 다르다.  최근에는 이것이 많이 나온다.

 

Spring Template Project(Spring Legacy Project): WAS를 사용하거나 이전에 Spring Project를 만들어 본 경우 사용하는 방식인데 WAS로 인한 리소스 소모가 심하다는 단점이 있지만 기존 프로젝트들이 이 방식으로 많이 만들어져 있음

=> 그전에 한 것

 

spring 5 버전까지 나왔다. 하지만

4 버전 부터 cloud등이 나왔다. api서버도

 

 

java 1.8로 바꾸는 것이좋다.

java 1.8 부터 :

1)    try ~ resource

try(){

}

()안에 사용하면 close안해도 된다. 자동으로 메모리 close가 된다. 1,7에서 추가했다.

2)    람다와 스트림 api함수를 프레임워크

 

1.8 ->big data때문에 하면

함수 단위로 뭔가 하면 1.8이부터

**IoC(제어의 역전)

=> 클래스는 개발자가 만들고 클래스의 인스턴스는 프레임워크가 was가 만들어서 일반적인 프로그래밍의 흐름의 반대로 수행되는 것

 

 

상속의 단점 이 <-> 프레임워크 사용의 단점

알고리즘 공부 여부

 

simple java 선택

 

1.Factory Method Pattern 실습

1)    Java Project를 생성

 

 

1)    Temp 클래스 생성

public class Temp {

      private int num;

      private String name;

      public Temp(int num, String name) {

                 super();

                 this.num = num;

                 this.name = name;

      }

      public Temp() {

                 super();

      }

      public int getNum() {

                 return num;

      }

      public void setNum(int num) {

                 this.num = num;

      }

      public String getName() {

                 return name;

      }

      public void setName(String name) {

                 this.name = name;

      }

      @Override

      public String toString() {

                 return "Temp [num=" + num + ", name=" + name + "]";

      }

}

 

2)    main 클래스를 소유한 main클래스를 만들고 Temp클래스를 사용

 

public class Main {

           public static void main(String[] args) {

                       Temp temp = new Temp();

                       temp.setNum(1);

                       temp.setName("Park");

                      

                       System.out.println(temp);

           }

}

=>사용자가 만든 클래스를 가지고 직접 생성자를 호출해서 인스턴스를 만들고 사용

 

2.Factory Method Pattern

=>클래스의 인스턴스를 new를 직접 호출해서 생성하지 않고 다른 클래스의 메소드를 이용해서 생성하는 방식

=>만드는 과정이 복잡하거나 디자인 패턴이나 기타 코드를 클래스에 추가하고자 하는 경우 사용

 

 

3.실습

1)Factory 클래스로 사용할 클래스를 추가

TempFacory 클래스

//temp 클래스의 Facotry 클래스

public class TempFacory {

           public static Temp create() {

                       return new Temp();

           }

}

 

2)main메소드 수정

public class Main {

           public static void main(String[] args) {

                       Temp temp1 = TempFacory.create();

                       temp1.setNum(2);

                       temp1.setName("Park1");

                      

                       System.out.println(temp1);

           }

}

TempFacory클래스가 spring 으로 생각한다.대신해줬다. 도대체 왜 하는지?

 

 

4.Singleton패턴

=>클래스가 인스턴스를 1개만 만들 수 있도록 된 디자인 패턴

=>서버쪽 클래스들은 대부분의 경우 여러 개의 인스턴스를 만들지 않고 하나의 인스턴스가 스레드를 이용해서 클라이언트 들의 요청을 처리하도록 해야 하는 경우가 대부분이고

clinet가 똑같은 일을 한다.하지만 동시에 오지 않는다.

서버가 3개가 있는 것이 아니라 하나 있어 도 된다.

서버가 만들고 없에는 데에 걸리는 것도 고려해야 한다.

클라이언트1 이 처리하다가 클라이언트2가 오면 대기 해서 스레드를 사용하면 된다.

 

스레드 - 함수 단위

메소드 (함수)

변수-> 함수->클래스 -> 객체

객체를 만든 이유는 포장을 하는 이유는 안전하기 떄문이다.

객체 지향은 안정성 때문이다.

 

서버쪽에서  메소드를 사용할려면 스레드를 사용한다.

스레드는 동시에 하는 것이 아니라 쉬는 시간이나 끝나면 한다.

메소드는 짧아야 한다.

 

프로그램은 함수 단위로

 

여러개 인스턴스를 만들지 않게 하려면 SINGLETON을 알아야 한다.

singleton 한개만 만들어야 한다.목적이 공유이다. static

static은 하나만 만들어서 공유한다.

//temp 클래스의 Facotry 클래스

public class TempFacory {

           //TempFacory 메소드

           //spring이 하는 역할

           static Temp temp = new Temp();

           public static Temp create() {

                       //return new Temp();

                       return temp;

           }

}

 

public class Main {

           public static void main(String[] args) {

                       /*

                       Temp temp = new Temp();

                       temp.setNum(1);

                       temp.setName("Park");

                      

                       System.out.println(temp);

                       */

                       //만들어서 사용해서 쓰면 된다.

                       //singleton인지

                       Temp temp = TempFacory.create();

                       temp.setNum(1);

                       temp.setName("Park");

                      

                       System.out.println(temp.hashCode());

                      

                       Temp temp1 = TempFacory.create();

                       temp1.setNum(2);

                       temp1.setName("Park1");

                      

                       System.out.println(temp1.hashCode());

                      

                       //spring에서는 우리가 만들지 않는다. 사용하기만 한다.

                       //만들어주는 것을 Facorty 제어의 역전이라고 한다.

                      

           }

}

** Spring java application project 생성

1.    [File] -[New] - [Other] - [spring project] - [simple spring maven] - [ project] finish

2.    디렉토리가 생성되지 않은 경우

1)    Maven 프로젝트  변환

프로젝트를 선택하고 마우스 오른똑을 누른 후 [configure] - [conbert to mavern  project]

2)    pom.xml파일에 블로그의 코드를 복사해서 붙여 넣기

project 태그 안에 작성

<project xmlns="http://maven.apache.org/POM/4.0.0"

           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

           xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

           <modelVersion>4.0.0</modelVersion>

           <groupId>spring</groupId>

           <artifactId>spring</artifactId>

           <version>0.0.1-SNAPSHOT</version>

 

           <!-- 이 코드를 pom.xml 파일에 붙여 넣습니다. -->

           <!-- 자주 사용하는 코드를 프로퍼티로 설정해놓은 태그

           프로그램에서 변수를 만드는 것과 유사 -->

           <properties>

                       <!-- Generic properties -->

                       <!-- 자바 버전 -->

                       <java.version>1.8</java.version>

                       <!-- 소스 코드와 출력되는 문자열을 인코딩 설정 -->

                       <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

                       <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

 

                       <!-- Spring -->

                       <!-- spring 버전 4.0.1, 5.0.7 -->

                       <spring-framework.version>5.0.7.RELEASE</spring-framework.version>

 

                       <!-- Hibernate / JPA(요즘에는 ) -->

                       <hibernate.version>4.2.1.Final</hibernate.version>

 

                       <!-- Logging -->

                       <!-- 로그 라이브러리 버전 -->

                       <logback.version>1.0.13</logback.version>

                       <slf4j.version>1.7.5</slf4j.version>

 

                       <!-- Test -->

                       <!-- 테스트 라이브러리 버전으로 최근에는 4.12이상 사용해야 함 -->

                       <junit.version>4.12</junit.version>

           </properties>

          

           <!-- 의존성 라이브러리 설정 -->

           <dependencies>

                       <!-- Spring and Transactions -->

                       <!-- 스프링 기본 라이브러리 -->

                       <dependency>

                                  <groupId>org.springframework</groupId>

                                  <artifactId>spring-context</artifactId>

                                  <version>${spring-framework.version}</version>

                       </dependency>

                       <dependency>

                                  <groupId>org.springframework</groupId>

                                  <artifactId>spring-tx</artifactId>

                                  <version>${spring-framework.version}</version>

                       </dependency>

 

                       <!-- Logging with SLF4J & LogBack -->

                       <!-- 로그 기록 라이브러리 설정 -->

                       <dependency>

                                  <groupId>org.slf4j</groupId>

                                  <artifactId>slf4j-api</artifactId>

                                  <version>${slf4j.version}</version>

                                  <scope>compile</scope>

                       </dependency>

                       <dependency>

                                  <groupId>ch.qos.logback</groupId>

                                  <artifactId>logback-classic</artifactId>

                                  <version>${logback.version}</version>

                                  <scope>runtime</scope>

                       </dependency>

 

                       <!-- Hibernate -->

                       <dependency>

                                  <groupId>org.hibernate</groupId>

                                  <artifactId>hibernate-entitymanager</artifactId>

                                  <version>${hibernate.version}</version>

                       </dependency>

 

                       <!-- Test Artifacts -->

                       <!-- spring test -->

                       <dependency>

                                  <groupId>org.springframework</groupId>

                                  <artifactId>spring-test</artifactId>

                                  <version>${spring-framework.version}</version>

                                  <scope>test</scope>

                       </dependency>

          

                       <!-- junit -->

                       <dependency>

                                  <groupId>junit</groupId>

                                  <artifactId>junit</artifactId>

                                  <version>${junit.version}</version>

                                  <scope>test</scope>

                       </dependency>

 

           </dependencies>

</project>

 

 

3)    속성을 2개 갖는 클래스를 생성

=> 디렉토리가 만들어진 경우에는 src/main/java라는 디렉토리에 생성하고 그렇지 않은 경우는 root디렉토리에 생성

=>디렉토리가 없는 경우는 프로젝트를 선택하고 source folder를 추가(main/src)하고 클래스를 추가

 

** spring Bean Container

=>spring에서는 spring이 제어권을 가지고 생성하고 관계를 설정하는 객체를 spring bean이라고 합니다.

Beanspring이 객체를 생성하고 관리하는 제어의 역전이 적용된 객체

=>Bean Container을 이용하는 방법

1.  annotation을 이용하는 방법

1) 설정

=>클래스를 만들고 클래스 위에 @Configuration어노테이션을 추가

=>인스턴스를 생성해서 리턴하는 메소드 위에 @Bean이라는 어노테이션을 추가

 

2) 사용

AnnotaitionConfigApplicationContext 변수명 = new AnnotationConfigApplicationContext(1번에서(앞에서 )만든 클래스이름.class);

인스턴스이름 = 변수명.getBean("메소드이름", 메소드가 리턴하는 클래스이름.class);

=>이렇게 만들면 싱글톤을 적용하지 않아도 자동으로 싱글톤 패턴의 객체가 리턴됩니다.

 

3)실습

=>Factory 클래스의 역할을 수행할 클래스를 생성

domain.Factory클래스

//spring Bean을 설정해주는 클래스라는 어노테이션

@Configuration

public class Factory {

           //Bean을 만들어주는 메소드 라는 어노테이션

           @Bean

           public static Item create() {

                       return new Item();

           }

}

 

 

=>main메소드를 소유한 클래스를 만들어서 인스턴스를 만든 후 테스트

domain.SpringMain

public class SpringMain {

           public static void main(String[] args) {

                       //springContainer 클래스 객체 만들기

                       AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Factory.class);

                       //Bean생성 메소드를 호출해서  bEAN을 생성

                       //Facory클래스의 create라는 메소드를 이용해서 인스턴스를 생성하고 리턴

                       Item item1 = context.getBean("create",Item.class);

                       item1.setNum(1);

                       item1.setName("사과");

                       System.out.println(item1);

                       //해시코드 출력

                       System.out.println(item1.hashCode());

                      

                       Item item2 = context.getBean("create",Item.class);

                       item2.setNum(2);

                       item2.setName("한라봉");

                       System.out.println(item2);

                       System.out.println(item2.hashCode());

           }

}

 

어노테이션을 이용해서 사용하는 방법이다.

 

2.xml을 이용하는 방법 : 현재까지는 이 방법을 많이 사용

1)spring bean configuration파일을 추가

 

2)객체를 생성하는 테그를 설정

클래스 경로에 해당하는 객체를 생성해서 리턴 ~ 싱글톤

<bean id="아이디" class="클래스 경로" />

 

3)사용

GenericXmlApplicationContext 변수명 = new GenericXmlApplicationContext(xml파일 경로);

인스턴스이름 = 변수명.getBean("메소드이름/아이디", 메소드가 리턴하는 클래스이름.class);

 

4)실습

=>spring bean configuraion file을 추가 -applicationcontext.xml

 

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

<beans xmlns="http://www.springframework.org/schema/beans"

           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

          

           <!-- domain.Item이라는 클래스의 객체를 만들어주는 태그 -->

           <bean id="item" class="domain.Item"/>

</beans>

 

=>main 메소드수정

SpringMain.java

                       GenericXmlApplicationContext context = new GenericXmlApplicationContext("classpath:applicationcontext.xml");

                       //xml일 파일을 이용할 때는 id를 기재

                       Item item1 = context.getBean("item",Item.class);

                       item1.setNum(1);

                       item1.setName("사과");

                       System.out.println(item1);

                       //해시코드 출력

                       System.out.println(item1.hashCode());

                                             

                       Item item2 = context.getBean("item",Item.class);

                       item2.setNum(2);

                       item2.setName("한라봉");

                       System.out.println(item2);

                       System.out.println(item2.hashCode());

3.Bean태그의 속성

1) class: 생성할 인스턴스의 class - 패키지이름까지 포함시켜야 합니다.

 

2) id : 외부에서 인스턴슬ㄹ 가져다가 사용하기 위한 이름

=>생략하면 클래스이름 뒤에 #0을 붙입니다.

 

3)init-method: 인스턴스를 생성할 때 호출되는 메소드

 

4) destroy - method:인스턴스가 소멸될 때 호출되는 메소드

 

5) lazy-init(지연 생성) :true를 설정하면 처음부터 만들어지지 않고 처음 사용할 때 만들어집니다.

=>클라이언트 프로그램을 제작할 떄 사용

=>lazy-initfalse이면 프로그램이 실행될 때 전부 만들어지고 실행

서버는 전부 만들어 놓고 사용하고 client는 필요할 때 생성한다. 메모리 때문에

 

 

6)scope: web에서만 설정하는 것이므로 기본은 singleton이고 호출할 때마다 생성하는 prototype이나 request, session등의 scope 를 설정하는 것이 가능

 

**DI(Dependency Injection - 의존성 주입)

=>의존성: 클래스의 객체가 다른 클래스의 객체에서 사용되는 것

=>주입: 클래스 안에서 사용하는 객체를 내부에서 만들지 않고 외부에서 만드는 것을 대입 받는 것

주입을 받는 방법은 생성자에서 받는 방법이 있고 setter를 이용해서 주입받는 방법이 있습니다.

spring에서의 di는 생성자나 setter를 이용해서 직접 받는 것이 아니고 설정파일을 이용해서 주입받는 것

 

 

a(b()) =>a 메모리 영역을 만들어야 하는데 b영역 만들고  끝나면 a로 돌아와서 a 를 한다. 메소드안에서 메소드 부르면 제귀

 

x= b() =>b 를 끝나고 a를 한다.

a(x)

 

필요할 때 추가하는 것이 좋다. 코드의 가독성 때문이다.

필요할 때 하는 것이 좋고 메모리 절약

DI di1 = new DI(msg: msg) ;// andriod이나 intelliJ에서 해준다.

 

생성자를 이용할 때는 변수를 잘 사용해야 한다.

 

 

1.    spring에서의 의존성 주입

=>생성자(contructor)를 이용한 주입

=>프로퍼티(property - setter)를 이용한 주입

 

2.    생성자를 이용한 주입

<bean class ="클래스 경로" id ="beanid">

      <constructor-arg value =""/>

</bean>

=>consturctor의 매개변수가 여러 개 인 경우에는 index속성을 이용해서 인덱스(순서)를 설정

 

3.    생성자를  이용한 의존성 주입을 위한 실습

1)    프로퍼티 1개를 갖는 클래스를 생성

=>프로퍼티(property) : 변수와 접근자 메소드를 모두 가진 것

접근자 메소드 없이 변수만 존재하는 경우 멤버 변수

public class DTO {

           private String name;

 

           public DTO() {

                       super();

           }

          

           public DTO(String name) {

                       super();

                       this.name = name;

           }

 

           public String getName() {

                       return name;

           }

 

           public void setName(String name) {

                       this.name = name;

           }

          

}

 

 

2)    main /src-> src/main /resources디렉토리에 Spring bean Configration file을 생성

=>diconfig.xml

 

3)    di패키지에 main메소드를 소유한 클래스를 만들고 앞에서 만든 bean가져다 사용하기

파일이 없으면 경로를 틀리거나 파일을 없을 경우

=>main메소드에 작성

생성자를 이용한 주입

public class DIMain {

           public static void main(String[] args) {

                       //스프링 설정 파일의 경로 설정

                       GenericXmlApplicationContext context = new GenericXmlApplicationContext("classpath:diconfig.xml");

                       //bean찾아오기

                       //클래스이름 변수명 =context.getBean("id",클래스이름.class);

                       //주입 받는 코드가 없음

                       DTO dto = context.getBean("dto",DTO.class);

                       System.out.println(dto);//di.DTO@1b26f7b2 이상한 hash코드가 나온다.

                       //diconfig.xml파일에서 설정한 내용이 출력

                       System.out.println(dto.getName());

                      

                       context.close();

           }

}

 

 

4.property를 이용한 주입

<bean id ="아이디" class="클래스경로">

<property name="프로퍼티이름" value=""/>

</bean>

=>property가 여러개 이면 property태그를 추가해서 해결

=>property태그의 name에 설정하는 것은 변수명이 아니고 setter메소드에서 set을 제외한 부분의 첫 글자만 소문자로 변경한 것입닏.

어느 언어에서든지 간에 property라고 부를 때는 변수명이 아니고 gettersetter메소드에서 getset을 제외한 부분의 첫글자만 소문자로 변경한 것입니다.

 

1)     diconfig.xml파일에 프로퍼티를 이용한 주입 코드를 작성

      <bean id="dto1" class="di.DTO">

                 <property name="name" value="프로퍼티를 이용한 주입"></property>

     </bean>

 

2)    main메소드 추가

           DTO dto1 = context.getBean("dto1",DTO.class);

                 System.out.println(dto1);

               System.out.println(dto1.getName());

 

 

value는 값이고

reference는 참조이다.

 

 

4.    다른 bean을 주입

=>value는 직접 값을 설정하는 형식

=> 이미 만들어진 다른 bean을 주입하는 것이 가능

 

<constructor-arg>

      <ref bean ="다른 beanid" />

</constuctor-arg>

 

<property name ="프로퍼티이름">

<ref bean="다른 beanid"/>

</property>

 

1)    diconfig.xml에 추가

    <bean id ="string" class="java.lang.String">

           <constructor-arg value="다른 beam 이용한 주입"></constructor-arg>

    </bean>

   

    <bean id="dto2" class="di.DTO">

           <!-- NAME프로퍼티에 STRING이라는 BEAN 대입 -->

           <property name="name">

                  <ref bean="string"></ref>

           </property>

   </bean>

 

2)    main 메소드에서 확인

 

6.Main Project를 만들고 이전 실행이 잘 되었는데 git hub에 업로드 한 후 제대로 실행이 안되면 프로젝틀 선택하고 마우스 오른쪽을 클릭한 후 [Maven] -[update project] 를 한 후 실행

 

7.cp네임스페이스를 이용하는 방법

1)    c 네임 스페이스를 설정파일에 추가하면 생성자를 이용한 주입을 bean태그의속성으로 가능

c: 이름 = 값을 추가하는 것이 가능

 

2)    p 네임스페이스를 추가하면 프로퍼티를 이용한 주입을 bean 태그의 속성으로 가능

p:이름 = ""

p:이름-ref ="다른 bean의 아이디"

8.집단 자료형의 주입

=>list, set ,map, properties

1)List타입의 데이터를 주입하고자 하는 경우

<list value- type="자료형">

      <value></value>

      <value></value>

      ...

</list>

=>value - type을 생략하면 자료형을 유추합니다.

=>다른 bean의 참조를 대입할 때는 <value>대신에 <ref bean="beanid"/>

=>배열과 list의 차이

배열은 크기가 고정 ,중간에 데이터를 삽입하거나 삭제를 할려면 배열을 복사해두고 작업, 메모리 낭부가 없음

list는 크기 변경 가능, 여분의 메모리를 가지고 있어야 하므로 메모리 낭비가 발생

 

2)Map

=>keyvalue를 쌍으로 저장하는 자료구조

<map>

      <entry>

      <key>key의 값</key>

      <value>value의 값</value>

</entry>

</map>

 

3)properties

=>keyvalue를 쌍으로 저장하는 자료구조

=>map과 다른 점은 mapkeyvalue에 모든 자료형이 가능하지만 properties.keyvaluejava.lang.String만 됩니다.

<props>

      <prop key="key의 값" >value</prop>

</pops>

 

4)Set

=>데이터를 중복없이 순서와 상관없이 저장

=>설정 방법은 list동일한데 태그의 이름만 set으로 설정

 

 

9.xml설정과 어노테이션 설정을 같이 사용

context네임스페이스 annotation-config태그를 xml설정 파일에 추가해주어야 합니다.

 

<context: annotation-config/>

 

 

 

클래스의 bean생성 -Ioc

.객체를 대신 만들어주는 것

<bean id="아이디" class="클래스경로" >

</bean>

 

bean에 다른 bean또는 값을 주입 -DI

<bean id="아이디" class="클래스경로" >

      <property name ="프로퍼티이름" value ="" />

</bean>

 

 

<bean id="아이디" class="클래스경로" >

      <property name ="프로퍼티이름" >

      <ref bean="다른 bean의 아이디"/>

      </property>

</bean>

 

반응형

'Study > spring' 카테고리의 다른 글

spring-6  (0) 2020.10.26
spring-5  (0) 2020.10.23
spring-4  (0) 2020.10.23
spring-3  (0) 2020.10.23
spring-2  (0) 2020.10.22

+ Recent posts