'스프링 프레임워크' 태그의 글 목록 :: 잡다한 프로그래밍
반응형

1. Data Access Layer

DB에 접근하기 위해 다음 그림과 같이 DAO는 JDBC Template에 이는 JDBC Driver를 통해 Database에 접근하고 DataSource를 이용하여 DB에 실질적으로 커넥션 한다.


2. Data Source

데이터 베이스에 접근하기 위해 DataSource를 사용한다 DataSource의 종류는 다양하지만 DBCP라이브러리의 BasicDataSource를 통상 많이 사용하므로 실습에서도 이를 사용할 예정이다.


3. DAO란?

Data Access Object의 약자로서 서비스는 DB에 대해 아무것도 모르고, 실질적으로 DB에 접근하는 오브젝트를 의미한다. 쉽게 생각하여 DB의 CRUD를 실질적으로 수행하는 코드가 담긴 부분이다.


4. JDBC란?

JDBC란 DB와의 커넥션, SQL 사용, Close 커넥션 등 잡다한 일들을 해주는 프레임 워크이다. 기본 JAVA JDBC는 커넥션 등 try catch의 반복으로 반복적인 코드를 짜야하지만 Spring JDBC를 사용하면 SQL만 코드를 작성하고 나머지는 Spring 프레임워크에서 담당한다.


5. 실습하기

#1) 사전 준비

  • Mysql 5.7.28 설치

Mysql내부에는 csemall라는 DB, offers라는 테이블을 만들고 다음과 같은 구조로 이루어져 있다.

id(INT) name email text
1 Alice Alice@google.com alice
2 Bob Bob@google.com bob
3 Jun Jun@google.com jun

 

#2) Simple Spring Maven 프로젝트 실행

다음과 같은 helloDB프로젝트를 생성한다.

 

#3) pom.xml 수정

다음과 같은 dependency를 추가하고 저장을 누르면 maven에 라이브러리가 추가된 것을 확인할 수 있다.

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.38</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>4.1.4.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.4</version>
		</dependency>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-dbcp2</artifactId>
			<version>2.1.1</version>
		</dependency>

 

#4) jdbc.properties 생성

props라는 패키지를 생성하고 그 밑에 jdbc.properties라는 파일을 생성한다. 파일 내부는 다음과 같다 이는 DB의 정보를 담고 있으며, 생성할 bean에 하드 코딩하는 것보다 좋은 방법이다.

jdbc.username = root
jdbc.password = 사용자 비밀번호를 입력
jdbc.driverClassName = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/csemall

 

#5) beans.xml 생성

다음과 같이 beans.xml을 생성한다 context:annotation은 DAO클래스에서 사용할 @Autowired를 활성화한다는 의미이며 context:component는 @Component 에노 테이션이 있는 어떤 패키지를 scan 할 건지 명시하는 부분이다. bean으로 생성한 dataSource는 #4에서 생성한 jdbc.properties를 사용하여 실제 DB와 커넥션을 하는 부분이다 dbcp2의 BasicDataSource클래스를 사용하고 있고 이 클래스는 DataSource인터페이스를 따르는 클래스이다. 마지막으로 context:property-placeholder는 앞서 사용할 jdbc.properties가 어떤 위치에 있는지 명시하는 부분이다.

<?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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
	
	<context:annotation-config></context:annotation-config>
	<context:component-scan base-package="csemall"></context:component-scan>

	<bean id="dataSource"
		class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
		<property name="driverClassName"
			value="${jdbc.driverClassName}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
	</bean>


	<context:property-placeholder
		location="kr/ac/hansung/spring/props/jdbc.properties" />

</beans>

 

#6) OfferDAO 클래스 생성

src/main/java아래의 csemall이라는 패키지를 만들고 다음과 같은 Class를 생성한다. @Component 에노테이션은 이 클래스는 id가 offerDAO라는 bean을 하나 생성하겠다는 의미이다. 또한 JdbcTemplate를 사용하여 bean에 생성한 dataSource를 주입(@Autowired)시켜 DB와 실질적인 커넥션을 해주는 부분이 담겨있다. getRowCount() 부분은 다음과 같은 sql을 query 하고 결과는 Integer로 받는다는 의미이다.

package csemall;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

@Component("offerDAO")
public class OfferDAO {
	private JdbcTemplate jdbcTemplateObject; //얘는 new를 사용해됨 이후 DataSource는 DI를 통해 주입 시킬예정	

	@Autowired
	public void setDataSource(DataSource dataSource) { //DataSource는 인터페이스인데 우리가 앞서 bean에 선언한 datasource가 이 인터페이스를 따르고 DI한다
		this.jdbcTemplateObject = new JdbcTemplate(dataSource);
	}
	
	public int getRowCount() {
		String sqlStatement = "select count(*) from offers";
		return jdbcTemplateObject.queryForObject(sqlStatement, Integer.class);
	}
}

 

#6) Offer.java 클래스 생성

Lombok을 이용해 @Getter, @Setter를 생성하였고 DB에 저장된 id, name, email, text를 받는다. 이는 추후에 사용될 클래스이다.

package csemall;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class Offer {
	private int id;
	private String name;
	private String email;
	private String text;
	
	public Offer() {
		
	}

	public Offer(String name, String email, String text) {
		this.name = name;
		this.email = email;
		this.text = text;
	}
	
	public Offer(int id, String name, String email, String text) {
		this.id = id;
		this.name = name;
		this.email = email;
		this.text = text;
	}
}

 

#7) MainApp.java 클래스 생성

다음과 같이 코드를 작성한다 ClassPathXmlApplicationContext를 이용하여 beans.xml을 읽어오고 읽어온 context의 offerDAO라는 빈을 이용하여 getRowCount() 함수를 출력한다

package csemall;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {

	public static void main(String[] args) {
		ClassPathXmlApplicationContext context =
				new ClassPathXmlApplicationContext("kr/ac/hansung/spring/csemall/beans/beans.xml");
		
		OfferDAO offerDAO = (OfferDAO) context.getBean("offerDAO");
		System.out.println(offerDAO.getRowCount());
		
		context.close();
	}

}

 

#8) 실행화면

MainApp.java를 실행하면 다음과 같은 결과를 확인 할 수 있다.

반응형
반응형

1. AOP란?

만약 다음과 같이 Bean으로 만들 클래스 내부에 로깅, 트랜잭션, 실제 코드인 비즈니스 로직이 함께 있다고 생각해보자. 로깅, 트랜잭션, 비즈니스 로직 순서대로 작동하겠지만 이는 좋은 코드라고 할 수 없다. 따라서 로깅, 트랜잭션과 비즈니스 로직을 분리하기 위해 AOP가 존재한다

Bank 클래스

AOP는 다음 그림처럼 선처리, 후처리(런타임시 짜집기함)를 가능하게 지원하기 때문에 메인 Bean을 만드는 클래스를 따로 두고 로깅, 트랜잭션을 선처리 후처리로 다음과 같은 구조를 만드는 것이다.

 

다음 그림처럼 a.f()가 실직적인 타겟이되는 joinpoint가 되고 그림 앞에 보라색, 주황색이 선처리 후처리를 담당하는 어드바이스가 된다. 어드바이스는 joinpoint는 Pointcut이 가리키게 된다

다음 그림을 보면 조금더 이해하기 쉽다

AOP 구조 설명


2. AOP실습

#1) spring-aspect를 이용한 실습

1. pom.xml dependency추가

다음과 같은 디펜던시를 추가하면, Maven Dependencies에 spring-aspects라이브러리가 추가된 것을 확인할 수 있다.

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aspects</artifactId>
			<version>4.2.5.RELEASE</version>
		</dependency>

 

2. Logger 클래스 추가

다음과 같은 Logger클래스를 추가한다.

public class Logger{
	public void aboutToSound() {
		System.out.println("Before: about to sound");
	}
}

 

3. animal.xml Namespaces 수정 및 aop추가

다음과 같이 Namespaces에 aop를 추가한다

aop 추가

aop추가를 완료하였다면 다음과 같은 코드를 추가한다 <aop:aspect ref="Logger">를 통해 Logger클래스를 Aspect로 이용하겠다는 의미이며, <aop:pointcut expression="execution(void kr.ac.hansung.helloDI.*.sound())" id="selectSound" />를 통해 helloDI패키지의 sound() 함수를 joinpoint로 지정하겠다는 의미이다. 이때 *은 와일드카드로서 어떤 클래스든 상관없다는 의미를 가진다. <aop:before method="aboutToSound" pointcut-ref="selectSound" />는 before어드바이스를 추가하겠다는 의미로 aboutToSound라는 메서드를 이용하며 ref로는 위에 선언한 pointcut의 id를 가진다. 따라서 pointcut은 jointpoint를 가르키고 advice는 그 pointcut을 가리킨다

	<aop:config>
		<aop:aspect ref="Logger" id="myAspect">
			<aop:pointcut
				expression="execution(void kr.ac.hansung.helloDI.*.sound())"
				id="selectSound" />
			<aop:before method="aboutToSound"
				pointcut-ref="selectSound" />
		</aop:aspect>
	</aop:config>

 

4. 실행

메인 함수를 실행하면 다음과 같은 결과를 확인할 수 있다. 메인 함수에서는 Logger빈을 사용하지 않았지만 다음과 같이 before advice가 실행된 것을 확인할 수 있다.

실행

 

#2) AOP 에노테이션을 이용한 실습

1. animal.xml수정

다음과 같이 animal.xml을 수정한다 기존 코드를 주석 처리하고 <aop:aspectj-autoproxy>를 추가함으로 에노테이션을 사용하겠다고 명시한다.

<!-- 	<aop:config>
		<aop:aspect ref="Logger" id="myAspect">
			<aop:pointcut
				expression="execution(void kr.ac.hansung.helloDI.*.sound())"
				id="selectSound" />
			<aop:before method="aboutToSound"
				pointcut-ref="selectSound" />
		</aop:aspect>
	</aop:config> -->

	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

 

2. Logger 클래스 수정

다음과 같이 Logger 클래스를 수정한다 @Aspect로 클래스가 Aspect라는 걸 명시하고 @Pointcut을 통해 sound() 메서드를 joinpoint로 지정하겠다는 것을 명시하고 @Before로 이전 어드바이스를 추가한다.

@Aspect
public class Logger{
	
	@Pointcut("execution(void kr.ac.hansung.helloDI.*.sound()")
	private void selectSound() {}
	
	@Before("selectSound()")
	public void aboutToSound() {
		System.out.println("Before: about to sound");
	}
}

 

3. 실행

모두 완료하였다면 다음과 같은 실행화면을 볼 수 있다

실행화면

반응형
반응형

1. DI(Dependency Injection)란?

DI는 말 그대로 의존성을 주입한다 라는 뜻이다. 쉽게 설명하면 JAVA에서 객체를 new를 이용하여 생성하는데 이렇게 사용하지 않고 외부에서 생성한 객체를 세터 또는 생성자를 통해 사용하겠다는 의미이다. 이를 의존성 주입이라 한다. 의존성 주입 방법에는 세터를 이용하거나 생성자를 이용한 방법 두가지가 있다. 예제로는 생성자를 이용한 방법으로 예제를 공부하겠다

DI 사용하지 않은 예시

그림처럼 DI를 이용하지 않고 new를 사용하여 객체를 생성하게 되면 PetOwner와 Dog간 강한 결합이 생기게 되어 도그를 수정하면 PetOwner가 수정될 수 있다.

 

DI

반면 다음과 같이 Bean Container를 이용하여 객체를 생성하고 의존성 주입을 시켜주면 결합이 강하지 않다는 장점이 생긴다. 이때 Bean Container는 XML로 이루어져 있다.

DI 설명

다음 그림처럼 메인함수에서는 ApplicationContext라는 BeanContainer를 생성하고 미리 작성된 xml에 따라 ApplicationContext는 Dog, Cat, PetOwner라는 객체를 생성하고 Dog, Cat을 PetOwner에 의존성 주입한다. 스프링은 new방식 대신 DI방식을 권장한다.


2. 의존성 주입 실습

#1 프로젝트 생성

File > New > Spring Legacy Project를 클릭하고 다음과 같은 Simple Spring Maven 프로젝트를 생성한다. 프로젝트명은 원하는 프로젝트명을 사용해도 무방하다. 이 실습에서는 helloDI라는 프로젝트명을 사용하겠다.

프로젝트 생성

#2 AnimalType, Cat, Dog 생성하기

src/main/java에 클래스와 인터페이스를 담을 패키지를 생성한다 패키지명은 자유로워도 좋다. 패키지를 생성하였다면 패키지 아래에 AnimalType.java라는 인터페이스를 생성한다

인터페이스 코드는 다음과 같다 인터페이스를 implements할 cat, dog클래스들이 사용할 sound라는 메소드를 정의하고 있다.

 

AnimalType.java

package kr.ac.hansung.helloDI;

public interface AnimalType {

	public void sound();

}

 

다음으로 Cat.java라는 클래스를 생성한다. 게터와 세터가 만들어져 있으며 AnimalType의 sound메소드를 사용하고 있다.

 

Cat.java

package kr.ac.hansung.helloDI;

public class Cat implements AnimalType {

	public String getMyName() {
		return myName;
	}

	public void setMyName(String myName) {
		this.myName = myName;
	}

	private String myName;

	@Override
	public void sound() {
		
		System.out.println("Cat name = " + myName + ":" + "Meow");
	}

}

 

마지막으로 Dog.java라는 클래스를 생성한다. 게터와 세터가 만들어져 있으며 AnimalType의 sound메소드를 사용하고 있다.

 

Dog.java

package kr.ac.hansung.helloDI;

public class Dog implements AnimalType {

	public String getMyName() {
		return myName;
	}

	public void setMyName(String myName) {
		this.myName = myName;
	}

	private String myName;

	@Override
	public void sound() {
		
		System.out.println("Dog name = " + myName + ":" + "Bow Wow");
	}

}

 

#3 PetOwner클래스 생성하기

petOwner클래스는 AnimalType의 animal을 받는다 이는 cat이나 dog를 받아서 사용하겠다는 의미이고 play라는 메소드와 생성자를 정의했다.

 

PetOWner.java

package kr.ac.hansung.helloDI;

public class PetOwner {

		private AnimalType animal;

		public PetOwner(AnimalType animal) {
			this.animal = animal;
		}
		
		public void play() {
			
			animal.sound();
		
		}
}

 

#4 animal.xml 생성하기

Bean Container가 생성하기 위해 참고할 xml파일을 생성한다 코드는 다음가 같다.

<bean id = "dog"> 부분이 dog라는 클래스의 객체를, <bean id = "cat"> 부분이 cat이라는 클래스의 객체를 <bean id = petOwner"> 부분이 petOwner의 객체를 생성하고 <constructor-arg ref = "dog">는 dog객체를 의존성 주입하겠다 라는 의미이며, <property name="myName" value="poddle">는 도그의 myName의 값을 poodle로 주겠다는 의미이다.

 

animal.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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
	<bean id="dog" class="kr.ac.hansung.helloDI.Dog">
		<property name="myName" value="poodle"></property>
	</bean>

	<bean id="cat" class="kr.ac.hansung.helloDI.Cat">
		<property name="myName" value="bella"></property>
	</bean>

	<bean id="petOwner" class="kr.ac.hansung.helloDI.PetOwner">
		<constructor-arg ref="dog"></constructor-arg>
	</bean>
</beans>

 

#5 MainApp.java작성

마지막으로 메인 함수인 MainApp.java를 다음과 같이 작성한다. ApplicationContext가 animal.xml을 바라보게 하고

petOwner의 person이 context의 getBean함수를 통해 객체를 가져와 사용하는 모습이다.

package kr.ac.hansung.helloDI;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {

	public static void main(String[] args) {

		ClassPathXmlApplicationContext context = 
				new ClassPathXmlApplicationContext("/kr/ac/hansung/helloDI/conf/animal.xml");
		
		PetOwner person = (PetOwner) context.getBean("petOwner");
		person.play();
		
		context.close();
	}

}

 

#5 프로젝트 Run

프로젝트를 Run 하게 되면 다음과 같은 결과를 확인할 수 있다.

결과화면

 

사용자는 animal.xml에서 정의한 대로 dog, cat, petOwner의 객체를 먼저 생성하고, 이후 dog를 petOwner에 주입하였으니 결과 화면에는 dog가 보이게 된다 만약 cat을 주입하고 싶다면 constructor-arg의 ref = cat으로 수정해주면 된다

반응형
반응형

1. MVC 아키텍처란?

  • Model(Java Beans) 객체로 생각, 데이터를 나타냄
  • View (JSP) 사용자가 상태를 볼 수 있는 View page를 의미
  • Controller (Servlet) 뷰와 모델 사이에서 실질적으로 request를 처리하는 부분

MVC패턴

그림과 같은 MVC패턴은 다음과 같은 5가지 단계로 진행된다

1) 브라우저의 request를 Servlet으로 전달함

2) 객체를 생성하여 서블릿의 결과를 저장함

3) view페이지를 선택함

4) JSP 페이지에 객체를 전달함

5) JSP 페이지를 브라우저에 Response 함


2. MVC 패턴 실습하기

MVC패턴을 실제 프로젝트로 실습해 보자.

 

#1 프로젝트 생성

https://diqmwl-programming.tistory.com/18?category=740999의 프로젝트 생성 부분을 참고하여 MVCexample이라는 프로젝트를 생성한다

 

#2 index.jsp생성

다음 그림과 같이 WebContent폴더에 index.jsp를 생성한다

index.jsp생성

 

생성한 index.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 http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>MVC Example</title>
</head>
<body>
MVC 예제 페이지 입니다.
	<p><a href="/MVCexample/home?action=login"> 로그인하기 </a></p>
	<p><a href="/MVCexample/home?action=help"> 도움말 </a></p>

</body>
</html>

 

코드를 생성하고 프로젝트를 실행한다면 index.jsp는 다음과 같이 실행된다.

index.jsp 실행

 

#3 Home 서블릿 생성

파일 작성을 완료하였다면 로그인하기, 도움말의 링크를 처리하기 위한 Home이라는 Servlet을 생성하기 위해 MVCeample >> Java Resources >> src >> controller라는 패키지를 생성한다.

패키지 생성을 완료하였다면 아래 그림과 같이 Home이라는 Servlet을 생성한다

서블릿 생성 1

 

index.jsp의 링크가 home으로 되어있으므로 URL Mapping을 다음과 같이 /home로 수정한다

서블릿 생성 2
서블릿 생성 3

서블릿 생성이 완료되었다면 다음과 같이 코드를 작성한다.

코드를 살펴보면 action이라고 request 받은 데이터를 String action에 저장하고 이 값이 login일 경우 view폴더의 loginform.jsp를, help일 경우 help.jsp, 이외의 경우는 error.jsp를 경로로 저장하게 된다.

이후 RequestDispatcher을 이용하여 설정한 경로로 forward 시켜주는 방식이다

package controller;

import java.io.IOException;

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

/**
 * Servlet implementation class Home
 */
@WebServlet("/home")
public class Home extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public Home() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		String action = request.getParameter("action");
		String page = null;
		
		if(action.equals("login")) {
			page = "/view/loginform.jsp";
		}
		else if(action.equals("help")) {
			page = "/view/help.jsp";
		}
		else {
			page = "/view/error.jsp";
		}
		
		RequestDispatcher dispatcher = request.getRequestDispatcher(page);
		dispatcher.forward(request, response);
	}

}

 

#4 view폴더, loginform.jsp, help.jsp error.jsp 생성

코드를 작성하고 현재 view 폴더와 loginform.jsp, help.jsp, error.jsp를 만들지 않았으므로 생성해주도록 한다.

먼저 WebContent 아래에 view라는 폴더를 생성시킨다. 이후 아래 그림처럼 loginform.jsp, help.jsp, error.jsp를 생성하고 다음과 같은 코드를 작성한다

view 폴더 구성

loginform.jsp

//loginform.jsp
<%@ page language="java" contentType="text/html; charset=US-ASCII" pageEncoding="US-ASCII"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Insert title here</title>
</head>
<body>
This is Login Page.

<form action="/MVCexample/doLogin" method="get">
	customer ID(id1, id2, id3, id4, id5)<br/>
	<input type="text" name="customerId"/> <br/>
	
	<input type="submit" value="submit"/> <br/>
</form>
</body>
</html>

 

help.jsp

<%@ page language="java" contentType="text/html; charset=US-ASCII" pageEncoding="US-ASCII"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Insert title here</title>
</head>
<body>
This is help Page.
</body>
</html>

 

error.jsp

<%@ page language="java" contentType="text/html; charset=US-ASCII" pageEncoding="US-ASCII"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Insert title here</title>
</head>
<body>
This is error Page.
</body>
</html>

모두 작성을 완료하였다면 index.jsp에서 링크를 클릭 시 다음과 같이 forward 된 것을 확인할 수 있다.

loginform.jsp

 

#5 Model 작성

loginform에서 사용자가 입력하는 id의 실질적인 객체를 만들기 위해 Model을 생성한다 먼저 MVCexample >> Java Resources >> src >> model 패키지를 생성한다. 이후 아래 사진과 같이 Customer 클래스를 생성한다

 

model 생성

생성한 Class의 코드는 다음과 같다 id, name, email을 가지고 있으며 Customer이라는 생성자와, 각각의 게터, 세터 메소드가 정의되어있다.

package model;

public class Customer {

	private String id;
	private String name;
	private String email;
	
	public Customer(String id, String name, String email) {
		this.id = id;
		this.name = name;
		this.email = email;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}
	
}

 

#6 Service 생성

실제로 만든 모델에 데이터를 저장하거나, 데이터를 읽어오거나 하는 함수들이 정의된 서비스이다. 사용자의 요청이 들어왔을 때 서블릿에서 이를 처리하는 함수를 구현해도 상관없으나 Service로 분리하여 보다 보기 좋은 코드를 구현한다

model 생성과 같은 방법으로 MVCexample >> Java Resources >> src >> service 패키지를 생성한다. 이후 다음 그림처럼 CustomerService 클래스를 생성한다

service 생성

실제 코드는 다음과 같다. 먼저 CustomerService를 생성하면 customers라는 Map을 생성한다 이때 String은 id, 값으로는 Customer 모델을 받고 customers 객체가 생성될 때 id1~id5의 정보를 미리 저장해 놓는다. 또한 DoLogin 서블릿에서 사용할 findCustomer함수를 정의한다 이는 검색한 아이디가 있을 경우 id의 cusomer을 반환하고 없을 경우 null을 반환한다.

 

package service;

import java.util.HashMap;
import java.util.Map;

import model.Customer;

public class CustomerService {
	
	private Map<String, Customer> customers;

	public CustomerService() {
		customers = new HashMap<String, Customer>();
		
		addCustomer( new Customer("id1", "test1", "test1@naver.com"));
		addCustomer( new Customer("id2", "test2", "test2@naver.com"));
		addCustomer( new Customer("id3", "test3", "test3@naver.com"));
		addCustomer( new Customer("id4", "test4", "test4@naver.com"));
		addCustomer( new Customer("id5", "test5", "test5@naver.com"));
	}
	
	public void addCustomer(Customer customer) {
		customers.put(customer.getId(), customer);
	}
	
	public Customer findCustomer(String id) {
		if(id != null) {
			return (customers.get(id.toLowerCase()));
		}
		else{
			return null;
		}
	}
	
}

 

#6 DoLogin 서블릿 작성

loginform.jsp에서 사용자가 정해진 id를 입력하면 이를 실질적으로 처리할 서블릿인 DoLogin 서블릿을 생성한다.

다음 그림과 같이 URL Mapping을 /doLogin으로 생성한다.

DoLogin 서블릿 생성

DoLogin의 코드는 다음과 같다. loginform.jsp에서 사용자가 입력한 customerId의 값을 저장하고

CustomerService의 객체를 선언한다. 다음으로 findCustomer함수를 사용하여 사용자가 입력한 결과를 Customer라는 Model객체에 저장하여 이를 setAttribute라는 함수를 통해 customer라는 이름으로 저장하여 success.jsp로 forward 한다.

package controller;

import java.io.IOException;

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

import model.Customer;
import service.CustomerService;

/**
 * Servlet implementation class DoLogin
 */
@WebServlet("/doLogin")
public class DoLogin extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public DoLogin() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		
		String customerId = request.getParameter("customerId");
		
		CustomerService service = new CustomerService();
		Customer customer = service.findCustomer(customerId);
		request.setAttribute("customer", customer);
		
		String page;
		if(customer == null) {
			page = "/view/error.jsp";
		}
		else {
			page = "/view/success.jsp";
		}
		
		RequestDispatcher dispatcher = request.getRequestDispatcher(page);
		dispatcher.forward(request, response);
	
	}

}

 

#7 success.jsp생성

view폴더에 success.jsp를 생성하고 다음과 같은 코드를 작성한다. ${}는 JSP EL으로서 변수를 사용하는 방법이다.

넘겨받은 customer를 다음과 같이 화면에 출력하는 코드이다

<%@ page language="java" contentType="text/html; charset=US-ASCII" pageEncoding="US-ASCII"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Insert title here</title>
</head>
<body>
This is Login Success page.

<ul>
<li> Name : ${customer.id }</li>
<li> Name : ${customer.name }</li>
<li> Name : ${customer.email }</li>
</ul>
</body>
</html>

모두 완료하였을 경우 다음과 같은 결과 화면을 확인할 수 있다

success.jsp

반응형
반응형

1. 정적(Static) 페이지란?

정적 페이지

다음 사진과 같이 사용자의 request가 있을 때 (index.html을 요청하는 것) 웹 서버는 파일 시스템의 index.html을 사용자에게 response 해주는 방식이 정적 페이지 방식이다.


2. 동적(Dynamic) 페이지란?

동적 페이지

위 사진과 같이 사용자의 request를 웹 애플리케이션 서버(톰캣)에서 Servlet에 전달한다

Servlet내부에서는 요청에 맞는 재정의 된 함수(doGet)를 실행하고 얻은 결과를 response 해준다

이때 DB와 함께 연동된 처리일 수 있으며 사용자는 함수에 따라 동적인 결과를 얻게 된다.


3. 웹 애플리케이션 서버 구성도

웹 어플리케이션 서버 설명

위 사진과 같이 WAS가 구성된다 앞서 설명한 동적 페이지와 유사한 그림이다

사용자의 request를 web server가 jsp, servlet으로 전달하고 이를 동적으로 처리하고 (이때 DB와의 커넥션이 있을 수 있음) 이를 다시 Web Server로 다시 client에게 전달하는 방식으로 처리하게 된다


4. 구현하기

#1. 프로젝트 생성

프로젝트 생성

File > New > Dynamic Web Project를 선택하여 프로젝트를 생성한다.

프로젝트 생성

Project name을 설정한다 여기서는 servlettest로 설정하였다.

Target runtime은 톰켓 8.0 버전으로 진행하였다.

프로젝트 생성

설정해 줄 것이 없으므로 다음으로 넘어간다

프로젝트 생성

Web.xml을 생성하기 위해 체크를 해주고 Finish를 누른다

 

#2. index.html 생성

html 만들기

생성된 프로젝트에 WebContent를 우클릭하여 다음과 같이 html 파일을 생성한다.

html 만들기

index.html의 코드는 다음과 같다

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Servlet Test Page</title>
</head>
<body>
	<form action="DoLogin" method="POST">
		Username: <input type="text" name="username"> <br/>
		Password: <input type="password" name="password"> <br/>
		<input type="submit" value="제출"/>
	</form>
</body>
</html>

기본적인 흐름을 알기 위한 코드로 form 안에 username을 입력하기 위한 input과 password를 입력하기 위한 input이 존재한다 form은 POST방식으로 전달하기 위해 method = POST이며, action은 실제 서블릿에서 DoLogin이라는 함수에서 처리한다는 의미이다.

 

#3. index.html 결과 화면

html 결과

만약 html을 성공적으로 작성하고 실행하였다면 다음과 같은 결과가 확인된다.

이때 사용자가 제출 버튼을 누르게 된다면 다음과 같은 오류 화면이 발생할 것이다.

 

error 화면

왜냐하면 /DoLogin을 처리해줄 서블릿이 존재하지 않기 때문이다 따라서 /DoLogin을 처리해줄 서블릿을 생성해보자.

 

#4. 서블릿 생성 하기

서블릿 패키지 생성

생성된 프로젝트에 Src를 우클릭하여 다음과 같이 Package를 생성한다. 패키지명은 원하는 명으로 해도 상관없으나 이 프로젝트에서는 servlet이라고 패키지명을 작성하였다.

서블릿 생성

생성된 패키지를 우클릭하여 New > Servlet을 클릭하여 서블릿을 생성한다

서블릿 생성

서블릿 명은 DoLogin으로 작성 하였다 (이는 html form에서 action을 DoLogin으로 지정했기 때문)

서블릿 생성

다음은 자동으로 URL이 /DoLogin으로 매핑되어있으므로 건드리지 않고 넘어간다.

서블릿 생성

다음은 재정의 하여 사용할 함수의 목록을 보여준다 아래에 현재 doPostdoGet이 체크되어있지만 실습에서는 POST를 사용하기로 하였으므로 doPost만 체크하고 서블릿 생성을 완료한다.

 

생성된 DoLogin 서블릿의 코드는 다음과 같다.

package servlet;

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

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

/**
 * Servlet implementation class DoLogin
 */
@WebServlet("/DoLogin") //URL에노테이션으로 되어 있음
public class DoLogin extends HttpServlet { //HttpServlet상속 받아야함
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public DoLogin() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		PrintWriter out = response.getWriter();
		String htmlResponse = "<html>";
		htmlResponse += "<h2> Your name is : " + username + "<br/>";
		htmlResponse += "<h2> Your password is : " + password + "<br/>";
		htmlResponse += "</html>";
		
		out.println(htmlResponse);
	}
}

String username = request.getParameter("username")으로 form의 username input이 보낸 value를 저장하고

PrintWriter를 사용해 html을 response해준다.

 

@WebServlet("/DoLogin")이 부분이 form에서 /DoLogin으로 요청을 보낸 부분을 처리하겠다고 명시해주는 에노테이션 부분이다. 에노테이션에 대한 자세한 설명은 ~~에서 확인할 수 있다.

 

#5. 프로젝트 실행 결과

다음과 같이 서블릿을 생성을 완료하고 이전과 같이 html을 제출하였다면 다음과 같은 화면이 보이게 될 것이다.

프로젝트 성공

5. 설명

코드 구조

프로젝트에서 작성한 구성을 그림으로 표현하면 다음과 같다 사용자는 html폼을 이용하여 POST방식으로 /DoLogin이라는 요청을 보내고 서블릿에서는 DoLogin 클래스의 재정의된 doPost를 사용하여 이를 처리하여 사용자에게 다시 반환하는 방식이다.

 

간단한 서블릿을 활용한 웹 서버 애플리 케이션 예제였다

반응형
반응형

1. 프레임 워크란?

SW의 구조와 클래스를 제공한다.


2. 라이브러리와 프레임워크의 차이

라이브러리 : 클래스의 집합으로 다른 개발자가 만들어놓은 함수라고 생각하면 좋다. 사용자는 이 라이브러리를 가져다 사용한다.

 

프레임워크 : 프레임워크에서 기본 골격을 잡아놓고 프레임워크의 제어 흐름에 맞게 코드를 작성하여 사용한다. 라이브러리와 다르게 프레임워크에서 사용자의 코드를 호출한다고 생각하면 좋다.


3. 스프링이란?

POJO기반의 엔터프라이즈 애플리케이션 개발을 쉽고 편하게 해주는 프레임워크

자바 애플리케이션을 개발하는데 필요한 구조를 제공하는 프레임워크로, 스프링의 전체적인 구조를 처리하므로 개발자는 애플리케이션 개발에 집중할 수 있다는 장점이 있다.

반응형

+ Recent posts