충분히 쌓여가는
원격 프로그램 실행 본문
@Controller 어노테이션
원격 호출 가능한 프로그램으로 등록
@RequestMapping 어노테이션
URL과 메서드 연결(맵핑, mapping)
home이라는 메서드가 호출됨
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);
/**
* Simply selects the home view to render by returning its name.
*/
// 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
메서드 추가
package com.fastcampus.ch2;
public class Hello {
// 메서드 추가
public void main() {
System.out.println("Hello");
}
}
@Controller과 @RequestMapping 추가
빨간줄 표시되는 이유: import 하지 않았기 때문, 더블 클릭하면 import 할 수 있는 표시 나옴
package com.fastcampus.ch2;
// 1. 원격 호출 가능한 프로그램으로 등록
@Controller
public class Hello {
// 2. URL과 메서드 연결
@RequestMapping("/hello")
public void main() {
System.out.println("Hello");
}
}
package com.fastcampus.ch2;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
// 1. 원격 호출 가능한 프로그램으로 등록
@Controller
public class Hello {
// 2. URL과 메서드 연결
@RequestMapping("/hello")
public void main() {
System.out.println("Hello");
}
}
hello라는 url과 main()메서드가 연결된 것
브라우저에서 hello라고 url 주소창에 입력(http://localhost:8080/ch2/hello)하면 main()메서드가 호출돼서 Hello가 출력 된다
여기서 void앞에 static메서드가 아닌데 어떻게 호출이 될수 있을까, 정확히 static 생략
main 메서드가 instance 메서드이고,
instance 메서드가 호출가능하다는 것은 중간(tomcat 내부)에서 객체를 생성해주기 때문에 가능하다
instance 메서드로 하는 이유
instance 메서드 - iv, cv 둘 다 사용 가능
static 메서드 - cv만 사용 가능, (tomcat에서 객체생성하는 것은 마찬가지)
static 메서드 사용해도 되지만 둘 다 사용 가능한 instance 메서드를 사용하는 것이 좋다
package com.fastcampus.ch2;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
// 1. 원격 호출 가능한 프로그램으로 등록
@Controller
public class Hello {
int iv = 10; // instance 변수
static int cv = 20; //static 변수
// 2. URL과 메서드 연결
@RequestMapping("/hello")
public void main() { // instance 메서드 - iv, cv 둘 다 사용 가능
System.out.println("Hello");
System.out.println(cv); // 사용 가능
System.out.println(iv); // 사용 가능
}
public static void main2() { // static 메서드 - cv만 사용 가능
System.out.println(cv); // 사용 가능
// System.out.println(iv); // 에러
}
}
만약 public이 아니라 private로 한다면?
그래도 실행가능하다
@RequestMapping으로 연결되어 있다는 의미는 외부에서 연결가능하게 하겠다는 것이기 때문 = 접근제어자 상관없이 사용가능
(내부에서는 private이고 외부에서 호출할 수 있게만 되어있다)
private이 가능한 이유
class 생성(이름: Main)
package com.fastcampus.ch2;
public class Main {
public static void main(String[] args) {
Hello hello = new Hello();
hello.main(); // private 이기 때문에 외부 호출 불가
// Reflection API를 사용 - 클래스 정보를 얻고 다룰 수 있는 강력한 기능 제공
// java.lang.reflect 패키지를 제공
}
}
Reflection API를 이용해서 객체 생성 후 main()메서드 호출
class 정보 가져오기
forName("")에 class 이름을 패키지와 같이 입력
Hello 클래스의 Class 객체(클래스의 정보를 담고있는객체)를 얻어옴
예외처리 해주기(빨간 줄 사라짐: 클래스를 못찾으면 에러 발생)
package com.fastcampus.ch2;
public class Main {
public static void main(String[] args) throws Exception{
// Hello hello = new Hello();
// hello.main(); // private 이기 때문에 외부 호출 불가
// Reflection API를 사용 - 클래스 정보를 얻고 다룰 수 있는 강력한 기능 제공
// java.lang.reflect 패키지를 제공
// class 정보 가져오기
// forName("")에 class 이름을 패키지와 같이 입력
// Hello 클래스의 Class 객체(클래스의 정보를 담고있는객체)를 얻어옴
Class helloClass = Class.forName("com.fastcampus.ch2.Hello"); // Class 정보를 이용해 객체를 만들 수 있다
}
}
Class 객체가 가진 정보로 객체 생성
반환 타입이 Object이기 때문에 (Hello)로 형변환
package com.fastcampus.ch2;
public class Main {
public static void main(String[] args) throws Exception{
// Hello hello = new Hello();
// hello.main(); // private 이기 때문에 외부 호출 불가
// Reflection API를 사용 - 클래스 정보를 얻고 다룰 수 있는 강력한 기능 제공
// java.lang.reflect 패키지를 제공
// class 정보 가져오기
// forName("")에 class 이름을 패키지와 같이 입력
// Hello 클래스의 Class 객체(클래스의 정보를 담고있는객체)를 얻어옴
Class helloClass = Class.forName("com.fastcampus.ch2.Hello"); // Class 정보를 이용해 객체를 만들 수 있다
Hello hello = (Hello)helloClass.newInstance(); // Class 객체가 가진 정보로 객체 생성
}
}
Hello를 가지고 있는 main()메서드를 밖에서 호출할 수 있게 바꾸기
helloClass가 가지고 있는 DeclaredMethod
main이라는 메서드의 정보를 가져옴
setAccessible로 main이라는 정보를 접근가능하게 함 = private인 main()을 호출가능하게 함
main.invoke(hello); = hello.main() 호출한 것과 같다
Method import 해주기
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(); // private 이기 때문에 외부 호출 불가
// Reflection API를 사용 - 클래스 정보를 얻고 다룰 수 있는 강력한 기능 제공
// java.lang.reflect 패키지를 제공
// class 정보 가져오기
// forName("")에 class 이름을 패키지와 같이 입력
// Hello 클래스의 Class 객체(클래스의 정보를 담고있는객체)를 얻어옴
Class helloClass = Class.forName("com.fastcampus.ch2.Hello"); // Class 정보를 이용해 객체를 만들 수 있다
Hello hello = (Hello)helloClass.newInstance(); // Class 객체가 가진 정보로 객체 생성
Method main = helloClass.getDeclaredMethod("main"); // "main" 이라는 메서드의 정보를 가져온 것
main.setAccessible(true); // private인 main()을 호출가능하게
main.invoke(hello); // hello.main() 호출한 것과 같다
}
}
main.java만 실행해보면
Hello - private
20
가 표시된다
파란색 부분을 호출한 것이다
private이기 때문에 외부에서 호출이 안되는게 맞고 해당 Hello 클래스 내부에서만 사용할 수 있는데
다른 클래스, 즉 Main클래스에서 Hello 클래스의 main() 메서드를 호출하였다
* Reflection API를 이용했기 때문
'Spring > Spring' 카테고리의 다른 글
HTTP 요청과 응답1 (0) | 2023.05.18 |
---|---|
Spring으로 개발하기 위해 필요한 도구들 (0) | 2023.05.12 |