럭키 77
오늘도 역시 이어서 spring 기본 문법을 배웠다. 사실 꼭 필수적인 부분인데 문법만 배우는건 쉽게 지루해진다..
그래도 정신차리고 열심히 정리를 해야지
기본 개념 다시 정리
1. 스프링: 여러 클래스들을 모아서 관리해주는 컨테이너.
객체의 생성부터 객체의 소멸까지 다운다. 스프링은 이미 만들어져 있는 라이브러리이기 때문에 자바소스코딩을 할 수 없다.
스프링으로 클래스를 관리하는 방법에는 두 가지가 있다.
1) XML
2) Annotation
먼저 XML은 <bean> 태그를 이용해서 메모리를 할당해준다. id는 해당 객체를 찾을 수 있게 해주는 명칭같은 것이다.
app.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"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="movieDao" class="com.sist.main.MovieDAO"
p:sqlSessionFactory-ref="ssf"
/>
</beans>
위의 코드를 보면 DAO 클래스의 메모리 생성을 해주고 있다. app.xml 파일에서 해주고 있다.
package com.sist.main;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.*;
public class MainClass {
public static void main(String[] args) {
String[] xml={"datasource.xml", "muisc_app.xml", "movie_app.xml"};
ApplicationContext app=
new ClassPathXmlApplicationContext(xml);
MusicDAO musicdao=(MusicDAO)app.getBean("musicDao");
MovieDAO moviedao=(MovieDAO)app.getBean("movieDao");
// 스프링에서 생성된 객체를 얻어오면 => 객체에서 필요한 메소드 호출
List<MovieVO> mList=moviedao.movieListData();
List<MusicVO> nList=musicdao.musicAllData();
}
}
그리고 MainClass에서 이렇게 메모리를 생성한 객체를 getBean을 통해서 얻어오고, 객체에서 필요한 메소드를 호출할 수 있게 된다.
2) Annotation
어노테이션으로 클래스 메모리를 할당하는 방법도 있다. 사용방법은 사용할 클래스 위에 @(Annotaion)을 올려주는 것이다.
<?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"
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">
<context:component-scan base-package="com.sist.main2"/>
<!-- 패키지 단위로 메모리 할당 -->
</beans>
어노테이션을 사용한 패키지의 app.xml 파일
위의 xml을 이용한 방법과는 다르게, 클래스 단위가 아닌 패키지 단위로 메모리를 할당한다.
package com.sist.main2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
@Component("mc")
public class MainClass {
// 스프링에서 같은 클래스명을 가지고 있는 저장된 객체주소를 자동으로 찾아서 대입 (자동주입)
// 스프링에서 Sawon 객체를 자동으로 찾아주는 것
@Autowired
private Sawon sa;
public static void main(String[] args) {
ApplicationContext app=
new ClassPathXmlApplicationContext("app2.xml");
MainClass m=(MainClass)app.getBean("mc");
m.sa.print();
}
}
MainClass 맨 위에 올려준 저 @Component 어노테이션으로 클래스 메모리를 할당해줄 수 있다.
그리고 Sawon 클래스 역시 만들어 뒀기 때문에, @Autowired를 통해서 Sawon 클래스를 자동으로 찾아와서 값을 대입해줄 수 있다.
package com.sist.main2;
import org.springframework.stereotype.Component;
/*
* <bean id="ds" class="com.sist.main.Sawon">
* => 필요한 데이터를 첨부 (DI)
* 어노테이션은 DI를 할 수 없다/ 메모리만 할당
*/
@Component("sa")
public class Sawon {
private String name;
private String sex;
public Sawon ()
{
name="황런쥔";
sex="공주";
}
public void print()
{
System.out.println("이름:"+name);
System.out.println("성별:"+sex);
}
}
이게 Sawon 클래스이다. 이렇게 @Component에 id "sa"를 주면 다른 클래스에서 아이디를 주고 값을 주입해줄 수 있다.
그러면 어노테이션의 종류에 대해서 간단히 정리해보겠다.
1. @Component : 일반클래스에 사용
2. @Repository : 저장소 (DAO)에 사용
3. @Service : 통합된 저장소 (BI), DAO를 통합할 경우에 사용
4. @Controller : Model 클래스, 파일명을 전송할때 사용 (사이트 이동시, 주로 웹에서 사용함)
5. @RestController : 화면 이동이 아니라 필요한 문자열 전송할때 사용 ex) Ajax, VueJS, React 등등
bean에서는 id를 주고 생성된 객체를 찾아왔듯이, 어노테이션에서도 @Component("sa")/ 괄호안에 있는 값으로 객체를 찾아 올 수 있다.
스프링에서 객체를 생성하기 전에, 개발자는 반드시 필요한 데이터를 설정(주입)해주어야 한다.
이 과정을 DI라고 부른다.
그리고 이 과정이 Map방식으로 진행이 된다.
id를 주면 주소값(ref)를 읽어오는 방식이다. 즉, id==key | 메모리주소==value 이다.
스프링을 사용할때 가장 큰 장점은, 클래스들을 모아주지만 각자 독립적으로 움직이기 때문에 결합성이 낮지만 응집력이 높은 프로그램을 만들 수 있기 때문이다.
여기에 이제 오라클을 연결해주는 라이브러리로 Mybatis를 사용하면 좀더 간략하게 프로그램을 만들 수 있다는 장점을 갖게 된다.
오늘 수업을 들으면서 필기를 한 부분.
config.xml -> music-mapper.xml -> app.xml -> MusicDAO -> MainClass
이 순서대로 파일을 만들고 작성해줬다.
db를 연결해주는 config.xml 파일을 먼저보면,
<?xml version="1.0" encoding="UTF-8"?>
<!-- mapper전체, VO 전체를 모아준다 -->
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- VO를 모아서 관리 -->
<typeAliases>
<typeAlias type="com.sist.main.MusicVO" alias="MusicVO"/>
</typeAliases>
<!-- SQL문장을 모아서 관리 -->
<mappers>
<mapper resource="com/sist/main/music-mapper.xml"/>
</mappers>
</configuration>
VO를 모아주고, SQL문장을 모아서 관리할 mapper class의 주소를 저장한다. 여기에 저장을 해두면 알아서 mapper.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="com.sist.main.music-mapper">
<!-- 프로그램에서 사용하는 SQL문장을 저장
CURD => Create , Update , Read , Delete
======(Insert) ====(Select)
1) Insert => <insert>
2) Update => <update>
3) Select => <select>
4) Delete => <delete>
==> 1. id부여(Map에서 저장되는 키명 : 중복이 없이 만든다)
2. 결과값을 받는 경우 : resultType(SELECT문장에만 존재)
결과값이 1개인 경우 => 일반데이터형
SELECT pwd FROM table_name ==> String
SELECT COUNT(*) FROM table_name ==> int
결과값이 2개인 경우 => VO,Map
VO로 먼저 처리 (VO에 없는 변수는 Map)
SELECT MAX(hit),Min(hit) FROM table_name
======== ========= Map => 스칼라 서브쿼리
SELECT no,title FROM table_name
========
VO
3. 데이터베이스에 값을 추가 (?) : parameterType
SELECT * FROM table_name
WHERE no=? => ?대신 #{no} => getNo()
=> 동적 퀴리 <if> : 다중 검색 in(<forEach> , <where>)
-->
<!-- 데이터 읽기 : 페이지 나누기 -->
<!-- id의 시작은 알파벳으로 한다 , 대소문자 구분 -->
<!-- start , end
데이터 두개이상 => VO,Map
Map map=new HashMap();
map.put("start",1)
map.put("end",10)
#{start} => map에서 start는 키명
#{end} => map에서 end는 키명
-->
<select id="musicListData" resultType="MusicVO" parameterType="hashmap">
SELECT no,title,singer,album,num
FROM (SELECT no,title,singer,album,rownum as num
FROM (SELECT no,title,singer,album
FROM genie_music ORDER BY no ASC))
WHERE num BETWEEN #{start} AND #{end}
</select>
<!-- 총페이지 구하기 -->
<select id="musicTotalPage" resultType="int">
SELECT CEIL(COUNT(*)/10.0) FROM genie_music
</select>
<select id="musicCount" resultType="int">
SELECT COUNT(*) FROM genie_music
</select>
<!-- 찾기
1) 제목 ==> title LIKE
2) 가수명 ==> singer LIKE
#{} => 일반데이터
${} => table_name,column명을 설정
-->
<select id="musicFindData" resultType="MusicVO" parameterType="hashmap">
SELECT no,title,singer,album
FROM genie_music
WHERE ${column} LIKE '%'||#{finddata}||'%'
</select>
<!-- 상세보기 -->
<select id="musicDetailData" resultType="MusicVO" parameterType="int">
SELECT * FROM genie_music
WHERE no=#{no}
</select>
</mapper>
수업시간 예제로 만든 music-mapper.xml 파일
여기에 사용할 SQL문장을 적어준다. 어제 정리해둔 것 처럼 resultType, parameterType을 잘 생각해서 지정해둔다.
<?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:c="http://www.springframework.org/schema/c"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
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/util http://www.springframework.org/schema/util/spring-util-4.3.xsd">
<!-- 오라클 정보를 모아서 마이바티스로 전송 -->
<util:properties id="db" location="classpath:db.properties"/>
<bean id="ds" class="org.apache.commons.dbcp.BasicDataSource"
p:driverClassName="#{db['driver']}"
p:url="#{db['url']}"
p:username="#{db['username']}"
p:password="#{db['password']}"
/>
<!-- MyBatis로 전송 -->
<bean id="ssf" class="org.mybatis.spring.SqlSessionFactoryBean"
p:dataSource-ref="ds"
p:configLocation="classpath:config.xml"
/>
<!-- 사용자 정의 DAO에 전송 -->
<bean id="dao" class="com.sist.main.MusicDAO"
p:sqlSessionFactory-ref="ssf"
/>
</beans>
그리고 메모리를 할당할 클래스의 정보를 모아주는 app.xml 파일
오라클의 정보를 모아주는 클래스, MyBatis로 전송하는 클래스, 사용자 DAO에 전송할 클래스를 하나로 모아준다.
package com.sist.main;
import org.mybatis.spring.support.SqlSessionDaoSupport;
/*
* => SqlSessionDaoSupport
* 데이터 베이스 정보 (DataSource)
* SqlSessionFactory : getConnection, disConnection
* =================
* SqlSession => sql문장 전송, 결과값을 받는 역할
*/
import java.util.*;
public class MusicDAO extends SqlSessionDaoSupport{
public List<MusicVO> musicListData(Map map)
{
return getSqlSession().selectList("musicListData", map);
}
public int musicTotalPage()
{
return getSqlSession().selectOne("musicTotalPage");
}
// 총갯수 읽기
public int musicCount()
{
return getSqlSession().selectOne("musicCount");
}
public MusicVO musicDetailData(int no)
{
return getSqlSession().selectOne("musicDetailData", no);
}
public List<MusicVO> musicFindData(Map map)
{
return getSqlSession().selectList("musicFindData", map);
}
}
그리고 DAO 파일에서 메소드들을 실제로 만들어 준다. 그리고 MainClass로 가면
ApplicationContext app=
new ClassPathXmlApplicationContext("app.xml");
// 스프링에 저장된 DAO를 가지고 온다
MusicDAO dao=(MusicDAO)app.getBean("dao");
// 사용
int totalpage=dao.musicTotalPage();
Scanner scan=new Scanner(System.in);
System.out.print("페이지 입력:(1~"+totalpage+")=>");
int curpage=scan.nextInt();
Map map=new HashMap();
int rowSize=10;
int start=(rowSize*curpage)-(rowSize-1);
int end=(rowSize*curpage);
// WHERE num BETWEEN #{start} AND #{end}
map.put("start", start);
map.put("end", end);
// 결과값 받기
List<MusicVO> list=dao.musicListData(map);
이렇게 스프링에 저장한 dao 클래스를 가지고와서 메소드를 사용해서 원하는 결과값을 확인해 볼 수 있다.
그리고 @Autowired 사용법
자동으로 메모리를 할당해준 클래스를 찾아와 주는 것인데, 만약에 같은 @Component로 메모리를 할당해준 클래스가 여러개였다면
package com.sist.main3;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
@Component
public class MainClass {
@Autowired
//@Qualifier("mySQL")
//@Resource(name="mySQL")
DB db;
public static void main(String[] args) {
ApplicationContext app=
new ClassPathXmlApplicationContext("app3.xml");
MainClass mc=(MainClass)app.getBean("mainClass");
mc.db.select();
mc.db.insert();
mc.db.update();
mc.db.delete();
}
}
위와 같은 경우 오류가 나는 코드를 만날 수 있다.
오류 메세지를 보면 매칭되는 bean이 한개가 아니라 2개이기 때문에 실행할 수 없다고 나온다.
인터페이스 파일인 DB에 아래와 같이 4개의 메소드가 있는데,
package com.sist.main3;
public interface DB {
public void select();
public void insert();
public void delete();
public void update();
}
이것을 상속받은 클래스가 Oracle, MySQL 두개 이기 때문이다.
이런 경우에 @Autowired를 사용해도 자동으로 클래스 정보를 읽어올 수 없다.
@Autowired
@Qualifier("mySQL")
DB db;
그래서 이렇게 클래스 정보를 읽어와야 딱 지정한 정보를 읽어올 수 있게 된다.
그리고 앞으로 다루게될 웹을 연결하는 프로젝트
MVC 구조
이것만 봐도 벌써 좀 복잡하고 머리속이 아찔해진다. (그정돈 아님)
일단 그냥 자바로만 해본 것과는 다른 점이 WEB-INF 폴더 아래에 config.xml 파일과 applicationContext.xml 파일을 저장한다는 점이다.
사실 아직 엄청 제대로 웹 연동을 배운것은 아니기 때문에 구조정도만 잘 이해하고 있어도 성공일것 같다.
한가지 추가된 것은 web.xml 파일에 dispatcherServlet을 등록해야한다는것, controller와 연동에 필요한 모델 클래스들이 필요하다는 것이 있다.
package com.sist.main;
// Model => Controller
/*
* DispatcherServlet : Front Controller => 요청 제어
* Model : Controller = 요청처리한 결과를 제어
*/
import java.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import com.sist.dao.*;
public class MusicController {
@Autowired
private MusicDAO dao;
@RequestMapping("music/list.do")
public String music_list(Model model)
{
List<MusicVO> list=dao.musicAllData();
model.addAttribute("list", list); // => JSP로 넘어갈때 변환 request.setAttribute()
// Model => JSP로 데이터 전송하는 역할
return "music/list";
}
}
일단 오늘은 여기까지만 정리하고
내일 어차피 더 제대로 웹 연동을 배우게 되기 때문에 더 배우고 나서 다시 정리해보겠다.
'programming > Gukbi' 카테고리의 다른 글
국비 교육 79일차 - spring project (cookie사용) (0) | 2021.04.19 |
---|---|
국비 교육 78일차 - spring mvc 게시판 만들기, mvc 프로젝트 셋팅 (0) | 2021.04.18 |
국비 교육 76일차 - spring DI, MyBatis (0) | 2021.04.14 |
국비 교육 75일차 - Constructor, Annotation, Interface 복습 (0) | 2021.04.13 |
국비 교육 75일차 - spring (Container, DI, DB연동) (0) | 2021.04.13 |