참고
수업 중간에 AWS에 올리는 과정이 포함되어있으나 우선 Spring을 익히는 것이 목적이므로 이 부분은 메모를 남기지 않음.
File > new > Spring lagacy Project 로 프로젝트 생성
Spring starter Project
는 스프링 부트 프로젝트를 생성하는 메뉴이므로 이 강의를 들을때는 사용하지 않음
위 사진처럼 ch2라는 새로운 스프링 프로젝트를 생성. (사진은 이미 생성 후이므로 에러발생)
도메인은 com.fastcampus.ch2
로 설정한다.
-HemeController-
package com.fastcampus.ch2;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* Handles requests for the application home page.
*/
@Controller // 1. 원격호출 가능한 프로그램으로 등록
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
// 2. URL과 메서드 연결(매핑, mapping)
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
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";
}
}
-Hello.java-
package com.fastcampus.ch2;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
// 1. 원격호출 가능한 프로그램으로 등록
@Controller
public class Hello {
int iv = 10; // 인스턴스 변수 (iv)
static int cv = 20; // static 변수 (cv)
// URL과 메서드를 연결
@RequestMapping("/hello")
private void main() { // 인스턴스 메서드 - iv, cv 둘 다 사용가능
System.out.println("Hello!");
System.out.println(cv); // OK
System.out.println(iv); // OK
}
public static void main2() { // static 메서드 - cv만 사용가능
System.out.println(cv); // OK
// System.out.println(iv); // 에러 - static메서드는 cv만 사용할 수 있기 때문
}
}
-Main.java-
package com.fastcampus.ch2;
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws Exception{
// Hello hello = new Hello();
// hello.main(); // main메서드가 private로 선언되었을 경우 외부호출불가
// Reflection API를 사용 - 클래스 정보를 얻고 다룰 수 있는 강력한 기능을 제공
// java.lang.reflect패키지를 제공
// Hello클래스의 Class객체(클래스의 정보를 담고 있는 객체)를 얻어온다.
Class helloClass = Class.forName("com.fastcampus.ch2.Hello");
Hello hello = (Hello)helloClass.newInstance(); // Class객체가 가진 정보로 객체 생성
Method main = helloClass.getDeclaredMethod("main");
main.setAccessible(true); // private인 main()을 호출가능하게 한다.
main.invoke(hello); // hello.main() 호출
}
}
spring의 main메서드는 static이 없어도 무관.
URL로 원격프로그램을 요청하면 톰캣이 내부에서 객체를 생성해주어 static으로 선언하지 않은 인스턴스메서드임에도 호출이 가능한 것.
인스턴스 메서드로 사용하는 이유:
인스턴스 변수와 static변수를 모두 사용할 수 있기 때문.
static메서드에서는 static변수만 사용가능함.
이에 대한 설명은 Ch02. 객체지향입문 03 참고.
접근지정자를 public
이 아니라 private
로 선언해도 정상적으로 동작함.
=> @RequestMapping
를 사용하면 접근제어자와 관계없이 해당 메서드를 외부에서 호출할 수 있도록 하겠다는 의미이므로 정상동작하는것.
단, 내부에서는 그대로 private인 상태.
클래스파일(*.class)이 메모리에 올라갈 때, 클래스파일마다 Class객체가 하나씩 생성된다.
Reflection API
를 당장 알아야 하는건 아니지만 spring framework에서 자주 사용되므로 알아는 두는게 좋음.
YoilTeller: 년.월.일을 입력하면 요일을 알려주는 프로그램
-YoilTeller.java-
package com.fastcampus.ch2;
import java.util.Calendar;
// 년월일을 입력하면 요일을 알려주는 프로그램
public class YoilTeller {
public static void main(String[] args) {
// 1. 입력
String year = args[0];
String month = args[1];
String day = args[2];
int yyyy = Integer.parseInt(year);
int mm = Integer.parseInt(month);
int dd = Integer.parseInt(day);
// 2. 작업
Calendar cal = Calendar.getInstance();
cal.set(yyyy, mm -1, dd);
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); // 1: 일요일, 2: 월요일 ...
char yoil = " 일월화수목금토".charAt(dayOfWeek);
// 3. 출력
System.out.println(year + "년 " + month + "월 " + day + "일은 ");
System.out.println(yoil + "요일입니다.");
}
}
실행은 .java파일이 컴파일된 파일이 target폴더에 위치하게 되므로
target폴더 우클릭 > terminal 열기 > cd classes로 이동한 후
java com.fastcampus.ch2.YoilTeller 2022 09 03
을 입력하여 테스트.
맨 뒤의 숫자들은 매개변수로 넣어줄 값이 된다.
현재 요일을 반환함을 확인가능.
main메서드에서 매개변수를 String 배열로 받아 요일을 구할때 사용함.
String[] args
를 통해 String배열로 받았기 때문에 int로 변경하는 과정이 필요한 것.
서버로 매개변수를 받을때는 HttpServletRequest를 이용하여 매개변수로 받음.
HttpServletRequest의 method
http://52.78.79.190:8080/ch2/requestInfo?year=2022&month=9&day=3
getScheme()
: http
getServerName()
: 52.78.79.190
getServerPort()
: 8080
getContextPath()
: ch2
getServletPath()
: requestInfo
getRequestURI()
: /ch2/requestInfo
getRequestURL()
: http://52.78.79.190:8080/ch2/requestInfo
getQueryString()
: year=2022&month=9&day=3?뒤의 url이 값을 전달할 때 사용하는
queryString
임
URI와 URL의 차이
-YoilTeller.java-
package com.fastcampus.ch2;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Calendar;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
// 년월일을 입력하면 요일을 알려주는 프로그램
@Controller
public class YoilTeller {
// public static void main(String[] args) {
@RequestMapping("/getYoil")
public void main(HttpServletRequest request, HttpServletResponse response) throws IOException{
// 1. 입력
String year = request.getParameter("year");
String month = request.getParameter("month");
String day = request.getParameter("day");
int yyyy = Integer.parseInt(year);
int mm = Integer.parseInt(month);
int dd = Integer.parseInt(day);
// 2. 작업
Calendar cal = Calendar.getInstance();
cal.set(yyyy, mm -1, dd);
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); // 1: 일요일, 2: 월요일 ...
char yoil = " 일월화수목금토".charAt(dayOfWeek);
// 3. 출력
response.setContentType("text/html"); // 응답의 형식을 html로 지정
response.setCharacterEncoding("utf-8"); // 응답의 인코딩을 utf-8로 지정
PrintWriter out = response.getWriter(); // 브라우저로의 출력 스트림(out)을 얻는다.
out.println("<html>");
out.println("<head>");
out.println("</head>");
out.println("<body>");
out.println(year + "년 " + month + "월 " + day + "일은 ");
out.println(yoil + "요일입니다.");
out.println("</body>");
out.println("</html>");
out.close();
}
}
톰캣서버 실행 후
http://localhost:8090/ch2/getYoil?year=2022&month=9&day=3
로 값을 넘겨 확인
서버란?
서비스를 제공하는 애플리케이션
클라리언트란?
서버를 요청하는 애플리케이션
랜덤한 주사위를 굴리는 프로그램
실행 할때마다 결과가 변하는 동적리소스.
html, js, css처럼 리소스내용이 고정되어 있는 리소스는 정적리소스에 해당한다.
위에서 사용한 ch2프로젝트에 클래스를 추가함
-TwoDice.java-
package com.fastcampus.ch2;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller // ctrl + shift + o => 자동 import
public class TwoDice {
@RequestMapping("/rollDice")
public static void main(HttpServletResponse response) throws IOException {
int idx1 = (int)(Math.random()*6)+1;
int idx2 = (int)(Math.random()*6)+1;
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("</head>");
out.println("<body>");
out.println("<img src='resources/img/dice" + idx1 + ".jpg'>");
out.println("<img src='resources/img/dice" + idx2 + ".jpg'>");
out.println("</body>");
out.println("</html>");
out.close();
}
}
자바에서 제공하는 랜덤함수를 이용하여 1~6사이의 수를 구하여 해당 숫자에 해당하는 resources > img 폴더의 Dice.jpg이미지를 꺼내어 html로 출력해줌.
getQueryString()
: ?name1=value1&name2=value2
=> QueryString이므로 name과 value모두 String이므로, 형변환이 필요할 수 있다.
getParameterValues("name")
을 이용하면 모든 value값을 배열로 가져올 수 있음.
서버란?
서비스를 제공하는 애플리케이션 (응답하는 역할)
클라리언트란?
서버를 요청하는 애플리케이션 (요청하는 역할)
서버는 종류에 따라 email server, file server, web server 등으로 구분되는데, 요청의 ip주소만으론 이를 구분할 수 없다.
이를 구분하기 위해서 사용하는것이 port번호가 이다.
web server의 경우 기본적으로 포트번호 80번을 사용하지만 기본설정과 다른 포트번호로 설정해둘 경우 생략이 불가능함.
웹 애플리케이션 서버(WAS)
요청이 왔을때 thread
컨트롤러와 서블릿은 비슷한 개념임
서블릿 servlet
: 작은 서버프로그램의 개념
톰캣설치경로/conf/server.xml
: Tomcat 서버 설정 파일톰캣설치경로/conf/web.xml
: Tomcat의 모든 web app의 공통설정웹앱이름/WEB-INF/web.xml
: web app의 개별설정설정적용순서: 공통설정 적용 -> 개별설정 적용
예전에는 web.xml에서 1) 원격프로그램 등록 2) URL연결
을 직접 해줘야 했지만 요즘은 전부 에너테이션@Controller @RequestMapping("/name")
으로 처리함.