-->

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 컨넥션 설정은 필수 설정이다.

 

 

 

jsp

 

about author

PHRASE

Level 1  라이트

댓글 ( 4)

댓글 남기기

작성