package com.fastcampus.ch2;

import java.io.IOException;

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

public class HelloServlet extends HttpServlet{

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO Auto-generated method stub
		super.service(req, resp);
	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		super.destroy();
	}

	@Override
	public void init() throws ServletException {
		// TODO Auto-generated method stub
		super.init();
	}

}

 

 

호출이 언제 되는지 확인

package com.fastcampus.ch2;

import java.io.IOException;

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

@WebServlet("/hello")
public class HelloServlet extends HttpServlet{

	@Override
	public void init() throws ServletException {
		// 서블릿이 초기화 될 때 자동 호출되는 메서드
		// 1. 서블릿의 초기화 작업 담당
		System.out.println("[HelloServlet] init() is called");
	}
	
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("[HelloServlet] service() is called");
	}

	@Override
	public void destroy() {
		System.out.println("[HelloServlet] destroy() is called");
	}

	

}

 

init은 처음에만 호출되고 새로고침하면 service는 계속 호출된다.

 

 

코드를 수정하고 저장하면 재시작 되므로

destroy가 호출됨

 

 

 

JSP

 

 

 

<%@ page contentType="text/html;charset=utf-8"%>
<%@ page import="java.util.Random" %>
<%-- <%! 클래스 영역 %> --%>
<%!  
	int getRandomInt(int range){
		return new Random().nextInt(range)+1;
	}
%>
<%-- <%  메서드 영역 - service()의 내부 %> --%>
<%
	int idx1 = getRandomInt(6);
	int idx2 = getRandomInt(6);
%>
<html>
<head>
	<title>twoDice.jsp</title>
</head>
<body>
	<img src='resources/img/dice<%=idx1%>.jpg'>
	<img src='resources/img/dice<%=idx2%>.jpg'>
</body>
</html>

 

별도로 매핑해주지 않아도 jsp는 자동으로 매핑이 된다.

 

 

 

 

서블릿 : lazy-init

spring : early-init

 

 

서비스 메서드에 기본으로 생성되어 있는 것들은 사용가능

package com.fastcampus.ch2;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.StringJoiner;

public class MethodInfo {
	public static void main(String[] args) throws Exception{

		// 1. YoilTeller 클래스의 객체를 생성
		Class clazz = Class.forName("com.fastcampus.ch2.YoilTeller");
		Object obj = clazz.newInstance();
		
		// 2. 모든 메서드 정보를 가져와서 배열에 저장
		Method[] methodArr = clazz.getDeclaredMethods();
		
		for(Method m : methodArr) {
			String name = m.getName(); // 메서드의 이름
			Parameter[] paramArr = m.getParameters(); // 매개변수 목록
//			Class[] paramTypeArr = m.getParameterTypes(); // 반환 타입
			Class returnType = m.getReturnType();
			
			StringJoiner paramList = new StringJoiner(", ", "(", ")"); // 구분자, 접두사, 접미사
			
			for(Parameter param : paramArr) {
				String paramName = param.getName();
				Class  paramType = param.getType();
				
				paramList.add(paramType.getName() + " " + paramName);
			}
			
			System.out.printf("%s %s%s%n", returnType.getName(), name, paramList);
		}
	} // main
}

 

 

 

 

 

매개변수의 이름을 저장하지 않아서 arg0으로 출력됌

 

메서드의 매개변수 이름이 필요하기 때문에 컴파일러 옵션에 parameters를 준다.(매개변수 이름을 저장)

JDK 1.8부터 추가되었다.

 

Window - Preferences

 

 

다시 실행해도 파라미터가 나오지 않는 것은 1.6버전이기 때문이다.

 

자바의 버전을 변경하기 위해 pom.xml 로 들어가서 수정

버전 복사

 

아래로 내려서 plugin도 변경해준다.

${java-version} 대신에 직접 11버전이면 11을 입력해줘도 되지만 위에 프로퍼티에 버전이 언제든지 바뀌면

따로 수정하지 않아도 되므로 문자열로 이렇게 받도록 수정해주는 것이다.

 

 

메이븐을 사용중이므로 업데이트 프로젝트를 해주어야 한다.

 

 

재실행을 해보면 이제 매개변수의 이름이 출력되었다.

 

 

Window - Show View - Other

탐색기라고 생각하면 된다.

 

이번엔 YolilTellerMVC이 매개변수를 출력해보았다.

 

메서드의 진행 방향과 인스턴스의 생성과정

 

다른 예제를 가져왔다.

 

package com.fastcampus.ch2;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;

class ModelController {
	public String main(HashMap map) {
		// 작업 결과를 map에 저장
		map.put("id", "asdf");
		map.put("pwd", "1111");
		
		return "txtView2"; // 뷰이름을 반환
	}
}

public class MethodCall {
	public static void main(String[] args) throws Exception{
		HashMap map = new HashMap();
		System.out.println("before:"+map);

		ModelController mc = new ModelController();
		String viewName = mc.main(map);
		
		System.out.println("after :"+map);
		
		render(map, viewName);
	}
	
	static void render(HashMap map, String viewName) throws IOException {
		String result = "";
		
		// 1. 뷰의 내용을 한줄씩 읽어서 하나의 문자열로 만든다.
		Scanner sc = new Scanner(new File(viewName+".txt"));
		
		while(sc.hasNextLine())
			result += sc.nextLine()+ System.lineSeparator();
		
		// 2. map에 담긴 key를 하나씩 읽어서 template의 ${key}를 value바꾼다.
		Iterator it = map.keySet().iterator();
		
		while(it.hasNext()) {
			String key = (String)it.next();

			// 3. replace()로 key를 value 치환한다.
			result = result.replace("${"+key+"}", (String)map.get(key));
		}
		
		// 4.렌더링 결과를 출력한다.
		System.out.println(result);
	}
}

 

 

실행을 해봤는 txtView2.txt 가 없어서 에러가 났다.

 

ch2우 클릭후 new - file

 

viewTxt1.txt

 

viewTxt2.txt

 

다시 MethodCall을 실행

현재 view2를 출력하여서 이렇게 출력된 것이고 view1로 바꾼다면 이렇게 출력된다.

기존에 있던 YoilTeller를 복붙하고 이름 변경

 

 

 

입력부분을 주석처리 그리고 직접 입력받게 할 것이다.

 

작업 부분도 직업 int형으로 받으면 되기 때문에 주석처리

 

url매핑도 중복되면 안되므로

getYoil 에서 getYoilMVC로 변경

 

관심사 분리전이랑 똑같은 결과

 

출력부분도 별도의 jsp파일로 빼낼 수 있으므로 주석처리

대신 별도의 jsp를 만들어야한다.

기존에 있던 home.jsp를 복사한 후 이름을 변경해서 yoil.jsp 와 yoilError.jsp생성

 

바디 부분을 수정하고 저장하려니 오류가 났다.

인코딩 문제라 첫줄에 인코딩 방식추가

혹은 에러가 난 부분을 지우고 다시 붙여넣기 한 후 저장하면 에러가 해결되는 경우도 있다고 한다.

 

yoil.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
	<title>Home</title>
</head>
<body>
<P> ${year }년 ${month }월 ${day }일은 ${yoil }입니다. </P>
</body>
</html>

 

혹은 Save as UTF-8 클릭

 

yoilError.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
	<title>Home</title>
</head>
<body>
<h1>
	잘못된 요청입니다. 년, 월, 일을 모두 올바르게 입력해주세요.
</h1>


</body>
</html>

 

 

다시 yoilTellerMVC로 돌아감.

 

입력같이 틀린경우 yoilError를 출력해야하니 유효성 검사에 추가

 

 

별도의 메서드로 뽑아낼 수 있다.

드래그 후 우클릭 Refactor - Extract Method

 

메서드의 이름은 getYoil

private으로 메서드가 생겼는데 좀 수정해야 한다.

 

 

 

isVaild도 클릭후 자동으로 메서드 생성 클릭

 

 

위에 valid메서드에 false라고 되어있기에 이렇게 나오는데 true로 변경

 

컨트롤러가 작업한 것이 뷰에 잘 적용되지 않아서 숫자가 입력되지 않음.

 

모델로 변경

그후 모델에 저장하면 잘 출력됌

 

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.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class YoilTellerMVC { // http://localhost:8080/app/getYoilMVC?year=2024&month=11&day=1
	@RequestMapping("/getYoilMVC")
//	public void main(HttpServletRequest request, HttpServletResponse response) throws IOException {
	public String main(int year, int month, int day, Model model) throws IOException {
		// TODO Auto-generated method stub
		
		// 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);
		
		// 1. 유효성 검사
		if(!isValid(year, month, day))
			return "yoilError";
		
		// 2. 요일 계산
		char yoil = getYoil(year, month, day);
		
		
		//3. 계산한 결과를 model에 저장
		model.addAttribute("year", year);
		model.addAttribute("month", month);
		model.addAttribute("day", day);
		model.addAttribute("yoil", yoil);
		
		return "yoil";// WEB-INF/views/yoil.jsp
		// 3. 출력
//		response.setContentType("text/html");//텍스트 인지 알려주고
//		response.setCharacterEncoding("utf-8"); //인코딩 방식을 알려주어야 한다.
//		PrintWriter out = response.getWriter(); // response객체에서 브라우저로 출력 스트림을 얻는다.
//		out.println(year + "년" + month + "월" + day + "일은");
//		out.println(yoil + "요일입니다");
		
	}

private boolean isValid(int year, int month, int day) {
	// TODO Auto-generated method stub
	return true;
}

private char getYoil(int year, int month, int day) {
	Calendar cal = Calendar.getInstance(); //날짜 셋팅
	cal.set(year, month-1, day);
	
	int dayOfweek = cal.get(Calendar.DAY_OF_WEEK); //1:일요일, 2:월요일 ...
	return " 일월화수목금토".charAt(dayOfweek); //다시 문자열로 변환
}

}

 

 

 

view의 경로를 담당하는 부분 servlet-context.xml

 

 

반환타입을 void로 하면 매핑된 주소로 이동된다.

 

모델과 뷰를 한번에도 볼 수 있다.

 

 

결론

 

 

+ Recent posts