@RequestParam 

▶ @RequestParam (required = true)  // 필수입력이지만 값 입력x 시 400대(Client) Error

▶ @RequestParam (required = false, defaultValue="url에 값이 없을때 대입시킬 기본값")

    //defaultValue 주지 않으면 500대(Server) Error

[EX]

public String main(HttpServletRequest request){  }


public String main2(@RequestParam(name="year", 
                                                        required=false)

== public String main2(String year) {  }

public String main3(@RequestParam(name="year", required=true) String year)
  == public String main3(@RequestParam String year) {   }



public String main5(@RequestParam(required=false, defaultValue="1") String year) {  } 


[RequestMapping 대신 Get/PostMapping사용] 

      ex) 경로- "/mapping/examp" (메소드로 구분)

▶@RequestMapping((공통경로)"/mapping") + GetMapping("/examp") / PostMapping("/examp")

 

- @GetMapping 

== @RequestMapping(value="경로", method=RequestMethod.GET)

== <servlet-context.xml>파일에 <view-contorller path="경로" view-name="jsp파일명"/>추가  (GET만 허용)

 

- @PostMapping("경로")  

== @RequestMapping(value="경로", method=RequestMethod.POST)

 

 @ModelAttribute 

 : 적용대상을 Model의 속성으로 자동 추가해주는 애너테이션, 반환타입 or 컨트롤러 메서드의 매개변수에 적용가능

 > 호출, 저장이 따로 필요 없음

 

[EX]

@Controller
public class 클래스{

    public String main(@ModelAttribute("myDate") MyDate date, Model m) { 
      == public String main(@ModelAttribute MyDate date, Model m) { 

      == public String main(MyDate date, Model m) {  //참조형(MyDate date)은 @ModelAttribute 생략가능

      // 1. 유효성 검사 
        if (!isValid(date))   return "yoilError";
      // 2. 처리
        char yoil = getYoil(date);

      // 3. Model에 작업한 결과를 저장할 필요 없음  View로 자동 전달됨.

      // 4. 작업 결과를 보여줄 뷰의 이름을 반환  
           return "yoil";

    }

}

> 컨트롤러 매개변수가 기본형,string일때 : @RequestParam생략된 것
> 컨트롤러 매개변수가 참조형일때 : @ModelAttribute 생략된 것

 redirect 

[in JSP]

 300번대(응답헤더)응답시 자동으로 헤더의 location으로 재요청(GET) / 요청과 응답이 2번

[in Spring]

 DispatcherServlet에 요청> Controller의 메소드 호출 > Controller가 리턴값(redirect:경로) 전달 > DispatcherServlet가 RedirectView에 전달 > 응답 

 

 forward 

[in JSP]

 잘못된 경로로 혹은 일부만 처리할 수 있는 파일(1jsp)에 요청시 가능한 처리하고 다른 파일(2jsp)로 요청전달

> 응답 > 1jsp가 2jsp에 request를 Model(request객체)에 담아서 전달 / 1jsp = Controller역할, 2jsp = View역할 (MVC패턴)

[in Spring]

 DispatcherServlet에 요청> Controller의 메소드 호출 > Controller가 리턴값(forward:경로")을 DispatcherServlet에게 반환 > DispatcherServlet가 InternalResourceViewResolver에게 받은 문자열 전달 > 해석 후 다시 서블릿에 반환 > JstlV iew에 경로를 전달 > Jsp파일에 Model을 전달 > Jsp파일이 응답

 

 Cookie 

: 이름과 값의 쌍으로 구성된 정보로 아스키 문자만 가능

: 서버에서 생성/ 브라우저에 저장/ 유효기간 이후 자동삭제

: 서버에 요청시 domain, path(하위경로포함)일치시 전송(응답헤더: Set-Cookie: id=id값; Max-Age=86400)

 

* 생성

Cookie cookie = new Cookie("id","id값"); //쿠키생성
cookie.setMaxAge("60*60*24"); //유효기간설정[sec] (=24시간)
response.addCookie(cookie); //응답에 쿠키 추가

개발자 도구에서 생성 > [Application] [Cookies] 탭에서 name, value값 입력

쿠키 존재시 login form에 자동으로 아이디 기억 체크박스 체크하기 > ${empty cookie.id.value ? " " : "checked"}

 

* 삭제 ( =유효기간이 0)

Cookie cookie = new Cookie("id",""); //동일한 이름 쿠키생성
cookie.setMaxAge(0); //유효기간설정[sec] (=0 =삭제)
response.addCookie(cookie); //응답에 쿠키 추가

* 읽기

Cookie[] cookie = request.getCookies(); //read, 존재x시 null
for(Cookie cookie:cookies){
	String name = cookie.getName(); // id
    String value = cookie.getValue(); // id값
	System.out.println(name, value);
}

 Session 

: 서로 관련된 독립된 요청들을 쿠키를 이용하여 하나로 묶은 것으로 쿠키가 브라우저에 저장되므로, 브라우저마다 개별 저장소(Session)를 서버에서 제공 > 쿠키는 브라우저에, 세션은 서버에 저장

 


  Spring DI(Dependency Injection)  

** DI 의존성주입 : 사용할 객체를 외부에서 주입(라이브러리의 매개로) 받는것 

 

[in Java] Beans : 재사용 가능한 컴포넌트, 상태(iv),. 게터&세터, no-args constructor

[in Servlet & JSP] Bean : (mvc의)Model, EL, Scope, JSP container가 bean을 관리

[in Spring] Bean

: 복잡한 EJB의 규칙을 심플하게 만듬 (POJO), Spring container가 관리하는 객체 - 단순, 독립적

<.xml> bean 정의됨

→ spring container에서 읽어드리고 클래스/객체관리, bean저장/관리(생성, 소멸, 연결(AutoWired))

 

IoC(Inversion of Conrol, 제어의 역전)

: 제어(if, for)의 flow흐름을 전통적인 방식과 다르게 뒤바꾸는 것

: 변하지 않는 코드만 라이브러리안에, 잘 변하는 코드는 사용자 코드에 작성 (= DI 의존성주입)

ex)

전통적인 방식
사용자가 라이브러리 코드를 호출
 IoC
라이브러리에서 사용자 코드를 호출
[사용자]
Car car = new Car();
car.turboDrive();

[라이브러리]
void turboDrive(){
  engine = new turboEngine();
  engine.start();
}
[사용자]
Car car = new Car();
car.drive(new turboEngine()); // 수동연결

[라이브러리]
void turboDrive(){
  engine.start();
}

 

> 변경에 유리한 코드 

** 다형성 

class SpotsCar { }
class Truck { }

SpotsCar car = new SpotsCar();

Truck car = new Truck();
class Car{}
class SpotsCar extends Car{}
class Truck extends Car{}

Car car = new SpotsCar();
Car car = new Truck();

 팩토리메서드 

Car car = getCar();

static Car getCar() { return new SpotsCar() || new Truck();}

 

 Map과 외부파일  (파일.txt의 내용만 변경하면 됨) 

public static void main(String args[]){
	// 리턴 받은 객체 해당 클래스로 형 변형
	Car car = (Car)getObj("key값");
	// 호출부분만 변경하면 용이
	클래스 객체참조변수 = (클래스)getObj("key값");
}
static Obj getObj() {
	 //Properties:(String,String) == Map:(String,obj)
	Properties p = new Properties();
    // 파일.txt > key = 패키지명.class명
	p.load(new FileReader("파일.txt");
	Class clazz = Class.forName(p.getProperty(key));
	 // 객체 생성후 반환
	return clazz.newInstance();
}

 컨테이너사용 

자동객체 등록하기 (위 코드에서 getbean 추가)

 

 @Autowired 객체 자동연결 

guava 다운로드 -  https://mvnrepository.com/artifact/com.google.guava/guava/31.1-jre

[pom.xml]

<dependencies>
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.1-jre</version>
</dependency> //추가해줌
...
</dependencies>

이후 우클> maven > reload

 

: 인스턴스변수iv, setter, 참조형 매개변수를 가진 생성자, 메서드에 적용

: 생성자(construtor)는 @Autowired 생략가능

Appcontext()에 추가

 

: 타입(value로 instance of) 검색해서 연결

: 검색된 bean이 여러개 > 참조변수와 이름이 일치하는 것 주입

 

@Component // == Component ("turboengine == bean의 id ")

class TurboEngine extends Engine{}

-------

@Component ("engine") //engine == bean의 id

class SuperEngine extends Engine{}

 

> DI대상이 변수일때

@Autowired Engine engine;  //1개가 아니면 예외발생

// SuperEngine과 이름 일치 >  주입

 

> DI대상이 배열일때

@Autowired Engine[] engines;//bean이 0~n개여도 예외발생 x

// SuperEngine과TurboEngine 모두 주입

 

 

 

 

 

 

 @Resource (name=" bean의 id") 

: 이름(key값=name)으로 bean 검색하여 참조변수에 연결(자동주입 DI)

: 일치하는 이름(name)의 bean 없으면 예외 발생

: name생략가능> 참조변수 이름이 bean의 name이 됨

ex) 

class Car {

  @Resource(name="engine")  Engine engine; }

 

 

**setter로 객체의 값 set시

class Car {
    String color;
    int oil;
    Engine engine;
    Door[] doors;
    ..//getter, setter
 }
 
 public static void main(String[] args) {
        Car car1 = (Car) ac.getBean("car");
        Engine engine = (Engine) ac.getBean("engine");
        Door door = (Door) ac.getBean("door");

        car1.setColor("red");
        car1.setOil(100);
        car1.setDoors(new Door[]{ (Door) ac.getBean("door"), (Door)ac.getBean("door")});
        car1.setEngine(engine);
 }

setter 사용 대신 

[config.xml]의 bean으로 작성   

<bean id="car" class="com.fastcampus.ch3.Car">
        <property name="color" value="red"/>
        <property name="oil" value="100"/>
        <property name="engine" ref="engine"/>
        <property name="doors">
            <array value-type="com.fastcampus.ch3.Door">
                <ref bean="door" />
                <ref bean="door" />
            </array>
        </property>
</bean>

<bean id="engine" class="com.fastcampus.ch3.Engine"/>
<bean id="door" class="com.fastcampus.ch3.Door" scope="prototype"/>

 



[내일배움카드] [국비지원교육]

MVC

클라이언트 :  서비스 요청하는 애플리케이션(or PC)

서버: 서비스를 제공하는 애플리케이션(or PC)  > Email/ File/ Web server

WAS(Web Application server): 웹 애플리케이션을 서비스하는 서버/ 서버에 프로그램을 설치하고 웹에서 보여줌

 #Tomcat 

-Server : 서버> 서비스 > 엔진(서비스를 처리) > HOST> Context (서블릿 여러개) = 프로젝트

      주소형식 = Host명/context명/서블릿명

-설정파일

: conf/server.xml (서버설정) | conf/web.xml (모든 web app의 공통설정) | WEB-INF/web.xml (web app의  개별설정)

 

프로토콜 : 서로 간의 통신을 위한 약속, 규칙으로 주고받을 데이터에 대한 형식을 정의한 것

- HTTP(텍스트기반) 응답메시지

> 형식: 상태라인(HTTP/1.1 상태코드 상태설명) / 헤더 / 빈줄(헤더, 바디 구분) / 바디(응답내용)

#상태코드 : 1**(informational) 2**(성공) 3**(Redirect- 다른URL로 요청필요) 4**(client error) 5**(server error)

- HTTP(텍스트기반) 요청(GET/ POST) 메시지

> 형식: 요청라인 / 헤더 / 빈줄 / 바디

- GET: 리소스를 받는(Read) - 요청라인에 쿼리스트링으로 요청, 바디 없음, 보안취약, 소용량

- POST: 서버에 data(바디내용)를 전송/제공 (Write), 대용량가능 => 게시판 글쓰기, 로그인, 회원가입

 ▶개발자도구의 Network 탭에서 확인 가능

 

OOP 5대 설계원칙 - SOLID

> SRP: 단일책임 원칙 (하나의 메서드는 하나의 책임을 진다, 관심사/ (un)common /중복(입출력)코드 의 분리)

> OCP: 개방-폐쇄 원칙 

> LSP: 리스코프 치환 원칙 

> ISP: 인터페이스 분리 원칙 

> DIP: 의존성 역전 원칙 

 

ex) 요일을 계산해주는 프로그램 > MVC패턴으로 개선

 

isVaild함수 return true일때와 false일때

jsp파일내용

한글이 깨질때 : <%@ page contentType="text/html;charset=utf-8" %>

 

- Servlet  (싱글톤) 

@WebServlet  =  @Controller(메소드에 맵핑) + @RequestMapping

 > 해당 클래스는 HttpServlet 상속, 메소드HttpServletRequest request, HttpServletResponse response 필요

@WebServlet 
public class 클래스 extends HttpServlet {

   @Override
    public void 클래스(HttpServletRequest request,                 HttpServletResponse response) { }}
@Controller
public class 클래스{
    @RequestMapping
    public void main( HttpServletResponse response){ }
}

 

 

요청

> 존재x > 인스턴스 생성

> 서블릿 인스턴스 존재시

서블릿 클래스 로딩

init() 초기화

service() 호출할때마다 반복수행

 

- JSP (Java Server Pages) 

html안에 java코드가 존재하는 것, servlet과 동일 

동작) jsp작동 시 servlet으로 변환 >  servlet 클래스파일 컴파일 > servlet 인스턴스 생성

파일 저장 위치- src/main/webapp

<%! servlet의 클래스 영역 내용%>  <% servlet의메소드 내부에 존재함 %>

*기본객체 : 생성없이 사용할 수 있는 객체 (ex -request, response, pageContext, config, application, page, out 등)

 - EL (Expression Language)표현식 

    <%=값%>을 사용하지않기 위해 ${값}을 사용하는 표현식, lv(지역변수)는 사용불가, 값을 읽을 수 있음, null출력안함

[EX]

requset객체 안에 attribute 라는 Map(이름- request scope)저장 

key = name, value = silver로 저장

color 
= <%=person.getCar().getColor()%> //red
= ${person.getCar().getColor()} <br> //red
= ${person.car.color} <br>  //red

name 
= ${name} //Silver   
= ${requestScope.name} //Silver  
= <%=request.getAttribute("name")%> (EL불가) //Silver

name == "Silver" 
= ${ name eq "Silver"} // true
= ${name.equals("Silver")} // true

= ${name == "Silver" // true

name != "Silver"
= ${name != "Silver" // false
= ${name ne "Silver"}) // false


id 
= <%=request.getParameter("id")%> //null
= ${pageContext.request.getParameter("id")} //출력x
= ${param.id} <br> //출력x
Scope 기본객체
page pageContext
requst requst
session session
application application

 

- JSTL(JSP Standard Tag Lib) : <%태그%>사용하지 않기 위해 사용 <접두사:태그명 ~> 형식

 (접두사)

<c: 상단에 <%@ taglib prefix="c"  uri="http://java.sun.com/jsp/jstl/core"%> 선언한것으로 core 라이브러리를 사용

<fmt: <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> 선언한것으로 fmt 라이브러리를 사용

 

[EX]

<c:set  var="to"   value="10"/> //저장소에 저장 (key = var값, value = value값)으로 page Scope 생략한것

<c:forEach  var="i" begin="1" end="${to}">  ${i} </c:forEach> //1부터 10까지 출력

<c:set  var="arr"  value="10,20,30,40,50,60,70"/> // 배열생성

<%-- varStatus는 count와 index멤버를 가지고 있음 --%>

<c:if test="${not empty arr}">

    <c:forEach var = "elem"  items="${arr}" varStatus="status">
         status.count = ${status.count} / status.index = ${status.index}<br>
         arr[${status.index}]=${elem
    </c:forEach>
</c:if>

 

//주소창에 ?msg = 메시지 입력하면 출력됨
<c:if test="${param.msg == null}"> 메시지가 없습니다. </c:if>
 <c:if test="${param.msg != null}">
        msg = ${param.msg}   //태그를 인식하고 내용만 출력
        msg = <c:out value="${param.msg}"/>  //태그를 인식하지 않고 그대로 출력
</c:if>

 

 - Filter 

서블릿의 전처리 후처리 중복코드를 필터에 넣음

- 필터 1개
요청 > [필터] 전처리 > [필터] 서블릿 호출 
    > [서블릿] 처리 > [필터] 후처리
- 필터 2개
요청 > [필터1] 전처리 > [필터1] 필터2 호출 > [필터2] 전처리
    >[필터2] 서블릿 호출 > [서블릿] 처리 > [필터2] 후처리 > [필터1] 후처리

 

 

[내일배움카드] [국비지원교육]

 다운캐스팅 

> 업캐스팅된 클래스를 다시 원래의 타입으로 형 변환하는 것으로 하위클래스로의 형변환은 명시적으로 해야함

   묵시적) 상위클래스명 name2 = new 하위클래스명();

   명시적) 하위클래스명 name1 = (하위클래스명)name2;

** 인스턴스 형 체크 방식 : 상위클래스명 instance of 하위 클래스명 //return ture or false

 

 추상클래스 

> 구현코드 없이 메서드의 선언(반환타입, 메서드 이름, 매개변수로 구성)만 있고 구현부({ 바디 부분 })는 없는 추상 메서드를 가지고 있는 클래스로 new키워드로 인스턴스화 불가

> 상속하기 위해 만듬 (public) abstract  class 클래스명 {  }

  # 추상클래스의 추상 메서드 : 하위 클래스가 상속하여 구현

  #추상클래스 내 추상메서드 : 상속받은 하위 클래스가 구현할 메서드

  # 추상클래스 내의 구현된 메서드:  하위 클래스가 공통으로 사용하는 메서드

 

 템플릿 메서드 패턴 

> 메서드를 활용하여 코드 흐름을 정의하는 메서드 설계패턴

> 변해야 하는 부분은 추상메서드로 선언하여 하위 클래스에서 구현

 

 인터페이스 

> 모든 메서드가 추상 메서드, 모든 변수는 상수

> 클래스나 프로그램이 제공하는 기능을 선언하는 일종의 클라이언트 코드와의 약속

> 클라리언트 프로그램은 인터페이스에 선언된 메서드 명세를 보고 클래스 사용가능하며 인터페이스를 구현한 다양한 객체를 사용 (다형성)

>  jdbc(oracle, MySQL등)와 java를 connection으로 연결 > connection은 인터페이스 =  JDBC인터페이스

> 하나의 클래스가 여러 인터페이스 구현 불가

 

디폴트메서드

> 구현을 가지는 메서드, 인터페이스를 구현하는 클래스들에서 공통으로 사용할 수 있는 기본 메서드로 default 키워드를 사용하여 선언, 하위 클래스에서 재정의 가능

default 타입 메서드명(){ }

정적메서드

> 인스턴스 생성하지 않아도 인터페이스 타입으로 사용할 수 있음

static 타입 메서드명(){ }

private메서드

> 인터페이스를 구현한 하위 클래스에서 재정의 불가하며 인터페이스 내부에서만 사용, default메서드와 static메서드에서 사용

static 타입 메서드명(){ }

ex) 위 calc인터페이스에 privatt, default, static메소드 추가 후 test 실행

//private 메서드
private void myMethod(){
    System.out.println("==myMethod==");
}
private static void myStaticMethod(){
    System.out.println("==myStaticMethod==");
}

//디폴트 메서드
default void description(){
    myMethod();
    System.out.println("정수의 사칙연산 완료");
}
//정적 메서드
static int total(int[] arr){
    myStaticMethod();
    int total = 0;
    for(int num : arr){
        total += num;
    }
    return total;
}

 

<인터페이스활용 다형성 구현>

하나의 인터페이스(userInfoDao)를 여러 객체(userinfo, userinfoMySqlDao, UserInfoOracleDao)가 구현하면

클라이언트 프로그램(UserInfoClient)은 인터페이스의 메서드를 활용하여 여러 객체 구현

 

DAO (Data Access Object)

> 데이터 베이스나 외부 파일 시스템과 같은 영속성 메커니즘에 접근하여 데이터의 CRUD 처리하는 객체 or 패턴

> 고수준인 Business Logic과 저수준인 Persistence Logic을 분리하기 위해, Persistence Logic을 캡슐화 하고 도메인 레이어에 객체지향적인 인터페이스를 제공하는 객체

영구 저장소: MySQL, PostgreSQL, MongoDB 등 

출처-hudi.blog

 여러 인터페이스 구현 

> 해당 클래스는 인터페이스 타입으로 형 변환 되는 경우 해당 인터페이스의 메서드만 사용가능

> 사용할 클래스에서 디폴트 메서드 중복시 구현 클래스에서 재정의

 인터페이스 상속 

> 인터페이스 사이에도 상속을 사용할 수 있음

ex) 

<자식인터페이스.java>
interface 자식인터페이스 extends 부모인터페이스{ }
<하위클래스.java>
public class 클래스명 implements 자식인터페이스{ }

[내일배움카드], [국비지원교육]

 

<복습 문제>

 

 

 참조 자료형  - String/ Date/Student 등

클래스형으로 선언, 클래스에 따라 메모리 크기가 다름, String을 예외하고 사용시에 변수에대해 생성해야함

 § 정의 후 사용방법

< subject.java >

public class Subject { String SubName; int Score; }

 

 접근제어 지시자 

private - 동일 클래스 내에서만 접근 가능

protected - 동일 패키지내에서 or 상속관계에 있는 private를 사용하고 싶을때 사용하여 접근 가능

public - 어디서나 접근 가능

x - 같은 패키지내에서 접근 가능(다른 패키지에서 사용시 import )

 

 캡슐화 

정보은닉을 활용한 캡슐화 - 꼭필요한 정보와 기능만 외부 접근허용 (인터페이스만 제공함)

오류 최소화함

 

 this 키워드 

인스턴스 자신의 (heap)메모리를 가르키며 자신의 주소를 return / 생성자에서 또 다른 생성자를 호출할때 사용

클래스 내에서 참조변수가 가지는 주소값과 동일한 주소값을 가지는 키워드

ex) 위 Student 클래스에서  Student 생성자 생성 시 멤버변수을 입력 받음  > this.참조변수 = 매개변수;

 

#생성자의 역할: 인스턴스 초기화

클래스에 생성자가 여러개인 경우 생성자에서 다른 생성자 호출가능 (but, this() 선언 이전에 다른 statement 사용불가)

순서 : this(매개변수) 호출 > 매개변수 형식이 맞는 생성자 찾음 > 인스턴스 초기화 완료

main 함수에서 생성된 thisper과 class내 생성자에서 리턴해준(thisper2) 값과 동일 

 

 Static(정적) 변수  == 클래스 변수

> 공통으로 사용하는 변수가 필요한 경우, 여러 인스턴스가 공유하는 기준값이 필요한 경우

> 인스턴스 생성과 상관 없음, 클래스 이름으로 직접 참조

사용법 ) static 자료형 변수명;

ex) 입사자에게 사번 부여하는 프로그램

static형의 변수는 인스턴스 생성 전 클래스(Employee)명으로 접근하여 출력가능

> static 메서드내에서 인스턴스 변수 사용불가 (생성 전에도 static 변수가 사용가능하므로), 일반 메서드 내에서는 static 변수 사용가능

 

 Singleton패턴 

> 인스턴스가 한개만 생성되어야 하는 디자인 패턴으로 static 변수와 메서드를 활용해 구현가능

> 유일한 객체를 제공할때 구현

방법) class내  private 생성자  /유일한  private 인스턴스  / 인스턴스를 참조할 수 있는  public 메서드  생성

private 클래스명( ) { }

private static 클래스명 instance = new 클래스명();

public static 클래스명 getInstance( ) { return instance; }

 

 배열 

동일한 자료형의 순차적 자료구조로 인덱스로 빠른참조 가능 (인덱스 = 0~length-1)

ArrayList 클래스 사용 多

선언 = 타입[ ] 배열명 = new 타입[크기]    OR    타입 배열명[ ] = new int[크기] 

배열크기 = 타입의 byte * 크기 / length와 요소개수 다를 수 있음

ex)

 

** for (타입 변수 : 배열명){ }

// 배열의 요소를 인덱스0 ~ length-1까지 순차적 순회기능

 

복사

- System.arraycopy( )

: 복사본과 원본의 주소 동일, 배열요소 값 변경시 원본, 복사본 모두 변경

: 얕은 복사(주소복사)

 

 

 

 

 

> 얕은 복사와 깊은 복사

 2차원 배열 

> 선언: 타입[ ] [ ]배열명 = new 타입[행][열]  

> 초기화: 타입[ ] [ ]배열명 = {{#,$,%}, {!.@}}

 

 ArrayList 사용법 

성적 산출 프로그램

 

 

[내일배움카드], [국비지원교육]

 

+ Recent posts