인프런 스프링 프레임워크 강의
1강
1-1 : 스프링 프레임워크
스프링 프레임워크는 주요기능으로 DI, AOP, MVC, JDBC 등을 제공한다. 방법론
프레임워크 : 어떤 기능을 구현하기 위한 틀
스프링은 모듈로 구성되어 있다.
1-2: 스프링 프레임워크 모듈
프레임워크에서 제공하고 있는 모듈(라이브러리)
- spring-core : 스프링의 핵심인 DI(Dependency Injection)와 IoC(Inversion of Control)를 제공
- spring-aop : 관점지향프로그램 공통된부분을 붙였다뗏다 가능
- spring-jdbc : 데이터베이스를 쉽게 (적은 양의 코드) 다룰 수 있는 기능 제공
- spring-tx : 스프링에서 제공하는 트랜잭션 관련 기능 제공
- spring-webmvc : 스프링에서 제공하는 컨트롤러와 뷰를 이용한 스프링 MVC구현기능제공
스프링 프레임워크에서 제공하고 있는 모듈을 사용하려면 모듈에 대한 의존설정을 개발 프로젝트에 xml파일 등을 이용해서 개발자가 직접 하면 된다.
1-3 : 스프링 컨테이너(IoC)
스프링에서 객체를 생성하고 조립하는 컨테이너(container)로, 컨테이너를 통해 생성된 객체를 빈(bean, object)이라고 부른다.
외부에 있는 객체를 만들어서 생성자에 넣어준 것 : 컨테이너
3강
Maven : 빌드하는 틀
Maven project 생성시
Group : 전체를 감싸고 잇는 큰 plate
artifact : 하나하나의 plate (모듈이름)
dependencies : 의존
스프링 프로젝트를 생성하면 src 폴더-main폴더 안에 java폴더와 resources폴더가있다.
java 폴더 : 자바 언어를 사용하여 기능을 구현한 파일
resources 폴더 : 프로젝트를 진행하는데 도움되는 파일들
pom.xml 역할 : 외부 main repository에서 뭐가필요하다고 명시만 해놓으면 자동으로 외부에 있는 라이브러리를 개발중인 프로젝트에 삽입해줌
4강
내가 필요한 모듈을 dependency로 명시를 해주면
main repository로부터 local로(Maven dependencies 폴더)로 다운이 된다.
빌드태그 : 빌드할때 필요한 명령어
applicationContext(스프링 설정파일) : 스프링은 컨테이너 안에 객체를 다 모은다. 객체를 메모리 로딩 하긴하는데 IoC라는 스프링컨테이너 큰 그릇을 만든다. 내가 필요한 객체들을 다 생성해놓고 필요할때마다 객체들을 하나씩 빼와서 사용한다. 스프링컨테이너의 객체는 bean이라고 한다. 그 bean을 만들어주는게 applicationContext이다.
class : 현재패키지명 + class네임
applicationContext xml파일 안 빈태그에는 스키마 부분이 있다.
bean 코드를만들면 new 라는걸 생성하지 않아도 된다. 자동으로 메모리에 로딩이 됨 -> 컨테이너에
자바에서는 외부 리소스를 쓰면 반환을 해줘야한다.
예전에는 xml로 했지만, 요즘에는 annocation으로 한다.
Mainclass
package hello4;
import org.springframework.context.support.GenericXmlApplicationContext;
public class MainClass {
public static void main(String[] args) {
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext("classpath:applicationContext.xml");
TransportationWalk transportationWalk = ctx.getBean("tWalk", TransportationWalk.class);
transportationWalk.move();
ctx.close();
}
}
getbean으로 원하는 객체 끌어다가 씀
TransportationWalk
package hello4;
public class TransportationWalk {
public void move() {
System.out.println("도보로 이동 합니다.");
}
}
pom.xml
<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>spring4</groupId>
<artifactId>hello4</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>yes</name>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
6강
Dependency injection (의존성) : oop 프로그램에서 방법론적인 것이다.
7강
- 생성자를 이용한 의존 객체 주입
public StudentRegisterService(StudentDao studentDao) {
this.stuentDao = studentDao;
}
StudentRegisterSerivce는 생성자이고, 생성할 때 StudentDao라는 객체를 주입받고 싶다.
StudentDao에 studentDao를 매개변수로 받고, 받은것을 this.studentDao 필드에 할당해준다.
생성자를 이용한 studentDao 객체주입
객체를 생성할때 생성자에다 주입할 때 constructor-arg 라는 태그를 이용한다. studentDao를 레퍼런스(참조하라) -> 속성값으로 studentDao 객체가 주입된다.
-
setter를 이용한 의존객체 주입
property 태그 이용
-
List타입 의존 객체 주입
property와 list 태그 사용
- Map타입 객체 주입
property, map, entry, key, value 태그사용
key와 value는 같이다님
8강
하나의 xml(스프링 설정파일)에 너무많은내용이 담기면 안좋음
applicationContext.xml
->
appCtx1.xml
appCtx2.xml
appCtx3.xml
세가지 파일로 나눠서 저장, 보통 기능별로
1번파일 : Dao와 서비스 객체들
2번파일 : 데이터베이스 관련 객체들
3번파일 : information service
GenericXmlApplicationContext ctx =
new GenericXmlApplicationContext("classpath:applicationContext.xml");
xml 하나 가져오는 코드
String[] appCtxs = {"classpath:appCtx1.xml", "classpath:appCtx2.xml", "classpath:appCtx3.xml"};
GenericXmlApplicationContext ctx =
new GenericXmlApplicationContext(appCtxs);
1,2,3,번 xml파일 가져오는 코드 : 개발자들이 선호함
<import resource="classpath:appCtx2.xml"/>
<import resource="classpath:appCtx3.xml"/>
-----------------------------------------------------
GenericXmlApplicationContext ctx =
new GenericXmlApplicationContext("classpath:appCtxImport.xml");
xml 파일 하나에 다른 xml파일을 연결 할때 쓰는 코드
불러올때 하나만 불러와도됨
main method가 많은 프로젝트는 실행할때 어떤 main method로 실행할지 물어보는 창이 뜬다.
- new ClassName(); 처럼 new키워드를 이용해서 객체를 생성하면
new ClassName();new ClassName();new ClassName(); 이럴때는 메모리에 세번 서로 다른 객체를 생성한다. - 스프링은 객체를 스프링 컨테이너에 생성해놓고 getbean으로 호출만 해서 쓰기 때문에 getBean("a") 이 두개 있을때 둘다 같은 a를 가리킨다. -> 싱글톤 (default 설정)
prototype : 해당 bean 구문 안에 scope="prototype" 적으면 그것만 호출할때마다 새로운 객체가 생성이 된다.
9강
@Autowired : 주입하려고 하는 객체의 타입이 일치하는 객체를 자동으로 주입, Property, 생성자, 메소드 다쓸수있음
@Resource : 생성자에는 못씀
스프링에서는 Ctrl+/ (//) 주석이 안된다
<.!-- 내용 --> 만됨
데이터베이스를 안배워서 Map 데이터 타입의 자료구조 이용
생성자에 @autowired 하면 상관없는데 property(class)나 메소드에 @autowired할때에는 생성자에 대한 default 넣어줘야함, @Resource도 마찬가지
@Autowired
private WordDao wordDao;
public WordRegisterService() {
}
public WordRegisterService(WordDao wordDao) {
this.wordDao = wordDao;
}
annotation의 일부 기능은 현재 작동하지 않으므로 pom.xml파일에 dependency를 추가해줘야한다.
https://devbible.tistory.com/461
Maven
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
10강
동일한 객체가 2개 이상인 경우 스프링 컨테이너는 자동 주입 대상 객체를 판단하지 못해서 Exception을 발생시킨다.
우선순위 설정
@inject
11강
컨테이너와 빈의 생성시점은 동일하다.
GenericXmlApplicationContext에서 생성
ctx.close(); 일때 컨테이너 소멸(메모리에서 날라감)
빈과 컨테이너의 생명주기는 같다.
Interface : 특정한작업이 명시만되어있고 구현되어있지않은 추상적인개념
Dao파일이 데이터베이스와 관계를 이어줌
빈 생성될때, 소멸될때 특정 행동 하고 싶으면
package com.brms.book.service;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import com.brms.book.Book;
import com.brms.book.dao.BookDao;
public class BookRegisterService implements InitializingBean, DisposableBean{
@Autowired
private BookDao bookDao;
public BookRegisterService() { }
public void register(Book book) {
bookDao.insert(book);
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("bean 객체 생성");
}
@Override
public void destroy() throws Exception {
System.out.println("bean 객체 소멸");
}
}
클래스 옆에 implements InitializingBean, DisposableBean을 적으면 밑에 오버라이드 구문이 생긴다.
여기다가 적으면 된다. -> 인터페이스를 이용한 방법
속성을 이용하고싶으면 init method
public void initMethod() {
System.out.println(" -- initMethod() --");
}
public void destroyMethod() {
System.out.println(" -- destroyMethod() --");
}
11강
//<bean id="studentDao" class="ems.member.dao.StudentDao" ></bean>
public StudentDao studentDao() {
return new StudentDao();
//<bean id="studentDao" class="ems.member.dao.StudentDao" ></bean>
public StudentDao studentDao() {
return new StudentDao();
studentDao가 ID 값, StudentDao가 데이터 타입
12-1강
applicationContext에
property가 나올 경우
<bean id="dataBaseConnectionInfoDev" class="ems.member.DataBaseConnectionInfo">
<property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:xe" />
<property name="userId" value="scott" />
<property name="userPw" value="tiger" />
</bean>
@Bean
public DataBaseConnectionInfo dataBaseConnectionInfoDev() {
DataBaseConnectionInfo inforDev = new DataBaseConnectionInfo();
inforDev.setJdbcUrl("jdbc:oracle:thin:@localhost:1521:xe");
inforDev.setUserId("scott");
inforDev.setUserPw("tiger");
return inforDev;
}
list가 나올때는 ArrayList사용
<property name="developers">
<list>
<value>Cheney.</value>
<value>Eloy.</value>
<value>Jasper.</value>
<value>Dillon.</value>
<value>Kian.</value>
</list>
</property>
ArrayList<String> developers = new ArrayList<String>();
developers.add("Cheney");
developers.add("Eloy");
developers.add("Jasper");
developers.add("Dillon");
developers.add("Kian");
info.setDevelopers(developers);
Map나오면 HashMap
<property name="administrators">
<map>
<entry>
<key>
<value>Cheney</value>
</key>
<value>[email protected]</value>
</entry>
<entry>
<key>
<value>Jasper</value>
</key>
<value>[email protected]</value>
</entry>
</map>
</property>
Map<String, String> administrators = new HashMap<String, String>();
administrators.put("Cheney", "[email protected]");
administrators.put("Jasper", "[email protected]");
info.setAdministrators(administrators);
12-2강
xml 파일 나누듯이 자바파일도 그냥 기능별로 나누면 됨
13강
웹 프로그래밍 설계 모델
두가지가 있다.
스프링MVC
한 파일에다가 다넣음
만들기는편한데 유지보수가 힘듦
기능별로 나눠놔서 편함
MVC사용
유지보수 편함 모델1보다 많이씀
이 그림 중요
- HandlerMapping이 적합한 controller 찾아줌
- HandlerAdapter가 하나의 컨트롤 안에 있는 여러개 메소드중에 가장적합한 메소드 찾아줌
서블을 web.xml에서 매핑을 하면 자동으로 만들어지고 이때 init-param에서 서블릿context도 써놓으면 dispatcherservlet이 실행될때 스프링 컨테이너도 같이 생성이 된다.
스프링컨테이너 생성한다고 안써놔도 자동으로 생성됨
개발자가구현해야되는것 : Controller(Service, Dao, DB) -> 백엔드, View -> 프론트엔드
15강
com, bs, lec14 폴더가 package
web.xml안에 dispachersuvlet을 suvlet으로 등록하고, 이때 초기 파라미터로 servlet-context를 등록할수있다.
pom.xml->메이븐 설정파일
ViewResolver->View 기능을 InternalResourceViewResolver가한다.
http://localhost:8090/pjt14/로 서버 구동하면
Homecontroller.java가 받는다(/ value로 모든 요청 다받음) -> home.jsp가 실행(서버시간출력)
http://localhost:8090/pjt14/login 들어가면 login.java가 실행되고 login.jsp(뷰)에서 데이터끌어오게됨
16강
key is ${key}
17강
key is ${key}
회원 관리 웹 어플리케이션
18강
스프링 프레임워크는 설정이 반이다
DAO = Data Access Object
public String memLogin(Model model, HttpServletRequest request)
String memId = request.getParameter("memId");
String memPw = request.getParameter("memPw");
변경 가능
public String memLogin(Model model, @RequestParam("memId") String memId,
@RequestParam("memPw") String memPw)
@RequestParam(value = "memPw", required=true, defaultValue = "1234") String memPw)
required가 true면 값이 넘어오지않았을때 안됨
false면 값이 넘어오지 않아도됨
defaultValue는 값이 넘어오지 않았을때 사용되는 디폴트값
커맨드객체를 사용하면 코드의 양을 엄청 줄일 수 있다.
@RequestMapping(value="/memJoin", method=RequestMethod.POST)
public String memJoin(Member member) {
service.memberRegister(member.getMemId(), member.getMemPw(), member.getMemMail(),
member.getMemPhone1(), member.getMemPhone2(), member.getMemPhone3());
19강
19강 프로젝트가 완성된자료
@ModelAttribute("serverTime")
public String getServerTime(Locale locale) {
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
return dateFormat.format(date);
}
이런식으로 상단에 @ModelAttribute가 있으면 다른 메소드가 실행될 때 같이 실행된다.
즉, @ModelAttribute는 두가지 기능이 있다.
1. 닉네임 정함
2. 다른 메소드를 호출했을때 항상 같이 호출된다.
Model vs ModelAndView
mode은 데이터만 전달, modelandview는 데이터와 뷰의 이름을 같이 전달
20강
세션과 쿠키는 클라이언트와 서버의 연결을 유지
웹서비스는 http 프로토콜을 사용한다.
세션은 서버에서 연결정보 관리, 쿠키는 클라이언트에서 연결정보 관리
세션 이용할때 HttpServletRequest 이용해도되고 HttpSession 이용해도되는데, HttpSession이 더 간단하다.
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String memLogin(Member member, HttpServletRequest request) {
Member mem = service.memberSearch(member);
HttpSession session = request.getSession();
session.setAttribute("member", mem);
return "/member/loginOk";
}
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String memLogin(Member member, HttpSession session) {
Member mem = service.memberSearch(member);
session.setAttribute("member", mem);
return "/member/loginOk";
}
세션을 생성한다 = 세선에 속성을 추가한다
세션을 제거한다 = 세션에서 속성을 제거한다
쿠키 생성할때에는 new를 쓴다.
@RequestMapping("/main")
public String mallMain(Mall mall, HttpServletResponse response){
Cookie genderCookie = new Cookie("gender", mall.getGender());
if(mall.isCookieDel()) {
genderCookie.setMaxAge(0);
mall.setGender(null);
} else {
genderCookie.setMaxAge(60*60*24*30);
}
response.addCookie(genderCookie);
return "/mall/main";
}
생성된 쿠키를 사용할 때에는 @CookieValue를 사용한다.
@RequestMapping("/index")
public String mallIndex(Mall mall,
@CookieValue(value="gender", required=false) Cookie genderCookie,
HttpServletRequest request) {
if(genderCookie != null)
mall.setGender(genderCookie.getValue());
return "/mall/index";
}
21강
예를들어 로그인이 되어있지 않은 상태에서 회원정보 수정을 누르면 메인페이지로 돌아가야 한다. 이때 리다이렉트를 사용해서 세션이 생성되어있지않는다면 메인페이지로 돌아가게 한다. 그런데 리다이렉트를 많이 사용해야 할 때에는 번거로움을 제거하기 위해 인터셉터 기능을 사용한다. 보통 컨트롤러가 작동하기 전에 실행되는 프리핸들을 많이 사용한다.
servletcontext파일
<interceptors>
<interceptor>
<mapping path="/member/modifyForm"/>
<mapping path="/member/removeForm"/>
<!--
<mapping path="/member/**"/>
<exclude-mapping path="/member/joinForm"/>
<exclude-mapping path="/member/join"/>
<exclude-mapping path="/member/loginForm"/>
<exclude-mapping path="/member/login"/>
<exclude-mapping path="/member/logout"/>
<exclude-mapping path="/member/modify"/>
<exclude-mapping path="/member/remove"/>
-->
<beans:bean class="com.bs.lec21.member.MemberLoginInterceptor"/>
</interceptor>
</interceptors>
22강
database는 oracle꺼 다운받았다.
sql developer도 받음
23강
JDBC :
드라이버 로딩 -> DB 연결 -> SQL 작성 및 전송 -> 자원해제
memberdao.java
public class MemberDao implements IMemberDao {
private String driver = "oracle.jdbc.driver.OracleDriver"; // 오라클 드라이버 로딩
private String url = "jdbc:oracle:thin:@localhost:1521:xe";
private String userid = "scott";
private String userpw = "tiger";
private Connection conn = null;
private PreparedStatement pstmt = null;
private ResultSet rs = null;
private HashMap<String, Member> dbMap;
public MemberDao() {
//dbMap = new HashMap<String, Member>();
}
@Override
public int memberInsert(Member member) {
int result = 0;
try {
Class.forName(driver);
conn = DriverManager.getConnection(url, userid, userpw); //드라이버매니저로부터 커넥션 연결 객체 가져옴(브릿지역할)
String sql = "INSERT INTO member (memId, memPW, memMail) values (?,?,?)"; //쿼리를 날림
pstmt.setString(1, member.getMemId());
pstmt.setString(2, member.getMemPw());
pstmt.setString(3, member.getMemMail());
result = pstmt.executeUpdate(); // 성공한 횟수
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if(pstmt !=null) pstmt.close();
if(conn != null) conn.close();
} catch (SQLException e2) {
e.printStackTrace();
}
}
dbMap.put(member.getMemId(), member);
return result;
}
memberservice.java
public void memberRegister(Member member) {
int result = dao.memberInsert(member);
if(result == 0) {
System.out.println("Join Fail!!");
} else {
System.out.println("Join Success");
}
//printMembers(dao.memberInsert(member));
}
24강
JDBC의 단점: 매번 드라이버로드, 커넥션객체, 질의응답, 자원해제 매번 하는게 번거로워서 스프링에서 jdbc템플릿을 제공해줌
개발자는 쿼리문 작성만 하면 됨. jdbc템플릿에 한번 설정해두면 나머지는 자동으로 다 처리함
DataSource 클래스: 데이터베이스연결과 관련된 정보를 가지고 있는 DataSource 는 스프링또는 c3p0 에 제공하는 클래스를 이용할 수 있다
스프링에서 제공
org.springframework.jdbc.datasource.DriverManagerDataSource
c3p0 제공
com.mchange.v2.c3p0.DriverManagerDataSource
update에서 세가지 방법: PreparedStatementSetter(), PreparedStatementCreator()
쿼리 날리는 네가지 방법: PreparedStatementSetter(), PreparedStatementCreator(), new RowMapper(), members = template.query(sql, new Object[]{member.getMemId(), member.getMemPw()}, new RowMapper()
25강
jdbc: 자바를 통해서 데이터베이스와 통신하는 방법 제공
커넥션풀 : 동접자 수가 많을때 부하를 줄 수도 있어서 클라이언트가 요청하지 않아도 데이터베이스 커넥션을 미리 만들어두고 요청이들어오면 제공함, 예외처리를 반드시 해야한다.
datasource: 데이터베이스와 연결된 정보들(드라이버, 계쩡, 비밀번호 등)의 정보를 가지고있는 객체
Author And Source
이 문제에 관하여(인프런 스프링 프레임워크 강의), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@chss3339/인프런-스프링-프레임워크-강의저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)