Spring WebMVC: 

페이지 컨트롤러 만들기 II


───────
Spring webMVC: Request Handler의 리턴값 다루기


/* Spring webMVC: Request Handler의 리턴값 다루기
 */   
package control;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller  
@RequestMapping("/control/controller15/")
public class Controller15 {
  
  // 1) void: 요청 핸들러에서 직접 출력하기
  @RequestMapping("ok1")
  public void ok1(HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("ok1(): 안녕하세요!"); 
  }

  // 2) String: 리턴 값을 클라이언트로 출력하기
  @RequestMapping(path="ok2", produces="text/plain;charset=UTF-8")
  @ResponseBody
  public String ok2(HttpServletResponse response) throws Exception {
    return "ok2(): 안녕하세요!"; 
  }

  // 3) String: 리턴 값을 클라이언트로 출력하기 - error
  @RequestMapping(path="ok3")
  @ResponseBody // <=== 리턴 값이 응답 데이터임을 표시하는 애노테이션
                // 리턴 값을 바로 출력할 때는 @RequestMapping의 produces 속성을 이용하여
                // 출력 내용의 타입과 인코딩을 지정한다.
  public String ok3(HttpServletResponse response) throws Exception {
    //@ResponseBody를 사용하여 리턴 값을 바로 클라이언트로 출력할 때는
    // 다음과 같이 UTF-8 처리를 지정할 수 없다.
    // 해결책? 위의 ok2() 메서드에서처럼 @RequestMapping의 produces 속성으로 지정해야 한다.
    response.setContentType("type/plain;charset=UTF-8");
    return "ok3(): 안녕하세요!"; 
  }

  // 4) String: JSP로 포워딩하기
  //    => @ResponseBody가 붙지 않으면 리턴 값을 JSP URL로 취급한다.
  @RequestMapping(path="ok4")
  public String ok4() throws Exception {
    return "/controller15_ok4.jsp"; 
  }
}



application-context.xml 파일에 다음과 같은 bean 객체를 등록해줍니다.


<!-- 페이지 컨트롤러가 JSP URL을 리턴할 때, 해당 JSP를 찾아 실행하는 객체 -->
    <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="prefix" value="/"/>
    <property name="suffix" value=".jsp"/>
    </bean>


이렇게 JSP를 실행할 객체를 명시적으로 등록하게 되면 페이지 

컨트롤러에서 JSP URL을 리턴할 때 이 설정을 고려하게 됩니다.


그러나 String을 리턴 값으로 설정해주고 JSP로 포워딩 해준 4번 예제의 

코드를 바꿔야 합니다. 이유는 다음의 주석을 참고해주세요. 

* Controller15의 ok4() 메서드를 다음과 같이 정의해야 합니다.


@RequestMapping(path="ok4")
  public String ok4() throws Exception {

// return "/controller15_ok4.jsp"; // InternalResourceViewResolver를 설정하기 전에는 괜찮다. // InternalResourceViewResolver를 설정한 후에는 오류가 발생한다. // why? 리턴 값 앞 뒤에 문자열이 붙기 때문이다. // "/" + "controller15_ok4.jsp" + ".jsp" // 그래서 최종 url은 "/controller15_ok4.jsp.jsp"가 된다. return "controller15_ok4"; // 이렇게 InternalResourceViewResolver의 설정을 고려하여 리턴 값을 작성해야 한다. }


webapp 폴더 안에 controller15_ok4.jsp 파일을 만들고 다음처럼 작성합니다.


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta charest="UTF-8">
<title>test</title>
</head>
<body>
<h1>contoller_ok4()</h1>
</body>
</html>


실행 방법 :

http:localhost:8080/spring-web01/control/controller15/ok4.do




───────

클라이언트로 리턴 값을 출력하지도 않고, JSP URL로도 지정하지 않을 때

 앞서 application-context.xml 파일에 jspViewResolver bean 객체를 등록

    해주었기에 다음과 같은 예제를 추가해주고 실행해보면 정상적으로 실행

    되는 것을 알 수 있습니다.



// 5) void: 클라이언트로 리턴 값을 출력하지도 않고, JSP URL로도 지정하지 않으면 
  //    => 기본 JSP URL로 현재 URL을 사용한다.
  //    => 단 이럴 경우 스프링 설정 파일에 JSP를 어디에서 찾을 것인지 지정해야 한다.
  //       지정하지 않으면 URL이 
  @RequestMapping(path="ok5")
  public void ok5() throws Exception {
    System.out.println("ok5()");
  }


 실행 방법 :

http:localhost:8080/spring-web01/control/controller15/ok5.do





───────

JSP URL을 바구니에 담아 리턴하기


// 6) JSP URL을 바구니에 담아 리턴하기
  @RequestMapping(path="ok6")
  public ModelAndView ok6() throws Exception {
    ModelAndView mv = new ModelAndView();
    mv.setViewName("controller15_ok6");
    return mv;
  }


기존 예제에 위 코드를 추가하고 webapp 폴더 안에 controller15_ok6.jsp 파일을 만듭니다. 만든 파일에는 아래와 같이 작성합니다.


<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta charest="UTF-8"> <title>test</title> </head> <body> <h1>contoller_ok6()</h1> </body> </html>


 실행 방법 :

http:localhost:8080/spring-web01/control/controller15/ok6.do



───────

JSP URL과 JSP 사용할 데이터도 함께 ModelAndView 바구니에 담아 리턴하기


// 7) JSP URL과 JSP 사용할 데이터도 함께 ModelAndView 바구니에 담아 리턴하기
  @RequestMapping(path="ok7")
  public ModelAndView ok7() throws Exception {
    ModelAndView mv = new ModelAndView();
    mv.setViewName("controller15_ok7");
    mv.addObject("title", "제목이네요!");
    
    Member member = new Member();
    member.setName("홍길동");
    member.setAge(20);
    member.setWorking(true);
    mv.addObject("member", member);
    
    /* 이렇게 ModelAndView 바구니에 값을 담아 두면,
     * 프론트 컨트롤러는 이 바구니에 담긴 값을 꺼내
     * JSP 가 사용할 수 있도록 ServletRequest 바구니에 옮겨 싣는다.
     */


기존 예제에 위 코드를 추가하고 webapp 폴더 안에 controller15_ok7.jsp 파일을 만듭니다. 만든 파일에는 아래와 같이 작성합니다.


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta charest="UTF-8">
<title>test</title>
</head>
<body>
<h1>contoller_ok7()</h1>
${title}<br>
${member.name}<br>
${member.age}<br>
${member.working}<br>
</body>
</html>


 실행 방법 :

http:localhost:8080/spring-web01/control/controller15/ok7.do



실행 결과 :

contoller_ok7()

제목이네요!
홍길동
20
true



───────

JSP URL은 리턴 값으로,  JSP 사용할 데이터는 Model 바구니에 담아 리턴하기



// 8) JSP URL은 리턴 값으로, JSP가 사용할 데이터는 Model 바구니에 담는다.
  @RequestMapping(path="ok8")
  public String ok8(Model model) throws Exception {
    model.addAttribute("title", "제목이네요!");
    
    Member member = new Member();
    member.setName("홍길동");
    member.setAge(20);
    member.setWorking(true);
    model.addAttribute("member", member);
    
    /* 이렇게 ModelAndView 바구니에 값을 담아 두면,
     * 프론트 컨트롤러는 이 바구니에 담긴 값을 꺼내
     * JSP 가 사용할 수 있도록 ServletRequest 바구니에 옮겨 싣는다.
     */
    return "controller15_ok8";
  }


기존 예제에 위 코드를 추가하고 webapp 폴더 안에 controller15_ok8.jsp 파일을 만듭니다. 만든 파일은 아래와 같이 작성합니다.


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta charest="UTF-8">
<title>test</title>
</head>
<body>
<h1>contoller_ok8()</h1>
${title}<br>
${member.name}<br>
${member.age}<br>
${member.working}<br>
</body>
</html>


 실행 방법 :

http:localhost:8080/spring-web01/control/controller15/ok8.do



───────

Model 대신 Map 객체를 바구니로 사용해서 리턴 값을 받기


// 9) Model 대신 Map 객체를 바구니로 사용할 수 있다.
  @RequestMapping(path="ok9")
  public String ok9(Model model) throws Exception {
    model.addAttribute("title", "제목이네요!");
    
    Member member = new Member();
    member.setName("홍길동");
    member.setAge(20);
    member.setWorking(true);
    model.addAttribute("member", member);
    
    /* 이렇게 Map 바구니에 값을 담아 두면,
     * 프론트 컨트롤러는 이 바구니에 담긴 값을 꺼내
     * JSP 가 사용할 수 있도록 ServletRequest 바구니에 옮겨 싣는다.
     */
    return "controller15_ok8";
  }


기존 예제에 위 코드를 추가하고 webapp 폴더 안에 controller15_ok9.jsp 파일을 만듭니다. 만든 파일은 아래와 같이 작성합니다.



블로그 이미지

필로그래머

,

 Spring WebMVC: 

페이지 컨트롤러 만들기


Spring에서 제공하는 프론트 컨트롤러와 협업할 페이지 컨트롤러 만들기



 Spring WebMVC 프로젝트 설정 방법


1) web.xml에 Spring webmvc의 프론트 컨트롤러를 설정합니다.


<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <display-name>project01</display-name> <!-- 프론트 컨트롤러 등록 --> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:control/application-context.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> <!-- 클라이언트가 요청하지 않아도 init() 함수가 호출. 즉 servlet 객체가 생성한다. --> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> </web-app>



2) Spring 설정 파일을 준비합니다.

/src/main/src/control/application-context.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:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" 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.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- Spring IoC 컨테이너를 위한 객체 등록 --> <context:component-scan base-package="control"/> <!-- Spring WebMVC 관련 기능을 처리할 객체를 등록한다. (RequsetMapping 되어 있는 객체를 등록) --> <mvc:annotation-driven/> </beans>



3) Gradle 설정 파일을 준비합니다. (프로젝트 폴더 바로 아래에 위치시켜 주세요.)

    build.gradle


apply plugin: 'java' 
apply plugin: 'eclipse-wtp' 
apply plugin: 'war'       

compileJava {
  options.encoding = 'UTF-8'  
  sourceCompatibility = '1.8' 
}

repositories {
  mavenCentral() 
}

dependencies {
  compile 'org.slf4j:slf4j-api:1.7.22'
  compile group: 'commons-fileupload', name: 'commons-fileupload', version: '1.3.2'
  compile group: 'javax.servlet', name: 'jstl', version: '1.2'
  compile group: 'org.springframework', name: 'spring-webmvc', version: '4.3.9.RELEASE'
  
  providedCompile group: 'javax.servlet', name: 'javax.servlet-api', version: '3.1.0'
  
  testCompile 'junit:junit:4.12'
}


4) cmd 명령창에서 해당 프로젝트 폴더로 경로를 설정한 후 "gradle eclipse" 

   명령어를 입력해 실행시킵니다.

* 이 글의 예제에서의 프로젝트 폴더는 spring-web01입니다.



 페이지 컨트롤러 만들기


1) 클래스를 페이지 컨트롤러로 표시하기

   - @Controller 애노테이션을 붙입니다.


2) 요청을 처리할 메서드를 표시하기 

    - @RequestMapping(URL) 애노테이션을 붙입니다.



/* Spring webMVC: 페이지 컨트롤러 만들기 * */ package step01; import java.io.PrintWriter; 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 Controller01 { @RequestMapping("/control/controller01") // 어떤 요청을 처리할지 표시 public void service(HttpServletRequest request, HttpServletResponse response) throws Exception { response.setContentType("text/plain;charset=UTF-8"); PrintWriter out = response.getWriter(); out.println("Hello, world!"); } }



결과 : 

    웹 브라우저 url 주소에 http://localhost:8080/프로젝트명/패키지명/controller01.do 를 입력하면 

    화면에 "Hello, world!"가 출력되는 것을 확인하실 수 있습니다.





설정 파일은 남겨둔 채 Controller01 파일을 다음 Controller02 파일로

    업그레이드 시켜보겠습니다. 메소드의 이름은 꼭 service()일 필요가

    없다는 것을 알 수 있습니다. @RequestMapping에서 설정해준 경로의

    이름이 메소드 이름이 되면 됩니다.


/* Spring webMVC: 페이지 컨트롤러 만들기
 * 
 */
package control;

import java.io.PrintWriter;

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 Controller02 {
  @RequestMapping("/control/controller02/a") // 어떤 요청을 처리할지 표시
  public void a(HttpServletRequest request, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("aaaa");
  }

  @RequestMapping("/control/controller02/b") // 어떤 요청을 처리할지 표시
  public void b(HttpServletRequest request, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("bbbb");
  }

  @RequestMapping("/control/controller02/c") // 어떤 요청을 처리할지 표시
  public void c(HttpServletRequest request, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("cccc");
  }
}



위 예제는 다음 Controller03의 예제와 똑같은 결과를 호출합니다.

    공통되는 경로가 있다면 @RequestMapping을 통해 묶어줄 수 있습니다.

     요청 URL 계산하기 = class에 붙은 URL + 메소드에 붙은 URL


/* Spring webMVC: 페이지 컨트롤러 만들기
 * 
 */
package control;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller  // 페이지 컨트롤러 클래스임을 표시
@RequestMapping("/control/controller03/")
public class Controller03 {
  @RequestMapping("a") // 어떤 요청을 처리할지 표시
  public void a(HttpServletRequest request, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("aaaa");
  }

  @RequestMapping("b") // 어떤 요청을 처리할지 표시
  public void b(HttpServletRequest request, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("bbbb");
  }

  @RequestMapping("c") // 어떤 요청을 처리할지 표시
  public void c(HttpServletRequest request, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("cccc");
  }
}


▶ 호출될 메서드가 한 개일 경우에는 첫번째 @RequestMapping의 경로만

    설정해줘도 웹 브라우저에서 처리해줄 수 있습니다.

    요청 URL 계산하기 = class에 붙은 URL + 메소드에 붙은 URL


/* Spring webMVC: 한 페이지 컨트롤러에서 요청 처리하기
 * 
 */
package control;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller  // 페이지 컨트롤러 클래스임을 표시
@RequestMapping("/control/controller04/ok")
public class Controller04 {
  @RequestMapping // 어떤 요청을 처리할지 표시
  public void a(HttpServletRequest request, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("aaaa");
  }
}




요청 http method 구분하여 처리하기 I


/* Spring webMVC: 요청 http method 구분하여 처리하기
 * 
 */
package control;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller  // 페이지 컨트롤러 클래스임을 표시
@RequestMapping("/control/controller05/ok")
public class Controller05 {
 
  @RequestMapping(method=RequestMethod.GET)
  public void get(HttpServletRequest request, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("get");
  }

  @RequestMapping(method=RequestMethod.POST)
  public void post(HttpServletRequest request, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("post");
  }
}



GET 요청과 POST 요청을 가능하게 해주는 html 코드 I

*참고 : .html 같은 정적파일은 webapp 폴더 아래에 생성해줘야 합니다.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="control/controller05/ok.do" method="GET">
    <button>GET 요청</button>
</form>
<hr>
<form action="control/controller05/ok.do" method="POST">
    <button>POST 요청</button>
</form>
</body>
</html>


▶ 실행 방법 : http://localhost:8080/spring-web01/controller05.html
GET 요청 버튼을 클릭하면 화면에 get 문장이 출력되고 
POST 요청 버튼을 클릭하면 화면에 post 문장이 출력됩니다.



요청 http method 구분하여 처리하기 II


/* Spring webMVC: 요청 http method 구분하여 처리하기
 * 
 */
package control;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller  // 페이지 컨트롤러 클래스임을 표시
@RequestMapping("/control/controller06/")
public class Controller06 {
 
  //@RequestMapping(value="ok", method=RequestMethod.GET) // 이렇게 해도 되고
  @RequestMapping(path="ok", method=RequestMethod.GET) // 이렇게 해도 된다.
  public void get(HttpServletRequest request, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("get");
  }

  //@RequestMapping(value="ok", method=RequestMethod.POST) // 이렇게 해도 되고
  @RequestMapping(path="ok", method=RequestMethod.POST)
  public void post(HttpServletRequest request, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("post");
  }
}


GET 요청과 POST 요청을 가능하게 해주는 html 코드 II


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="control/controller06/ok.do" method="GET">
    <button>GET 요청</button>
</form>
<hr>
<form action="control/controller06/ok.do" method="POST">
    <button>POST 요청</button>
</form>
</body>
</html>




요청 URL에 주는 파라미터에 따라 호출 메서드 제한하기

- 파라미터의 존재 유무로 요청을 구분합니다.


/* Spring webMVC: 요청 URL에 주는 파라미터에 따라 호출 메서드 제한하기
 * 
 */
package control;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller  
@RequestMapping("/control/controller07/")
public class Controller07 {
 
  @RequestMapping(path="ok", params={"name"}) 
  public void get(HttpServletRequest request, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("name 있어요!");
  }

  @RequestMapping(path="ok", params={"age", "tel"})
  public void post(HttpServletRequest request, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("age와 tel 있어요!");
  }
}


@RequestMapping의 params 속성에 지정한 값과 일치하는 요청 

파라미터가 있을 경우에 호출됩니다.


▶ 실행 방법: 

http://localhost8080:/spring-web01/control/controller07/ok.do?&age=20&tel=111



HTTP 요청 프로토콜에 지정한 이름의 헤더가 있을 경우에 호출됩니다.


/* Spring webMVC: 요청 프로토콜의 헤더 이름을 요청 조건으로 지정
 * => HTTP 요청 프로토콜에 지정한 이름의 헤더가 있을 경우에 호출된다.
 * 
 */
package control;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller  
@RequestMapping("/control/controller08/")
public class Controller08 {
 
  @RequestMapping(path="ok", headers="aaaa") 
  public void get(HttpServletRequest request, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("aaaa 있어요!");
  }

  @RequestMapping(path="ok", headers={"bbbb", "cccc"})
  public void post(HttpServletRequest request, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("bbbb, cccc 있어요!");
  }
}



AJAX 요청을 통해 헤더 값을 넘겨주는 코드 

* 참고 : 그냥 html을 통해선 헤더 값을 넘겨줄 수 없어요.


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<button id="btn1">"aaaa" 헤더 요청</button>
<button id="btn2">"bbbb", "cccc" 헤더 요청</button>
<div>
<textarea id="ta" cols="80" rows="8"></textarea>
</div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
$("#btn1").click(function() {
    $.ajax("control/controller08/ok.do", {
        method: "get",
        headers: {"aaaa":"hello"},
        dataType: "text"})
        .done(function(result) {
            $("#ta").val(result)
        })
        .fail(function(xhr, status, error) {
            $("#ta").val(xhr.responseText)
        })
})
$("#btn2").click(function() {
    $.ajax("control/controller08/ok.do", {
        method: "get",
        headers: {"bbbb":"hello", 
                   "cccc":"hello"}, // 한글은 헤더로 넘겨줄 수 없습니다.
        dataType: "text"})
        .done(function(result) {
            $("#ta").val(result)
        })
        .fail(function(xhr, status, error) {
            $("#ta").val(xhr.responseText)
        })
})
</script>
</body>
</html>


▶ 실행 방법: 

http://localhost8080:/spring-web01/controller08.html




요청 프로토콜의 Accept 헤더의 값에 따라 호출될 메서드 결정


/* Spring webMVC: 요청 프로토콜의 Accept 헤더의 값에 따라 호출될 메서드 결정
 * 
 */
package control;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller  
@RequestMapping("/control/controller09/")
public class Controller09 {
  
  @RequestMapping(path="ok", produces="text/plain") 
  public void get(HttpServletRequest request, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("text/plain 보냄!");
  }

  @RequestMapping(path="ok", produces="application/json")
  public void post(HttpServletRequest request, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("application/json 보냄!");
  }
}


▶ Accept 요청 헤더

     - 웹 브라우저가 웹 서버에게 요구하는 콘텐트의 타입을 가리킵니다.


produces란?
    - 이 메서드를 생산하는 콘텐트의 타입을 가리킵니다.


Accept 헤더의 값에 따라 호출될 메서드를 결정하는 html 코드


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<button id="btn1">"text/plain" 콘텐트 요청</button>
<button id="btn2">"application/json" 콘텐트 요청</button>
<div>
<textarea id="ta" cols="80" rows="8"></textarea>
</div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
$("#btn1").click(function() {
    $.ajax("control/controller09/ok.do", {
        method: "get",
        headers: {"Accept":"text/plain"},
        dataType: "text"})
        .done(function(result) {
            $("#ta").val(result)
        })
        .fail(function(xhr, status, error) {
            $("#ta").val(xhr.responseText)
        })
})
$("#btn2").click(function() {
    $.ajax("control/controller09/ok.do", {
        method: "get",
        headers: {"Accept":"application/json"},
        dataType: "json"})
        .done(function(result) {
            $("#ta").val(result)
        })
        .fail(function(xhr, status, error) {
            $("#ta").val(xhr.responseText)
        })
})
</script>
</body>
</html>



▶ 실행 방법: 

http://localhost8080:/spring-web01/controller09.html



요청 프로토콜의 Content-Type 헤더 값에 따라 호출될 메서드를 결정하기


/* Spring webMVC: 요청 프로토콜의 Content-Type 헤더 값에 따라 호출될 메서드 결정
 * => Content-Type 요청 헤더?
 *    - 웹 브라우저가 웹 서버에게 보내는 데이터의 형식을 의미한다.
 */   
package control;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller  
@RequestMapping("/control/controller10/")
public class Controller10 {
  
  @RequestMapping(path="ok", consumes="text/plain") 
  public void get(HttpServletRequest request, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("text/plain 데이터를 받아서 처리했음!");
  }

  @RequestMapping(path="ok", consumes="application/json")
  public void post(HttpServletRequest request, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("application/json 데이터를 받아서 처리했음!");
  }
}

cosumes 란?

    - 클라이언트가 보낸 데이터의 형식 중에서 이 메서드가 처리할 수 있는

      형식을지정



<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<button id="btn1">"text/plain" 콘텐트 요청</button>
<button id="btn2">"application/json" 콘텐트 요청</button>
<div>
<textarea id="ta" cols="80" rows="8"></textarea>
</div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
$("#btn1").click(function() {
    $.ajax("control/controller10/ok.do", {
        method: "post",
        data: "hello!",
        headers: {"Content-Type":"text/plain"},
        dataType: "text"})
        .done(function(result) {
            $("#ta").val(result)
        })
        .fail(function(xhr, status, error) {
            $("#ta").val(xhr.responseText)
        })
})
$("#btn2").click(function() {
    $.ajax("control/controller10/ok.do", {
        method: "post",
        data: '{"name":"hong", "age":"20", "tel":"1111-1111"}',
        headers: {"Content-Type":"application/json"},
        dataType: "json"})
        .done(function(result) {
            $("#ta").val(result)
        })
        .fail(function(xhr, status, error) {
            $("#ta").val(xhr.responseText)
        })
})
</script>
</body>
</html>


▶ 실행 방법: 

http://localhost8080:/spring-web01/controller10.html




Request Handler(요청을 처리하는 메서드)의 파라미터들 I

  프론트 컨트롤러는 페이지 컨트롤러의 메서드를 호출할 때,

   그 메서드가 어떤 파라미터 값을 요구하는 지를 분석하여

   그에 해당하는 값을 자동으로 꼽아줍니다.

 

 ▶ Request Handler의 파라미터로 선언할 수 있는 것

    1) HttpServletRequest, ServletRequest

    2) HttpServletResponse, ServletResponse

    3) HttpSession

    4) Map, Model 

    5) 요청 파라미터 



/* Spring webMVC: Request Handler(요청을 처리하는 메서드)의 파라미터들 I
 * => Request Handler의 파라미터로 선언할 수 있는 것
 *    1) HttpRequestServlet, ServletRequest
 */   
package control;

import java.io.FileInputStream;
import java.io.PrintWriter;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller  
@RequestMapping("/control/controller11/")
public class Controller11 {
  
  @RequestMapping("ok1") 
  public void ok1() throws Exception {
    System.out.println("ok1(): 프론트 컨트롤러로부터 아무것도 받지 않는다.");
  }

  @RequestMapping("ok2")
  public void ok2(HttpServletRequest request) throws Exception {
    System.out.println("ok2()");
  }

  @RequestMapping("ok3")
  public void ok3(HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("ok3()");
  }

  @RequestMapping("ok4")
  public void ok4(HttpServletRequest request, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("ok4()");
  }

  @RequestMapping("ok5")
  public void ok5(HttpSession session, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("ok5()");
  }
  
  // 프론트 컨트롤러가 줄 수 없는 값을 메서드에서 요구할 경우,
  // 즉 파라미터에 선언할 경우,
  // 실행할 때 오류가 발생한다!
  // 예) 다음 메서드에서 FileInputStream 파라미터가 이런 경우이다.
  @RequestMapping("ok6")
  public void ok6(FileInputStream in, HttpServletResponse response) throws Exception {
    System.out.println(in);
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("ok6()");

  }
  
  // 이 메서드에서 실행한 결과를 담을 빈 바구니를 요구할 수 있다.
  // 이 바구니에 값을 담으면, JSP에서 꺼내 쓸 수 있다.
  // 바구니의 타입은 Map 또는 Model 등이 가능하다.
  @RequestMapping("ok7")
  public void ok7(Map<String, Object> store, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("ok7()");
    
    store.put("name", "홍길동");
    store.put("age", 20);
  }
  // 이렇게 바구니에 담은 데이터는
  // 스프링의 프론트 컨트롤러가 ServletRequest에 보관한다.
  // 그래서 JSP에서 꺼내 쓸 수 있는 것이다.

  @RequestMapping("ok8")
  public void ok8(Model store, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("ok8()");
    
    store.addAttribute("name", "홍길동");
    store.addAttribute("age", 20);
      
    // Model이나 Map이나 쓰임새는 같다.
    // 이렇게 바구니에 담은 데이터는
    // 스프링의 프론트 컨트롤러가 ServletRequest에 보관한다.
    // 그래서 JSP에서 꺼내 쓸 수 있는 것이다.
  }

  // 클라이언트가 보낸 데이터를 꺼내기
  // => 예전처럼 문자열을 원하는 형식을 직접 형변환 해야 한다.
  @RequestMapping("ok9")
  public void ok9(HttpServletRequest request, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("ok9()");
    
    out.printf("name: %s\n", request.getParameter("name"));
    out.printf("age: %d\n", Integer.parseInt(request.getParameter("age")));
    out.printf("working: %b\n", Boolean.parseBoolean(request.getParameter("working")));
      
  }

  // 클라이언트가 보내는 데이터의 이름과 동일한 이름으로 파라미터 변수를 선언한다.
  // 그러면, 프론트 컨트롤러가 파라미터 이름과 같은 데이터를 찾아서 호출할 때 꼽아준다.
  // 프론트 컨트롤러는 문자열을 원시타입의 값으로 자동으로 바꿔준다.
  // 그 외의 타입에 대해서는 오류가 발생한다.
  // 해결책? => 웹 파라미터 타입 변환기를 설치해야 한다.
  @RequestMapping("ok10")
  public void ok10(String name, int age, boolean working, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("ok10()");
    out.printf("name: %s\n", name);
    out.printf("age: %d\n", age);
    out.printf("working: %b\n", working);
    
  }
}


▶ 실행 방법: 

http://localhost8080:/spring-web01/control/controller11/ok숫자.do?파라미터명=값&파라미터명=값



Request Handler(요청을 처리하는 메서드)의 파라미터들 II


/* Spring webMVC: Request Handler(요청을 처리하는 메서드)의 파라미터들 II - 
 */  
package control;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller  
@RequestMapping("/control/controller12/")
public class Controller12 {
  // 클라이언트가 보낸 파라미터 값을 받는 방법
  
  // 1) 보내는 데이터(요청 파라미터)의 이름과 같은 이름으로 아규먼트 이름을 짓는다.
  @RequestMapping("ok1")
  public void ok1(String name, int age, boolean working, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("ok1()");
    out.printf("name: %s\n", name);
    out.printf("age: %d\n", age);
    out.printf("working: %b\n", working);
  }
  
  // 2) 보내는 데이터(요청 파라미터)의 이름과 아규먼트 이름이 다를 경우
  //    @RequestParam 애노테이션을 사용하여 그 이름을 지정할 수 있다.
  //    단, @RequestParam을 붙이는 순간 필수 항목이 된다. URL에 파라미터로 넘겨주지 않으면 오류 발생!
  @RequestMapping("ok2")
  public void ok2(
      @RequestParam(name="name") String n, 
      @RequestParam(name="age")int a, 
      @RequestParam(name="working")boolean w, 
      HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("ok2()");
    out.printf("name: %s\n", n);
    out.printf("age: %d\n", a);
    out.printf("working: %b\n", w);
  }

  // 3) @RequestParam 애노테이션에서 요청 파라미터 값을 선택 항목으로 만들기
  @RequestMapping("ok3")
  public void ok3(
      @RequestParam(name="name", required=false) String n, 
      @RequestParam(name="age", required=false)int a, 
      @RequestParam(name="working", required=false)boolean w, 
      HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("ok3()");
    out.printf("name: %s\n", n);
    out.printf("age: %d\n", a);
    out.printf("working: %b\n", w);
  }

  // 4) @RequestParam 애노테이션에서 요청 파라미터의 기본(default) 값 지정하기
  @RequestMapping("ok4")
  public void ok4(
      @RequestParam(name="name", required=false) String n, 
      @RequestParam(name="age", required=false, defaultValue="0")int a, 
      @RequestParam(name="working", required=false, defaultValue="false")boolean w, 
      HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("ok4()");
    out.printf("name: %s\n", n);
    out.printf("age: %d\n", a);
    out.printf("working: %b\n", w);
  }

  // 5) 요청 파라미터 값을 바로 값 객체(Value Object; VO)에 저장하기
  //    VO 객체의 프로퍼티 이름과 일치하는 요청 파라미터를 찾아서 그 값을 넣어준다.
  //    누가? 프론트 컨트롤러가 Member 객체를 생성한 다음에 값을 넣어준다.
  @RequestMapping("ok5")
  public void ok5(Member member, HttpServletResponse response) throws Exception {
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("ok5()");
    out.printf("name: %s\n", member.getName());
    out.printf("age: %d\n", member.getAge());
    out.printf("working: %b\n", member.isWorking());
  }
}



ok5() 메서드 파라미터의 Member.class 작성하기


package control; public class Member { String name; int age; boolean working; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public boolean isWorking() { return working; } public void setWorking(boolean working) { this.working = working; } }


▶ 실행 방법: 

http://localhost8080:/spring-web01/control/controller12/ok숫자.do?파라미터명=값&파라미터명=값



블로그 이미지

필로그래머

,

 클래스의 정보 얻기



리플렉션(reflection)은 기본적으로 Java에서 클래스의 정보를 효율적으로
얻기 위해 개발된 기법입니다. 클래스의 정보를 얻는 방법부터 알아 
보겠습니다. 다음의 예제들을 살펴보겠습니다.


클래스 정보를 관리하는 도구의 종류

/* 클래스 정보를 다루는 도구 얻기 */
public class Test01 {

  public static void main(String[] args) throws Exception {
    // 1) 인스턴스를 통해서 얻기
    String obj = new String("Hello");
    Class<?> c1 = obj.getClass(); // <?> : 어떤 종류의 클래스든 다 얻어올 수 있다는 의미
    // => 인스턴스만 있으면 그 인스턴스가 어떤 클래스의 객체인지 쉽게 알아낼 수 있다.
    
    
    // 2) class.forName() 메서드를 통해서 얻기
    Class<?> c2 = Class.forName("java.lang.String"); 
    // => 아규먼트가 가리키는 문자열이 없을 수 있기 때문에 예외처리가 필요하다.
    // => 클래스 이름을 문자열로 받을 수 있기 때문에 유지보수가 쉽다.
        
    // 3) 모든 클래스에 내장된 "class" 스태틱 변수를 통해서 얻기
    Class<?> c3 = String.class;
    // => 코딩이 간편하다. 그러나 클래스 이름을 코드로 명시하기 때문에 유지보수가 어렵다.
  }

}


▶ Class 도구를 이용해 클래스의 이름 알아내기


/* Class 도구 사용법 : 클래스 이름 알아내기 */
public class Test02 {

  public static void main(String[] args) throws Exception {
    Class<?> c1 = String.class;
    
    System.out.println(c1.getName());
    System.out.println(c1.getSimpleName());
    System.out.println(c1.getCanonicalName());
  }
}

실행 결과 :
java.lang.String
String
java.lang.String



▶ Class 도구를 이용해 특정 메서드의 리턴 타입 알아내기


/* Class 도구 사용법 : 메서드의 리턴 타입 알아내기 */
import java.lang.reflect.Method;
public class Test05 {

  public static void main(String[] args) throws Exception {
    Class<?> clazz = Math.class;
    
    Method m = clazz.getMethod("sin", double.class);
    System.out.println(m);
    
    Class<?> returnType = m.getReturnType();
    System.out.println(returnType.getName());
  }
}

/*
실행 결과 : 
public static double java.lang.Math.sin(double)
double
*/



▶ Class 도구를 이용해 특정 메서드의 파라미터 타입 알아내기


/* Class 도구 사용법 : 메서드의 파라미터 타입 알아내기 */
import java.lang.reflect.Method;
public class Test06 {

  public static void main(String[] args) throws Exception {
    Class<?> clazz = Math.class;
    
    Method[] methodList = clazz.getMethods();
    for (Method m : methodList) {
      System.out.printf("%s\n", m.getName());
      Class<?>[] paramTypes = m.getParameterTypes();
      for (Class<?> paramType : paramTypes) {
        System.out.printf("--> %s \n", paramType.getName());
      }
      System.out.println();
    }
  }
}



▶ Class 도구를 이용해 메서드 호출하기


/* Class 도구 사용법 : 메서드 호출하기 import java.lang.reflect.Method; public class Test07 { public static void main(String[] args) throws Exception { // 1) 인스턴스 메서드 호출하기 String str = new String("Hello"); Class<?> clazz = String.class; Method m = clazz.getMethod("replace", char.class, char.class); Object returnValue = m.invoke(str, 'l', 'x'); System.out.println(returnValue); // 2) 클래스 메서드 호출하기 clazz = Math.class; m = clazz.getMethod("abs", int.class); returnValue = m.invoke(null, -100); // 스태틱 메서드를 호출할 때는 인스턴스를 null로 설정하라 System.out.println(returnValue); } }



Class 도구를 이용해 인스턴스 생성하기

/* Class 도구 사용법 : 인스턴스 생성하기 */
import java.lang.reflect.Method;
import java.util.Date;
public class Test08 {

  public static void main(String[] args) throws Exception {
    // Class<?> clazz = Date.class;
    Class<?> clazz = Class.forName("java.util.Date");
    Date obj = (Date)clazz.newInstance();
    System.out.println(obj);
  }
}


▶ Class 도구를 이용해 nested class 로딩하기

/* Class 도구 사용법 : nested class 로딩 */
import java.lang.reflect.Method;
import java.util.Date;
public class Test09 {

  static class My {}
  
  public static void main(String[] args) throws Exception {
    Class<?> c1 = My.class;
    Class<?> c2 = step26.Test09.My.class;
    Class<?> c3 = Class.forName("step26.Test09$My");
    
    System.out.println(c1);
    System.out.println(c2);
    System.out.println(c3);
  }
}

/*
실행 결과 :
class step26.Test09$My
class step26.Test09$My
*/


Step 1. MySuper 클래스를 정의하기

──────────────────────────────────────

public class MySuper {
  public int superPublicVar;
  String superDefaulttVar;
  protected boolean superProtectedVar;
  private float superPrivateVar;
  
  public void superPublicM() {}
  void superDefaultM() {}
  protected void superProtectedM() {}
  private void superPrivateM() {}
}



Step 2. MySuper 클래스를 상속한 MyClass 클래스 정의하기

──────────────────────────────────────

public class MyClass extends MySuper {
  public int publicVar;
  String defaultVar;
  protected boolean protectedVar;
  private float privateVar;
  
  public MyClass() {}
  public MyClass(int p1) {}
  public MyClass(String p1, int p2) {}
  
  public void publicM() {}
  void defaultM() {}
  protected void protectedM() {}
  private void privateM() {}
  
  public void m1() {}
  public void m2(int v1) {}
  public void m3(String p1, int p2) {}
}




Step 3. MyClass 클래스의 메서드를 알아내기

──────────────────────────────────────

* Class 도구 사용법 : 클래스의 메서드 알아내기 */
import java.lang.reflect.Method;
public class Test03 {

  public static void main(String[] args) throws Exception {
  // static 환경에서는 this가 없다.  
  test1();
  test2();  
  }
  
  private static void test1() throws Exception {
    Class<?> clazz = MyClass.class;
    
    Method[] methodList = clazz.getMethods(); 
    // 상속 받은 메서드를 포함하여 모든 public 메서드만 추출한다.
    for (Method m : methodList) {
      System.out.println(m.getName());
    }
  }
  
  private static void test2() throws Exception {
    Class<?> clazz = MyClass.class;
    
    Method[] methodList = clazz.getDeclaredMethods(); 
    // 해당 클래스에 선언된 모든 메서드를 추출한다. 
    for (Method m : methodList) {
      System.out.println(m.getName());
    }
  }
  
}




Step 4. MyClass 클래스의 특정 메서드만 추출하기

──────────────────────────────────────


/* Class 도구 사용법 : 클래스의 특정 메서드만 추출하기 */
import java.lang.reflect.Method;
public class Test04 {

  public static void main(String[] args) throws Exception {
    Class<?> clazz = MyClass.class;
    
    Method m = clazz.getMethod("m1");
    System.out.println(m.getName());
    
    // 일치하는 메서드를 찾지 못했을 때? null을 리턴하는 것이 아니라 예외가 발생한다.
    // m = clazz.getMethod("m1", String.class);
    // System.out.println(m);
    
    Method m2 = clazz.getMethod("m2", int.class);
    System.out.println(m2);
    
    Method m3 = clazz.getMethod("m3", String.class, int.class);
    System.out.println(m3);
  }
}
/*
실행 결과 : 
m1
public void step26.MyClass.m2(int)
public void step26.MyClass.m3(java.lang.String,int)
*/




블로그 이미지

필로그래머

,

 JSP란?


▶ JSP는 Servlet 클래스를 자동 생성할 때 참고하는 파일입니다.


▶ 자동 생성이란?
 
ex) hello.jsp --- [JSP 엔진}을 거치면 ---> hello_jsp.java(서블릿 클래스) 소스 파일 생성됩니다. 이것을 자동 생성이라 합니다.


▶ 언제 생성될까?

웹 브라우저가 요청했을 때,
- JSP에 해당하는 자바 서블릿 파일이 없으면 만듭니다.
- JSP 파일이 변경되었을 경우에 만듭니다.


▶ 자동 생성된 서블릿 파일의 위치

톰캣 서버의 경우 : $톰캣홈/work/폴더에 있습니다.
이클립스의 톰캣 임시 배치 폴더의 경우 : tmpX/work/ 폴더에 있습니다.


▶ 결론!

- 결국 JSP 파일을 가지고 서블릿 클래스를 생성합니다.

JSP가 직접 실행되는 것이 아니라 JSP로 만든 자바 서블릿 클래스가
실행되는 것입니다.

JSP가 직접 실행되지 않습니다.


▶ JSP 기술이 등장한 이유

I 서블릿에서 콘텐츠를 출력하려면 스트림 클래스를 사용하여 출력 함수를
   호출해야 하기 때문입니다.

II 자바에선 복잡한 문자열을 출력하려코드 작성이 번거로워 집니다.

II그래서 자바로 콘텐츠를 출력하는 코드를 자동으로 만들기 위해 등장하였습니다.

IV 또한 자바 언어를 모르는 사람도 쉽게 서버 프로그램을 작성할 수 있게
    도와주기 위해서 등장하였습니다.


_jspService() 메서드?

웹 브라우저에서 요청이 들어오면,
 - 서블릿 컨테이너가 service() 메서드가 호출되고
 - service() 에서 _jspService() 메서드가 호출됩니다.



참고
─ 
JSP 엔진이 JSP 파일을 가지고 서블릿 클래스를 만들 때 반드시 지켜야 하는
규칙이 있습니다.
 - javax.servlet.jsp.HttpJspPage 인터페이스를 구현해야 합니다.


 HttpJspPage 의 구성
 javax.servlet.Servlet
 ㄴ void Init(ServletConfig) - 웹어플리케이션 실행시 jspInit() 호출
 ㄴ void service(ServletRequest, ServletResponse)
 ㄴ void destroy() - 웹어플리케이션 종료시 jspDestroy() 호출
 ㄴ String getServletInfo()
 ㄴ ServletConfig getServletConfig()

 javax.servlet.jsp.JspPage extends Servlet
 ㄴ void jspInit()
 ㄴ void jspDestroy()

 javax.servlet.jsp.HttpJspPage extends JspPage
 -ㄴvoid _jspService(HttpServletRequest, HttpServletResponse)

 결국 서블릿이 되기 위해서 javax.servlet.Servlet 인터페이스를 
 구현해야 하고 JspPage, HttpJspPage의 추가된 메서드까지 구현합니다.



 JSP 구성 요소

▶ 템플릿 데이터
    - 화면에 출력할 콘텐츠
    - 아래에 지정된 문법을 제외한 JSP 파일에 작성하는 모든 텍스트는
      템플릿 데이터입니다.
    - 자바 코드 : 다음과 같이 출력문을 만듭니다.
       out.write("템플릿데이터"); 
  out.print("템플릿데이터");


▶ 스크립트릿(scriptlet) 엘리먼트
    - JSP에 자바 코드를 삽입할 때 사용합니다.
     <% 자바 코드 %>
    - JSP 엔진이 생성하는 서블릿 파일에 그대로 복사됩니다.
    - _jspService() 메서드 안에 순서대로 그대로 복사됩니다.

▶ 지시어(directive) 엘리먼트
     ▷ <%@ page %>
        language 속성 : 
          스크립트릿 등에서 사용하는 프로그래밍 언어가 무엇인지
          지정합니다. 현재 java만 지정할 수 있습니다. 
     ex) page language="java"

 contentType 속성 : 
    response.setContentType() 코드를 생성합니다.
    ex) contentType="text/html; charset=UTF-8"
 
 pageEncoding 속성 : 
    JSP 파일이 어떤 인코딩으로 저장되었는지 지정합니다.
    JSP 엔진이 JSP 파일을 읽을 때 사용합니다.
    ex) pageEncoding="UTF-8"

 trimDirectiveWhitespaces 속성 : 
    JSP 태그를 사용한 후 줄바꿈 코드가 있을 때의 제거 여부를 결정합니다.
    ex) trimDirectiveWhitespaces="true"
 
 buffer 속성 :
    출력 스트림의 기본 버퍼 크기를 지정합니다. 기본이 8kb입니다.
    ex) buffer="8kb"
 
 autoFlush 속성 :
    버퍼가 찼을 때 자동으로 출력할지의 여부를 지정합니다. 기본이 true입니다.
    ex) autoFlush="true"

 import 속성 :
    import 문을 추가할 때 사용합니다. 콤마(,)로 여러 개의 패키지를 지정할 수 
    있습니다. 또는 여러 개의 <%@ page import="..."%> 태그를 작성할 수 있습니다.
    그러나 여러 개의 import 속성을 둘 수는 없습니다.
    ex) import="java.util.ArrayList.java.net.Socket"   


     ▷ <%@ include %>
         file 속성 :
           지정된 파일을 그대로 읽어서 JSP 파일 안 include 태그가 있는 자리에
           그대로 포함시킨다. 그 후 자바 서블릿 클래스를 만든다.
           참고로 <jsp:include>는 RequestDispatcher의 include()를 호출한 것과 같다.
           지정된 파일이 JSP라면 실행할 것이고, 일반 텍스트라면 그 내용을 출력할 것이다.
           

     ▷ <%@ taglib %>
        JSP에서 기본으로 제공하지 않는, 외부에서 제공하는 태그를 사용할 때 선언합니다.
        prefix 속성 :
          외부 태그를 사용할 때 태그명 앞에 붙이는 접두어입니다. (=태그의 패키지명)
        url 속성 :
          외부 태그의 라이브러리 이름을 넣습니다. 자바의 패키지 명과는
          다르게 URL 주소 형태로 되어 있습니다. 개발자가 직접 만든 태그나
          외부에서 만든 태그를 사용하려면 /WEB-INF/classes 또는 /WEB-INF/lib에
          태그를 처리하는 라이브러리를 두어야 합니다.
       ex) <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
     
            
▶ 표현식(expression) 엘리먼트
    - 어떤 결과를 출력하는 코드를 만들고 싶을 때 사용합니다.
     <% 표현식 %>
      자바 코드 : out.println()

▶ 선언문(declaration) 엘리먼트
     - JSP 파일을 이용하여 만든 서블릿 클래스에 필드나 메서드를 추가하고        싶을 때 사용합니다.
     - <%! 자바 코드 %>
       자바 서블릿:
       class 서블릿 extends .... {
         자바 코드
       }
     - _jspService() 메서드 안에 놓여지는 것이 아니라,
       class 블록 안에 놓여집니다.
       따라서 클래스 블록 안에 작성할 수 있는 것은 모두 가능합니다.
     - 그래서 태그를 선언하는 순서는 상관 없습니다.

expression element와 declaration element의 예제

<%@ page language="java" 
contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"
    trimDirectiveWhitespaces="true"
    %>
<html>
<%! int age = 20; %>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP</title>
</head>
<body>
<%plus(10, 20); %>
10 + 20 = <%= result %><br>
</body>
</html>

<%!
int result;
void plus(int a, int b) {
    this.result = a + b;
}
%>  


▶ JSP 액션 태그
    - JSP에서 기본으로 제공하는 태그이다. 이 태그를 사용하기 위해 따로
      라이브러리를 가져오는 taglib를 선언할 필요가 없다.
  ▷ jsp:useBean
   => Serlvet 
   - id 속성 : 
     값을 보관소에 저장할 때 사용할 이름. 변수명으로도 사용합니다.
   - class 속성 : 
     변수의 타입. 보관소에 객체가 없으면 이 클래스의 인스턴스를 생성합니다. 
      import를 했는지의 여부와 상관없이 반드시 전체 클래스 이름을 적어야 합니다.
   - scope 속성 : 
     객체를 꺼내는 보관소를 가리킵니다. 기본이 pageContext입니다. 
     만약 보관소에 객체가 없다면 생성합니다.
   
  ex) <jsp:useBean id="list" class="java.util.ArrayList" scope="page">
       </jsp:useBean> 이 코드는 다음과 비슷한 자바 코드를 생성합니다.
  
   → java.util.ArrayList list = (java.util.ArrayList)pageContext.getAttribute("list");
        if (list == null) { 
          list = new java.util.ArrayList();
          pageContext.setAttribute("list", list);
        }
    
    - type 속성 :
      변수의 타입을 지정할 때 사용합니다. type 속성이 없으면 class 속성의 값이
       변수의 타입이 됩니다. 

    ▷ jsp:include
     - 다른 서블릿/JSP로 실행을 위임할 때 사용하는 태그입니다.
     - include는 RequestDispatcher.include()와 같습니다.
        ex) <jsp:include page="b.jsp"/>

     ▷ jsp:param
     - 다른 서블릿/JSP를 요청할 때 넘겨주는 파라미터 값입니다.

JSP 확장 태그(JSTL)
   - JSP에서 기본으로 제공하는 액션 태그만으로는 프로그래밍
     하기에 부족함이 많습니다. JSTL은 액션 태그에 덧붙혀 공식적으로 
     추가한 확장 태그(JSTL, JSP Standard Tag Library)입니다.
   - 이 태그를 사용하려면 이 태그를 처리하는 클래스들, 즉 JSTL 구현
     라이브러리를 다운로드 받아야 합니다. 서블릿 컨테이너가 기본으로
     제공하지 않습니다. 
   - 여러 JSTL 구현 라이브러리가 있지만, 대부분 apache.org 에서 만든
      것을 사용합니다.
   - 그리고 JSP 페이지에서 이 라이브러리를 사용하려면
      1) 웹 애플리케이션 라이브러리로 포함시켜야 합니다.
         - /WEB-INF/lib/ 폴더에 라이브러리 파일을 두어야 한다는 것입니다.
      2) JSP 페이지에서 이 라이브러리의 어떤 태그를 사용할 것인지 선언
         해야 합니다.
         - <%@ taglib %> 태그를 사용하여 라이브러리 정보를 선언해야
           쓸 수 있습니다.
           ex) <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 

   - JSTL에서 제공하는 주요 라이브러리


EL (Expression Language)
   - 보관소에서 값을 꺼낼 때 사용하는 문법입니다.
   - OGNL(Object Graph Navigation Language) 형식을 값이 들어있는
     객체의 경로로 지정합니다. 
     예) pageScope.member.name
   - EL에서 사용할 수 있는 기본 객체
     pageContext : pageContext 객체
     servletContext : servletContext 객체. 
      ex) ${pageContext.servletContext.객체명}
     session: HttpSession 객체 
      ex) ${pageContext.session.프로퍼티명}
     request: ServletRequest 객체
      ex) ${pageContext.request.프로퍼티명}
     response: ServletResponse 객체
     param: 요청 파라미터 값 조회 
      ex) ${param.파라미터명}
     paramValues: 요청 파라미터 값의 배열 조회
      ex) ${paramValues.파라미터명}
     header: HTTP 헤더 값 조회
      ex) ${header.헤더명}
     headerValues: HTTP 헤더 값의 배열을 조회
      ex) ${headerValues.헤더명}
     cookie: 쿠키 값 조회
      ex) ${cookie.쿠키명}
     pageScope: PageContext 객체
      ex) ${pageScope.프로퍼티명}
     requestScope: ServletRequest 보관소
     ex) ${requestScope.프로퍼티명}
         => ${request.servletContext} == request.getServletContext();
         => ${requestScope.servletContext} == request.getAttribute("servletContext");
     sessionScope: HttpSession 보관소
     ex) ${sessionScope.프로퍼티명}
         => ${session.creationTime} == session.getCreationTime();
         => ${sessionScope.creationTime} == session.getAttribute("creation Time");
     applicationScope: ServletContext 보관소
     ex) ${applicationScope.프로퍼티명}


JSP 주석


블로그 이미지

필로그래머

,

 쿠키(Cookie)란?


─────

웹서버가 웹브라우저에게 보내는 데이터 중의 하나입니다.
    웹브라우저는 웹서버로부터 받은 쿠키 데이터를 내부 메모리 또는 
    별도의 폴더에 저장합니다. 그리고 그 웹서버를 방문할 때마다 쿠키를 
    요청 헤더(Request Header)에 담아 다시 전달합니다.

쿠키 생성
- 쿠키의 이름은 'ISO-8859-1'이어야 합니다. 이 말은 한글이 안된다는 것이죠.
- 쿠키의 값은 'ISO-8859-1' 문자열이어야 합니다.


    만약 한글을 저장하고 싶다면?

   ▶  URL 인코딩을 하여 저장하면 됩니다.


 

───── 

쿠키의 사용 I : 쿠키 객체 생성


import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/cookieEx/Servlet01")
public class Servlet01 extends HttpServlet {
  private static final long serialVersionUID = 1L;

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) 

throws ServletException, IOException { /* 1) 쿠키 생성 */ Cookie cookie = new Cookie("c1", "aaaaaa"); /* 2) 쿠키를 응답 헤더에 포함시켜 보내기 HTTP/1.1 200 Set-Cookie: c1=aaaaaa <----- 쿠키 데이터가 이렇게 헤더에 추가됨. Content-Type: text/plain;charset=UTF-8 Content-Length: 29 Date: Mon, 12 Jun 2017 03:35:03 GMT */ resp.addCookie(cookie); resp.setContentType("text/plain;charset=UTF-8"); PrintWriter out = resp.getWriter(); out.println("Servlet01: 쿠키 보냈음."); } }



서버를 실행하고 웹브라우저 url 주소에 localhost:8080/프로젝트명/cookieEx/Servlet01 을 입력하면 쿠키가 생성되어 웹브라우저에 저장됩니다.



────

웹브라우저에 저장된 쿠키의 값을 읽기


mport java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/* 쿠키 읽기 I
 * => 웹브라우저가 보낸 쿠키 정보를 읽기
 */

@WebServlet("/cookieEx/CookieReader01")
public class CookieReader01 extends HttpServlet {
  private static final long serialVersionUID = 1L;

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
throws ServletException, IOException {
    resp.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = resp.getWriter();

    /* 1) 요청 헤더에서 쿠키 정보를 추출하기
     * => 웹브라우저가 쿠키를 보내지 않았다면, null을 리턴한다.
GET /프로젝트명/cookieEx/CookieReader01 HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) 
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,

*... Accept-Encoding: gzip, deflate, sdch, br Accept-Language: ko-KR,ko;q=0.8,en-US;q=0.6,en;q=0.4 Cookie: c1=aaaaaa <------------ 웹브라우저가 웹서버에 보내는 쿠키 데이터 */ Cookie[] cookies = req.getCookies(); // 2) 읽은 쿠기 정보 출력하기 if (cookies != null) { for (Cookie cookie : cookies) { out.printf("%s=%s\n", cookie.getName(), // 쿠키 이름 cookie.getValue()); // 쿠키 값 } } else { out.println("쿠키가 한 개도 없습니다."); } } }



서버를 실행시킨 후 웹브라우저 url 주소에 localhost:8080/프로젝트명/cookieEx/CookieReader01 을 입력하면 저장된 쿠키의 이름과 값이 출력됩니다.



───── 

쿠키의 사용 II : 사용 범위 지정


cookie.setPath(req.getContextPath());


쿠키의 사용 범위를 지정해주지 않으면 쿠키를 보낸 서블릿의 경로에

    한정됩니다. 따라서 쿠키의 사용 범위를 현재 웹 어플리케이션 전체로

    지정하고 싶다면 setPath(주소) 함수를 이용해야 합니다. 


여기서 req.getContextPath() 는 "/웹프로젝트명"과 동일합니다.





───── 

쿠키의 사용 III : 사용 기간 지정


cookie.setMaxAge(60);


쿠키의 사용 기간을 지정하지 않으면 웹브라우저가 실행되는 동안만 

    쿠키가 보관됩니다. 웹브라우저를 '모두' 닫으면 사용 기간을 지정하지

    않은 쿠키는 모두 소멸되어 버리는 것이죠.


사용 기간을 지정하면, 컴퓨터를 껐다 켜도 지정한 시간 만큼 유지할 수

    있습니다. 웹브라우저는 보낼 쿠키를 검사할 때 사용 기간이 지난 쿠키는

    제거합니다.


여기서 setMaxAge() 메서드의 파라미터로 넘어가는 값(60)의 단위는 '초'입니다.




───── 

쿠키의 사용 IV : 한글 보내는 법


Cookie cookie = new Cookie("c4", URLEncoder.encode("ABC가각간", "UTF-8"));


만약 웹서버가 유니코드를 그대로 내보내는 서버가 아니라면, 위와 같이 

    개발자가 URL 인코딩을 직접 수행해야 합니다.


▶ 한글 "가각간"을 보내주기 위해선 URLEncoder 인스턴스의 encode() 

    메서드를 사용해야 하는 것입니다. 첫번째 아규먼트로 넘겨줄 값을, 

    두번째 아규먼트로 인코딩 형식을 지정해야 하죠.


웹서버가 유니코드 값을 보내더라도 웹브라우저 중에서는 유니코드를

    처리할 수 없는 브라우저도 있기 때문에 개발자가 URL 인코딩을 해서

    보내기를 권장합니다.



왜 URL 인코딩을 해야만 하는지에 대해선 이전 글을 참고해주세요 :)


       2017/06/12 - [Programming/java] - [Java] URL 인코딩이란 무엇인가?





───── 

쿠키의 사용 V : 한글로 인코딩 된 쿠키 값을 읽기


import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/* 쿠키 읽기 III
 * => 쿠키 값이 URL 인코딩 되어 있을 때,
 *    개발자가 직접 URL 디코딩을 수행해야 한다.
 *  
 */

@WebServlet("/cookieEx/CookieReader03")
public class CookieReader03 extends HttpServlet {
  private static final long serialVersionUID = 1L;

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
throws ServletException, IOException {
    resp.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = resp.getWriter();

    Cookie[] cookies = req.getCookies();
    
    if (cookies != null) {
      for (Cookie cookie : cookies) {
        out.printf("%s=%s\n", 
            cookie.getName(),  // 쿠키 이름
            URLDecoder.decode(cookie.getValue(), "UTF-8"));  
        // 영어는 URL 디코딩해도 값이 같다. 그러니 영어를 디코딩하는 것에 대해 걱정말라!
      }
    } else {
      out.println("쿠키가 한 개도 없습니다.");
    }
  }
}


URLEncoder를 통해 인코딩 된 쿠키 데이터(한글 값)는 URLDecoder의 

    decode() 메서드를 통해 디코딩 시켜주어야 합니다. 


▶ decode() 메서드에 넣어주는 첫번째 아규먼트는 쿠키 데이터, 두번째 

   아규먼트는 디코딩 형식입니다.


영어는 URL 디코딩을 해도 값이 달라지지 않습니다. 그러니 영어를 

    디코딩하는 것에 대해선 걱정마세요 :)









블로그 이미지

필로그래머

,

 URL 인코딩

──────

 7비트만 처리할 수 있는 장비를 사용하는 경우, 8비트 데이터를 보낼 수 있게 만드는 인코딩 기술이 있습니다. 여기서 8비트 값을 7비트화 시키는 기술을 'URL 인코딩'이라고 부릅니다.

▶ 4비트 숫자를 첫 비트가 0인 8비트 숫자로 바꾸는 것이 URL 인코딩입니다.

▶ 숫자를 7비트 아스키 코드로 바꾸는 것이 URL 인코딩입니다.


 방법


보내려는 데이터가 영어 알파벳 'A'라고 가정해봅시다.

'A'의 코드 값 : 0x41 (01000001) <-- 7비트 장비를 통과하더라도 데이터를 잃지 않습니다. 7비트 장비에 통과된 값은 첫번째 비트 '0'을 제외한 1000001 이지만 데이터를 인코딩하면서 다시 맨 처음에 0 값을 추가하기 

때문이죠. 그래서 결과적으로 01000001 이 출력됩니다.



 but!

──────

한글의 경우 첫번째 비트 값이 '1'이 들어가기 때문에 7 비트 장비를 통과하면 앞자리 비트가 0으로 바뀌어 깨지게 됩니다. 

'가'의 코드 값 : 0xAC00(10101100 00000000) <-- 7비트 장비를 통과 후 00101100 0000 의 값이 출력되어 데이터가 깨집니다.




 해결


'가'의 코드 값(0xAC00)을 ASCII 코드로 문자화 시킵니다.

만약 유니코드 값을 그대로 ASCII 코드로 문자화 시킨다면,

%AC%00 : '%' -> 25 'A'- > 41 'B' -> 43 'C' -> 25 '0' -> 30 '0' -> 30이 될 것입니다. 물론 2바이트로 보내면 될 것을 ASCII 코드로 문자화 시키면 6 바이트로 보내야 합니다. 이에 따라 보내는 데이터의 크기는 커지지만 7비트 장비를 무사히 통과할 수 있습니다.



GET 또는 POST 요청을 할 때 보내는 데이터는 웹 브라우저가 자동으로 URL

인코딩을 합니다. 그 후에 서블릿 컨테이너가 자동으로 디코딩을 합니다.

개발자가 따로 인코딩/디코딩을 할 필요가 없어집니다.


 단, 쿠키로 데이터를 보낼 때는 개발자가 인코딩을 해주어야 하고,

    그것을 다시 읽을 때는 개발자가 디코딩 해주어야 합니다.


블로그 이미지

필로그래머

,

웹 어플리케이션 구성 요소


서블릿(Servlet)

 - 클라이언트 요청을 처리하는 역할을 합니다.


필터(Filter)

 - 요청 처리 전/후에 작업을 수행하는 역할을 합니다.


리스너(Listener) 

 - 특정 상태에 놓일 때 작업을 수행하는 역할을 합니다.




  먼저 Listener 리스너 예제를 보겠습니다.  



ServletContextListener?


  웹 애플리케이션이 시작되거나 종료되는 상태에 대한 작업을 수행합니다.



import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class Listener01 implements ServletContextListener {

  @Override
  public void contextInitialized(ServletContextEvent sce) {
    // ServletContext 객체가 생성되었을 때 호출된다.
    // 즉 웹 애플리케이션이 시작되었을 때 호출된다.
    System.out.println("====> Listener01.contextInitialized()");
  }

  @Override
  public void contextDestroyed(ServletContextEvent sce) {
    // ServletContext 객체가 소멸되기 직전에 호출된다.
    // 즉 웹 애플리케이션이 종료되기 직전에 호출된다.
    System.out.println("====> Listener01.contextDestroyed()");
  }

}



ServletRequestListener?


클라이언트로부터 요청이 들어오거나 서버에서 응답을 수행할 때 발생하는 

이벤트에 대한 작업을 수행합니다.



import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class Listener02 implements ServletRequestListener {
  
  @Override
  public void requestInitialized(ServletRequestEvent sce) {
    // ServletRequest 객체가 생성되었을 때 호출된다.
    // 즉 클라이언트로부터 요청이 들어 올 때 호출된다.
    System.out.println("====> Listener02.requestInitialized()");
  }

  @Override
  public void requestDestroyed(ServletRequestEvent sce) {
    // ServletRequest 객체가 소멸되기 직전에 호출된다.
    // 즉 클라이언트에게 응답했을 때 호출된다.
    System.out.println("====> Listener02.requestDestroyed()");
  }

}



ServletRequestAttributeListener?


ServletRequest 객체에 값을 저장, 제거 혹은 변경할 때 호출된다.


import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class Listener03 implements ServletRequestAttributeListener {
  
  @Override
  public void attributeAdded(ServletRequestAttributeEvent sce) {
    // ServletRequest 객체에 값을 저장할 때 호출된다.
    // 즉 req.setAttribute(...) 호출할 때
    System.out.printf("====> Listener03.attributeAdded(): %s=%s\n", 
        sce.getName(), sce.getValue());
  }

  @Override
  public void attributeRemoved(ServletRequestAttributeEvent sce) {
    // ServletRequest 객체에서 값을 제거할 때 호출된다.
    System.out.println("====> Listener03.attributeRemoved()");
  }
  
  @Override
  public void attributeReplaced(ServletRequestAttributeEvent sce) {
    // ServletRequest 객체에 저장된 값을 변경할 때 호출된다.
    System.out.println("====> Listener03.attributeReplaced()");
  }

}



서버에 add한 프로젝트 폴더의 경로를 찾아가 웹브라우저에서 url 주소를 치면

클라이언트의 요청을 인식하고 각 Listener에서 객체를 생성합니다.

이를 통해 어느 시점에서 Listener가 생성 - 소멸되는지 확인할 수 있습니다.





블로그 이미지

필로그래머

,

■ gradle 설정파일 준비하기

# gradle 빌드 도구를 실행할 때 필요한 설정 파일을 준비합니다.


cmd 명령창에서 프로젝트 폴더 경로를 찾아가 다음의 명령어를 줍니다.

> gradle init

build.gradle 등의 파일이 생성됩니다. 이제 build.gradle 설정 파일을 편집하면 됩니다.



■ gradle 사용법

## gradle에서 사용할 수 있는 도구를 확인합니다.


cmd 명령창에서 프로젝트 폴더 경로를 찾아가 다음의 명령어를 줍니다.

> gradle tasks



## gradle에 자바 빌드 도구 플러그인을 추가합니다.

[bulid.gradle 파일 txt로 열기]


apply plugin: 'java'


cmd 명령창에서 프로젝트 폴더 경로를 찾아가 다음의 명령어

> gradle tasks --all 를 주면 자바 빌드 도구 플러그인이 추가된 것을 확인할 수 있습니다.




## gradle 자바 빌드 도구 사용하기
[자바 소스 컴파일하기]

src > main > java > example > Hello.java 파일을 만들어 봅니다.


> gradle [명령(task) 이름]
> gradle compileJava

* (src/main/java/ 폴더의 모든 자바 소스 파일을 컴파일 한 후 그 결과를 build/classes/main/ 폴더에 저장한다.)

그러면 build > classes > main > example 폴더에서 컴파일된 Hello.class 파일이 
생성된 것을 확인할 수 있습니다.
실행 결과 : build/classes/main/example/Hello.class 파일 생성


[빌드 관련 모든 폴더와 파일 제거하기]
> gradle clean

실행 결과 : build 폴더가 제거됩니다.



[resources 폴더 파일을 빌드 폴더에 복사하기]

> gradle processResources


* (src/main/resources/ 폴더의 모든 파일이 build/resources/main/ 폴더에 복사된다.)


실행 결과 : build/resources/main/beans.properties  파일 생성


[compileJava 기능 + proccessResources 기능 = classes]

> gradle classes


실행 결과 : CompileJava와 processResources 명령을 모두 실행한 결과와 같다.


[JAR 배포 파일 만들기]
> gradle jar

실행 결과 : classes 명령을 실행한 후 .jar 파일을 생성한다.



[빌드 전 과정을 실행하기]

> gradle build


실행 결과 : 컴파일 ---> 단위 테스트 ---> JAR 파일 생성 등 빌드 전과정을 실행한다.



Java plugin - tasks





## gradle에 이클립스 빌드 도구 플러그인을 추가합니다.

[bulid.gradle 파일 txt로 열기]


apply plugin: 'eclipse'



[이클립스 프로젝트 설정 파일 삭제하기]
> gradle cleanEclipseProject

실행 결과 : .project 파일만 제거한다.



[이클립스 관련 모든 설정 파일 만들기]
> gradle eclipse

실행 결과 : 
플러그인이 있다면 그 플러그인과 관련된 설정 파일도 만든다.
만약 따로 플러그인이 등록되지 않았다면 .project 파일만 생성될 것이다,.



[이클립스 관련 모든 설정 파일 삭제하기]
> gradle cleanEclipse

실행 결과 : 
플러그인이 있다면 그 플러그인과 관련된 설정 파일도 제거한다.
만약 따로 플러그인이 등록되지 않았다면 .project 파일만 삭제될 것이다,.



## 웹 프로젝트 만들기

[웹 관련 플러그인 등록]

[build.gradle]


apply plugin: 'eclipse-wtp'


 > 이클립스 설정 파일을 다루는 도구

 > 웹 관련 설정 파일을 다루는 도구가 들어 있는 플러그인


apply plugin: 'war'


 > WebArchive 배포 파일을 만드는 도구가 들어 있는 플러그인




블로그 이미지

필로그래머

,