JSP

 

 

 

sqlMapConfig.xml

Mabatis DB 연결 configuration 파일이다.

JNDI       /jdbc/pool  은  server.xml 의  컨넥션 풀 설정의 이름값과 일치해야 한다.

<?xml version="1.0" encoding="UTF-8"?>
<!-- xml 지시어 -->
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 알리아스 설정 -->
    <!-- typeAlias type="전체경로" alias="별칭" -->
 <!--	<typeAliases>

	  <typeAlias type="emp.dto.EmpDTO" alias="e" />
	</typeAliases> -->
	
	<!-- db연결 참조코드 -->
	<environments default="">
		<environment id="">
			<transactionManager type="JDBC" />
			<dataSource type="JNDI">
				<property name="data_source" 
				value="java:comp/env/jdbc/pool" />
			</dataSource>
		</environment>
	</environments>
	<!-- 실제 sql query -->
	<mappers>
		<!-- 샘플 설정 -->
		<!-- <mapper resource="emp/mapper/emp.xml" /> -->	
		<mapper resource="mapper/board.xml"/>
		<mapper resource="mapper/product.xml"/>								
	</mappers>
	
</configuration>





 

 

 

 

class MybatisService

 

mybais  연결된 SqlSession  생성 코드 이다. 

session 자원 닫기 코드는 설정했는데, 스프링의 경우에는 스프링프레임워크가 자동으로 자원을 닫아주지만, 

jsp 서블릿 MVC 모델 2는  프레임워크가 아니다. 따라서 session  을 닫는 설정을 해 주어야 한다.

package config;

import java.io.Reader;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class MybatisService {
// SqlSessionFactoryBuilder => SqlSessionFactory
//		=> SqlSession	
	//SqlSession 객체 생성기
	private static SqlSessionFactory factory;
	static {
		try {
			// Java Resources의 src
			Reader r = Resources.getResourceAsReader("config/sqlMapConfig.xml");
			//SqlSessionFactory 생성기
			factory = new SqlSessionFactoryBuilder().build(r);
			r.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static SqlSessionFactory getFactory() {
		return factory;
	}
	
	// session 자원 닫기
	public static void sessionClose(SqlSession session){
		if(session !=null) session.close();
	}
	
	
}

 

 

product.xml

mybatis 데이를 가져올 쿼리 작성  xml  이다.

namespace="product" 는 유일해야 하며 다음과 같은 

작성후 sqlMapConfig.xml 파일에서 <mapper resource="mapper/product.xml"/> 와 

같이 반드시 설정해 주어야 한다.

쉽게 생각하면 될 것이 보통,  하나의 테이블 에 하나 이상의 매퍼 xml 생성해서 쿼리문을 작성한다. 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="product">
	<!-- id="태그의 식별자" resultType="sql 명령어의 리턴타입(레코드의 자료형)" 샵{변수} => 입력매개변수 -->

	<!-- 최신상품 -->
	<select id="listNewProduct" resultType="net.macaronics.web.dto.ProductVO"> 
		<![CDATA[ select * from NEW_PRO_VIEW ]]>
	</select>

	<!-- 베스트상품 -->
	<select id="listBestProduct" resultType="net.macaronics.web.dto.ProductVO"> 
		<![CDATA[ select * from BEST_PRO_VIEW ]]>
	</select>

	<!-- 선택된상품 -->
	<select id="getProduct" resultType="net.macaronics.web.dto.ProductVO"> 
		<![CDATA[ select * from TBL_PRODUCT where pseq =#{pseq} ]]>
	</select>

	<!-- 종류별 상품 -->
	<select id="listKindProduct" resultType="net.macaronics.web.dto.ProductVO"> 
		<![CDATA[ select * from TBL_PRODUCT where kind =#{kind} ]]>
	</select>

	<!-- 메인 배너 상품 -->
	<select id="bannerProduct" resultType="net.macaronics.web.dto.ProductVO"> 
		<![CDATA[ 			
		select * from (
			select rownum as num , pseq, name, price2, image from(
			select  pseq, name, price2, image
			from tbl_product where kind=5 order by indate desc			
			) ) where num  <= 4 
		]]>
	</select>

	<!-- 메인 배너 아래  세일 상품 5개 -->
	<select id="mainOnSale" resultType="net.macaronics.web.dto.ProductVO"> 
		<![CDATA[ 			
		select * from (
			select rownum as num , pseq, name, price2, image from(
			select  pseq, name, price2, image
			from tbl_product where kind=5 order by indate desc			
			) ) where num  >= 4 and num < 9
		]]>
	</select>

</mapper>


	
	
	

 

DAO

 

 ProductDAO 

위와 같이  mybatis  설정과 코딩을 하였으면  다음과 같은 dao 클래스로  자바와  mybatis 간에 데이터를 전달 한는 코드를 

작성 하면 된다.   preparedstatement  를 사용한 것보다 5배이상 코드양이 줄어 든 것을 볼 수 있다. 

또한, mybatis 이런 방식은 스프링과 별차이가 없다.   또한,  필자가 중복을 제거하기 위한 리팩토링을 해서 한줄로서 DB 에서 데이터를 

가져 올 수 있게 하였다.

package net.macaronics.web.dao;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.session.SqlSession;

import config.MybatisService;
import net.macaronics.web.dto.ProductVO;

public class ProductDAO {
	//싱글톤 
	private static ProductDAO instacnce;
	private ProductDAO(){
		
	}
	public static ProductDAO getInstance(){
		if(instacnce==null){
			instacnce =new ProductDAO();
		}
		return instacnce;
	}
	
	//mybatis 연결
	SqlSession session;
	
	
	//신상품 리스트 얻어오기
	public List<ProductVO> listNewProduct(){
		return commonProduct("product.listNewProduct", null);
	}

	
	//베스트상품 리스트 얻어오기
	public List<ProductVO> listBestProduct(){
		return commonProduct("product.listBestProduct", null);
	}
	
	//상품종류별 상품 리스트 얻어오기
	public List<ProductVO> listKindProduct(String kind){
		return commonProduct("product.listKindProduct", kind);
	}
	
	
	//매인 배너 상품 세일 중인 상품만 가져온다. 최신 4개 
	public List<ProductVO> bannerProduct(){
		return commonProduct("product.bannerProduct", null);
	}
	
	// 메인 배너 아래  세일 상품 5개
	public List<ProductVO> mainOnSale(){
		return commonProduct("product.mainOnSale", null);
	}
	
	
	
	//상품번호로 상품 정보 한개 얻어오기
	public ProductVO getProduct(String pseq){
		List<ProductVO> list=commonProduct("product.getProduct", pseq);
		//ProductVO product=new ProductVO();
		return list.get(0);
		
	}
	
	
	//리스트 상품 리스트   공통
	public List<ProductVO> commonProduct(String mybatisSql , String param){
		List<ProductVO> list =new ArrayList<>();
		try{
			session=MybatisService.getFactory().openSession();
			list=session.selectList(mybatisSql, param);
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			//자원 닫기
			MybatisService.sessionClose(session);
		}
		return list; 
	}
	

	
	
}






 

DTO

package net.macaronics.web.dto;

import com.sun.jmx.snmp.Timestamp;

public class ProductVO {
	private int pseq; //product_seq 시퀀스 객체로 자동 일련번호 부여
	private String name;  //상품명 
	private String kind ; //char(1) 상품 종류 
	private int price1 ;  // number DEFAULT 0,			-- 원가
	private int price2;  // number default 0,			-- 판매가
	private int price3; // number DEFAULT 0,			-- 판매가-원가
	private String content;  //VARCHAR2(3000) null,		-- 상품 내용
	private String image; // VARCHAR2(150) DEFAULT 'default.jpg',	
	private String useyn; 	// char(1) DEFAULT 'y', 			-- 상품 사용유무 체크 y: 사용가능 n: 사용불가능
	private String bestyn; 	// char(1) DEFAULT 'n',			-- 베스트상품인지 여부 체크 y:베스트 상품 n:베스트 상품 아님
	private Timestamp indate ; //date default sysdate	

 

 

 

Controller

 

총 3개의 클래스 를 작성을 한다.  url 을  분리하는 작업이라 생각하면 될 것 같다.

그리고 각 페이지마다의 컨트롤 클래스 만들면 되겠다. 

3개의 클래스 에서  메인 페이지 작업에  필요한 컨트롤 클래스 까지 4개 이다.

새로운 페이지를 만들시 컨트롤 클래스를 1나씩 추가해서 개발하면 될 것이다.

그리고 이 방식은 get 방식 post 방식 상관 없이 한 곳에서 처리 하는 작업이다.

REST ful 방식으로 하려면 다음과 같은 방법으로 개발을 하면 안된다.

 

Action

package net.macaronics.web.controll.action;

import java.io.IOException;

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

public interface Action {

	public void execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;

}

 

 

ActionFactory

package net.macaronics.web.controll.factory;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import net.macaronics.web.controll.IndexAction;
import net.macaronics.web.controll.action.Action;

public class ActionFactory {
	final Logger logger =LogManager.getLogger(ActionFactory.class);
	//싱글톤설정
	private static ActionFactory instance;
	private ActionFactory(){
		super();
	}
	public static ActionFactory getInstance(){
		if(instance==null){
			instance=new ActionFactory();
		}
		return instance;
	}
	
	
	//command 에서 넘어온 파라미터 값이 존재하면 실행
	//즉 ,존재하면 url 만 실행된다. 
	public Action getAction(String command){
		Action action=null;
		logger.info("ActionFactory : {}  ", command);
		
		if(command.equals("index")) action=new IndexAction();  
		
		return action;
	}
	
	
}

 

MacaronicsServlet 

package net.macaronics.web.controll;

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;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import net.macaronics.web.controll.action.Action;
import net.macaronics.web.controll.factory.ActionFactory;

@WebServlet("/MacaronicsServlet")
public class MacaronicsServlet extends HttpServlet {

	final Logger logger =LogManager.getLogger(MacaronicsServlet.class);
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//요청시 보내 파라미터 command 값을 얻어온다.
		String command=request.getParameter("command");
		//파라미터 command 값이 제대로 전달되었는지 확인차 출력
		logger.info("MacaronicsServlet 에서 요청을 받음을 확인  - command 값 : {} " ,command );	
	
		ActionFactory af =ActionFactory.getInstance();
		Action action =af.getAction(command);
		
		if(action!=null){
			action.execute(request, response);
		}		
	}

	
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//post 방식도 doGet() 에서만 요청에 대한 처리를 한다.
		doGet(request, response);
	}
	
	
}

 

 

IndexAction

package net.macaronics.web.controll;

import java.io.IOException;
import java.util.List;

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

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import net.macaronics.web.controll.action.Action;
import net.macaronics.web.dao.ProductDAO;
import net.macaronics.web.dto.ProductVO;

public class IndexAction implements Action{

	final Logger logger =LogManager.getLogger(IndexAction.class);
	
	@Override
	public void execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	  String url ="/index.jsp";
	  // 데이터 베이스에서 상품 정보 얻어오는 비즈니스 로직
	  ProductDAO productDAO =ProductDAO.getInstance();

	  request.setAttribute("newProductList", productDAO.listNewProduct());//신상품
	  request.setAttribute("bestProductList", productDAO.listBestProduct()); //베스트상품	 
	  request.setAttribute("bannerProduct", productDAO.bannerProduct()); //배너 상품
	  request.setAttribute("mainOnSale", productDAO.mainOnSale());//메인 배너 아래  세일 상품 5개

	  //ProductVO pro =productDAO.getProduct("1"); 
	  //logger.info("IndexAction  {}",pro.toString() );
	  
	  RequestDispatcher dispatcher=request.getRequestDispatcher(url);
	  dispatcher.forward(request, response);
	}

	
}

 

 

View

소스의 일부분만  올리겠다.

깃 허브에 소스가 있으니 참조하면 된다.

index.jsp 

      <ul class="nav nav-tabs aa-products-tab">
                    <li class="active"><a href="#newProduct" data-toggle="tab">신상품</a></li>
                    <li><a href="#bestProduct" data-toggle="tab">베스트상품</a></li>
                  </ul>
                  
                  <!-- Tab panes -->
                  <div class="tab-content">
                    <!-- Start men product category -->
                    <div class="tab-pane fade in active" id="newProduct">
                      <ul class="aa-product-catg">

					 
					<c:forEach items="${newProductList }" var="productVO">
                        <li>
                          <figure>
                            <a class="aa-product-img" href="MacaronicsServlet?command=product_detail&pseq=${productVO.pseq}"><img src="images/${productVO.image}" alt="신상품 이미지" width="250" height="300"></a>
                            <a class="aa-add-card-btn"href="#"><span class="fa fa-shopping-cart"></span>장바구니에 담기</a>
                            <figcaption>
                              <h4 class="aa-product-title"><a href="#">${productVO.name}</a></h4>
                              <span class="aa-product-price"><fmt:formatNumber pattern="#,### 원" value="${productVO.price2}"/></span>
                            </figcaption>
                          </figure>                          
                          <div class="aa-product-hvr-content">
                           <a href="#" data-toggle="tooltip" data-placement="top" title="Add to Wishlist"><span class="fa fa-heart-o"></span></a>
                            <a href="#" data-toggle="tooltip" data-placement="top" title="Compare"><span class="fa fa-exchange"></span></a>
                            <a href="#" data-toggle2="tooltip" data-placement="top" title="Quick View" data-toggle="modal" data-target="#quick-view-modal"><span class="fa fa-search"></span></a>
                          </div>
                        </li>
                        <!-- start single product item -->
                      </c:forEach>  
                    </ul>
                    </div>                 
                    <!-- /신상품 end -->
                   

 

 

 

 

 

 

시큐리티 설정

 

csrfguard.properties

org.owasp.csrfguard.unprotected.DailyShop=/dailyShop/*
org.owasp.csrfguard.unprotected.Include=/include/*
org.owasp.csrfguard.unprotected.MacaronicsServlet=/MacaronicsServlet
org.owasp.csrfguard.unprotected.Css=*.css
org.owasp.csrfguard.unprotected.JavaScript=*.js
org.owasp.csrfguard.unprotected.Jpeg=*.jpeg
org.owasp.csrfguard.unprotected.Jpg=*.jpg

 

 

실행 화면

 

 

 

 

 

제작 : macaronics.net - Developer  Jun Ho Choi

소스 :  https://github.com/braverokmc79/jsp_sin

루트 설정( http://macaronics.net/index.php/m01/jsp/view/1352)    및 server.xml  에서 DB 컨넥션 설정은 필수 설정이다.

 

 

 

 

about author

PHRASE

Level 60  라이트

남의 바르지 못한 점을 잡지 말라. 남이 무엇을 하든 참견하지 말라. 다만 내가 무엇을 하고 무엇을 하지 말아야 할 것인가 만을 생각하라. -법구경

댓글 ( 4)

댓글 남기기

작성