환경 변수 설정
- 인코딩 UTF-8 설정하기 ( Workspace/텍스트에디터/CSS/HTML/JSP )
- Server 설정에 RunTime Environments 톰캣 9버전 추가하기
- Customaize Perspective에 Shortcuts 편집하기
- 서버 등록후 더블클릭 Server modules without publising 체크 하고 Port Number 바꿔주기
- 서버에 동적 웹 프로젝트 add 서버 동작 확인하기
- web\WEB-INF\classes WEB-INF 하위 index.jsp 생성하기
lib 라이브러리 등록
WEB-INF 하위 lib라이브러리 파일 추가하기
Source 파일 등록
소스파일 등록하기 (동적 웹 프로젝트 하위에 소스파일로 생성하기)
1. mappers
동적 쿼리문 작성을 위한 dao매핑 xml파일
src 하위에 만들어진 com.greedy.jsp.member.model.dao의 클래스명과 동일해야 한다 (중요!)
2. log4j
로그 확인용 log4jdbc.xml / log4jdbc.log4j2.properties 등록
3. resources
mybatis-config.xml 파일 등록
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="net.sf.log4jdbc.DriverSpy"/>
<property name="url" value="jdbc:log4jdbc:oracle:thin:@127.0.0.1:1521:xe"/>
<property name="username" value="계정아이디"/>
<property name="password" value="비밀번호"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="경로/매핑될DAO xml파일명"/>
</mappers>
</configuration>
=> 설정파일이 필요한 다른 이유는 마이바티스 XML파일이 매퍼 클래스와 동일한 클래스패스에 있지 않은 경우이다. 이 설정을 사용하면 두가지 옵션이 있다. 첫번째는 마이바티스 설정파일에 <mappers> 섹션을 사용해서 XML파일의 클래스패스를 지정하는 것이다.
JSP 파일 생성
index.jsp (web 하위 생성)
그동안 index.html 파일로 만들었으나, 메인페이지로 <jsp:forword>를 사용하기 위해 jsp파일로 생성.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<jsp:forward page="/WEB-INF/views/main/main.jsp"></jsp:forward>
</body>
</html>
index 에서 메인 페이지로 forword 하기
index 파일이 xml설정에 확인해보면 <welcome-file>index.jsp</welcome-file>로 설정되어 있다.
jsp:forward 구문
<jsp:forward page="/WEB-INF/views/main/main.jsp"></jsp:forward>
views 폴더 (WEB-INF 하위 생성)
views는 사용자에게 보여지는 jsp 파일의 모음이다.
각 기능별, 혹은 메뉴별 폴더안에 jsp를 묶어주는 것이 보기 좋다.
(세미 프로젝트에서 구현할 프론트단을 팀원들과 분담하여 기능별로 관리할 목적으로 생성한다.)
common 폴더에는 모든 페이지 상단에 항상 보여지는 hrader.jsp와
응답 요청 결과에 따른 메세지 출력을 위한 success, failed 페이지
error 페이지 등등의 jsp를 담는다.
hrader.jsp include하기
<jsp:include page="../common/header.jsp"/>
jsp에서 css, 이미지파일 연결하기
web 하위에 resourses 폴더를 생성한 뒤 이 안에 css, images, js 파일을 넣는다.
jsp에서 css, js, 이미지 파일을 불러 오는 방법
1. css
<!-- 외부 스타일 시트 -->
<link href="${ pageContext.servletContext.contextPath }/resources/css/style.css" rel="stylesheet">
위 코드를 헤더 파일에 작성한다.
2. js
<!-- 예) 쿠키 사용하여 아이디 기억하기 기능 -->
<script src="${ pageContext.servletContext.contextPath }/resources/js/rememberId.js"></script>
필요한 위치 혹은 헤더 상단에 작성한다.
3. image
<img id="logo" src="${ pageContext.servletContext.contextPath }/resources/images/logo.png">
src 하위 클래스 파일
1. common 패키지
com.(프로젝트명).mvc.common.
1-1. config
ConfigLocation 클래스 생성. static mybatisConfigLocation 선언하기.
package com.onedu.jsp.common.config;
public class ConfigLocation {
public static String mybatisConfigLocation;
}
1-2. controller
init 메소드 서블릿 생성 ( InitialLoadingServlet )
package com.greedy.jsp.common.controller;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import com.greedy.mvc.common.config.ConfigLocation;
@WebServlet(urlPatterns= {}, loadOnStartup = 1)
public class InitialLoadingServlet extends HttpServlet {
public void init(ServletConfig config) throws ServletException {
ConfigLocation.mybatisConfigLocation
= config.getServletContext().getInitParameter("mybatis-config-location");
System.out.println(ConfigLocation.mybatisConfigLocation);
}
}
=> ConfigLocation 클래스(임포트하기)의 mybatisConfigLocation static 변수에
config.getServletContext().getInitParameter("mybatis-config-location") 대입하기
getInitParameter(name)
web.xml (배포 서술자)에 명시한 데이터(context-param)를 name에 의해 value를 반환
코드와 데이터를 분리해서 유지보수성을 향상
<!-- web.xml 파일 -->
<context-param>
<param-name>mybatis-config-location</param-name>
<param-value>mybatis/mybatis-config.xml</param-value>
</context-param>
@WebServlet 애너테이션(@)을 이용한 서블릿 설정
urlPatterns= {} ? 웹 브라우저에서 서블릿 요청 시 사용하는 매핑 속성
loadOnStartup = 1 ?컨테이너 실행시 서블릿이 로드되는 순서 지정
톰캣(서블릿 컨테이너) 시작시 Servlet 초기화 되도록 설정할 수 있다.
@WebServlet 어노테이션을 사용하는 경우 loadOnStartUp 속성값을 지정한다. 0에 가까울수록 먼저 초기화된다.
1-3. mybatis
마이바티스 getSqlSession() Template 클래스
package com.onedu.jsp.commonn.mybatis;
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import com.onedu.jsp.common.config.ConfigLocation;
public class Template {
private static SqlSessionFactory sqlSessionFactory;
public static SqlSession getSqlSession() {
if(sqlSessionFactory == null) {
String resource = ConfigLocation.mybatisConfigLocation;
try {
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
return sqlSessionFactory.openSession(false);
}
}
String resource = ConfigLocation.mybatisConfigLocation ;
ConfigLocation.mybatisConfigLocation의 값은 mybatis/mybatis-config.xml 이다.
서버가 로딩되는 순간 init 메소드에서 설정되었음.
ServletContext
톰캣 컨테이너가 실행 시 각 컨텍스트(웹 애플리케이션)마다 한 개의 ServletContext 객체를 생성하며,
톰캣 컨테이너가 종료하면 소멸된다.
ServletContext 객체는 웹 애플리케이션이 실행되면서 애플리케이션 전체의 공통 자원이나 정보를
미리 바인딩하여 서블릿들이 공유해서 사용한다.
ServletConfig
ServletContext 객체가 컨첵스트당 단위라면 ServletConfig는 각 서블릿에 대해 생성된다.
1-4. filter
필터란 브라우저에서 서블릿에 요청하거나 응답할 때 미리 요청이나 응답과 관련해 여러 가지 작업을 처리하는 기능이다.
AuthenticationFilter
인증된 사용자만 메뉴에 접근할 수 있도록 하는 필터 ('로그인이 필요한 서비스 입니다.'와 같은 인증절차)
EncodingFilter
request.setCharacterEncoding(encodingType); 인코딩 타입을 변경
PasswordEncryptFilter
비밀번호 암호화 처리에 대한 필터
1-5. paging
게시판의 페이징 목록 처리를 위한 Pagenation 클래스와 SelectCriteria 검색기준에 대한 DTO클래스.
1-6. wrapper
패쓰워드 암호화 처리에 필요한 EncryptRequestWrapper 클래스
스프링 시큐리티중 BCrypt 암호화를 제공해주는 라이브러리를 추가한 후 암호화 처리 한다.
sprint-security-crypto 라이브러리를 다운받아서 사용하면 되는데
의존관계에 있는 다른 라이브러리가 필요함 commons-logging 라이브러리도 추가해야한다.
(ClassNotFoundException이 발생하지 않도록)
2. controller
mvc패턴에 따라 controller 하위에는 서블릿 파일들을 생성한다.
서블릿의 세가지 기능
- 클라이언트로부터 요청을 받는다.
- 데이터베이스 연동과 같은 비즈니스 로직을 처리하고
- 3그 결과를 다시 클라이언트로 돌려준다.
controller ? 클라이언트의 요청을 처리한 후 그 결과를 view단으로 전달
Ex ) SelectOneEmpByIdServlet
@WebServlet("/employee/select")
public class SelectOneEmpByIdServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/* 전달한 파라미터 꺼내기 */
String empId = request.getParameter("empId");
System.out.println("empId : " + empId);
/* 비즈니스 로직 호출 - 사번을 이용해 사원 정보 조회 */
EmployeeService empService = new EmployeeService();
EmployeeDTO selectedEmp = empService.selectOneEmpById(empId);
System.out.println("selectedEmp : " + selectedEmp);
/* 비즈니스 로직 실행 결과에 따라 뷰 연결 */
String path="";
if ( selectedEmp != null) {
path = "/WEB-INF/views/employee/showEmpInfo.jsp";
request.setAttribute("selectedEmp", selectedEmp);
} else {
path = "/WEB-INF/views/common/errorPage.jsp";
request.setAttribute("message", "직원 정보 조회 실패!");
}
request.getRequestDispatcher(path).forward(request, response);
}
}
3. model
mvc패턴에 따라 model 하위에는 dto, dao(데이터에 직접적으로 접근하는 역할), service를 만든다.
model ? 컨트롤러가 처리한 결과 및 뷰 선택에 필요한 정보를 저장한다.
service란 ? controller에서 화면에서 넘어오는 매개변수들을 이용해 Service 객체를 호출한다.
Service는 Dao로 세션을 전달하고, DB에서 받아온 데이터를 전달받아 가공한다. (Ex. commit, rollback)
Ex ) EmployeeService
1. DB에서 Select구문을 실행한 경우 결과값이 한 개인 경우 DTO 객체에,
여러 행일 경우 List<DTO타입>객체에 담아 controller로 반환한다.
public class EmployeeService {
/* 의존 관계에 있는 객체가 불변을 유지할 수 있도록 final 필드로 선언한다. */
private final EmployeeDAO empDAO;
/* 생성자를 이용하여 객체를 생성하여 필드에 값을 넣는다. */
public EmployeeService() {
empDAO = new EmployeeDAO();
}
/* 입력받은 id를 매개변수로 전달받아 세션을 생성한 뒤 세션과 매개변수를 DAO로 전달한다. */
public EmployeeDTO selectOneEmpById(String empId) {
/* SqlSession 생성 */
SqlSession session = getSqlSession();
/* SqlSession과 함께 정보를 전달하여 조회한다. */
EmployeeDTO selectedEmp = empDAO.selectEmpById(session, empId);
/* SqlSession 닫기 */
session.close();
/* 조회 결과 반환 */
return selectedEmp;
}
2. DB에서 Insert / Update /Delete 구문을 실행한 경우 성공 여부에 따라 commit/rollback을 해야한다.
public int insertEmp(EmployeeDTO emp) {
/* SqlSession 생성 */
SqlSession session = getSqlSession();
/* SqlSession과 함께 정보를 전달하여 조회한다. */
int result = empDAO.insertEmp(session, emp);
/* 조회된 결과에 따라서 commit/rollback을 실행한다. */
if(result > 0) {
session.commit();
}else {
session.rollback();
}
/* SqlSession 닫기 */
session.close();
/* 조회 결과 반환 */
return result;
}
JDBC 파트부터 반복하여 MVC패턴을 이용해 보고 있지만
MVC 디자인 패턴에 대해서는 추가적인 공부가 필요한 것 같다. 스프링을 배울때 다시 한번 공부하게 되지 않을까..
여기까지 서블릿으로 세미프로젝트를 구현하는 기본적인 방식에 대해 복습해보았다.
세미 프로젝트 전에 간단한 회원가입과 로그인, 게시판 예제를 받았다.
회원가입 로그인 게시판이 가장 기초적인 내용이라고 알고 있는데,
회원가입/로그인 기능은 세미 끝나고서 꼭 연습해야겠다.
이번 세미에서 상품 주문 (결제 api), 주문내역관리 등의 기능들을 맡게 되어서 이것부터 완성해야한다.
메인 기능을 만들고 나면 추가로 공지사항 게시판이나 다른 게시판은 해볼 수 있을 것 같다.
기능 구현 하기도 전에 오늘 수업에서 무수한 설정과 라이브러리 추가, 폴더 생성을 따라가면서 조금 지치기도 했는데,
처음에 뼈대를 잘 만들어 둔다면 그 뒤에 메소드를 하나씩 추가하고 만드는 일은 재밌을 것 같다.
오늘 실습 코드로 홈페이지에서 가입하고, 게시판 글쓰고 하면서 얼마나 감탄했는지.
세미 발표까지 시간이 많이 부족하지만 오늘 예제를 보면서 분명 재밌을 거라는 확신이 들었다. (물론 어렵겠지만!)
세미를 진행하는 동안 우여곡절을 기록해야 할텐데 기록하는 습관이 덜 들어서 문제다.
처음 하게 된 세미 프로젝트! 정말 잘 완성하고 싶지만,
결과보다는 수많은 에러페이지와 내가 어떻게 해결했는지, 그리고 기능 구현에서 어려웠던 것들,
ERD를 만들면서 고민한 부분(erd는 만들었는데 블로그 포스팅을 아직 못했다) 같이 진행하는 과정에서 배운것들.
그리고 팀원들과의 협업하는 과정이 무엇보다 중요하다고 들었다.
그러니 세미 중간중간에 틈틈히 기록하기!! 가 목표이다.
세미 화이팅 !
'백엔드 과정 > Servlet' 카테고리의 다른 글
[Servlet] MIME-TYPE ? (0) | 2022.03.17 |
---|---|
Servlet 문제 풀이 (0) | 2022.03.15 |
[Servlet] file.io (0) | 2022.03.07 |
[Servlet] cookie와 session (0) | 2022.03.07 |
[Servlet] sendRedirect VS RequestDispatcher (0) | 2022.03.06 |