▶
→
└
[오늘의 계획]
★mvc2 + mybatis 합쳐서 게시판 + 댓글 사이트 구현해보기
[오늘의 흐름]
0.환경설정 잡기
- SqlSession.java
SqlSessionFactory 인스턴스를 생성하여 반환하는 기능을 제공하는 클래스
-> 맵퍼를 사용하는 dao 클래스가 상속받기 위한 부모클래스
-> 상속을 목적으로 작성된 클래스 이므로 추상클래스로 선언하는것을 권장
- xxDAO.java
우리가 실행할 메소드가 정의되어 모아져있는곳.
public int insertComment(MyComment1 comment) {
SqlSession sqlSession=getSqlSessionFactory().openSession(true);
try {
return sqlSession.getMapper(MyCommentMapper.class).insertComment(comment);
} finally {
sqlSession.close();
}
}
- db에 있는 테이블을 가져올때 값을 저장하기 위한 클래스.
public class MyComment1 {
private 필드선언;
생성자;
getter, setter 메소드;
}
- 검색결과를 저장하기 위한 클래스도 만들어 줄 수 있다.
- xxxMapper.java (인터페이스)
public interface MyCommentMapper {
int insertComment(MyComment1 comment);
List<MyComment1> selectCommentList1();
List<MyComment2> selectCommentList2();
List<MyComment3> selectCommentList3();
List<MyCommentUser1> selectCommentUserList1();
List<MyCommentUser2> selectCommentUserList2();
MyComment1 selectComment(int commentNo);
List<MyReply> selectCommentNoReplyList(int replyCommentNo);
MyCommentReply selectCommentReply(int commentNo);
}
- xxxMapper.xml
//인터페이스와 엮여 sql문을 작성함
<mapper namespace="xyz.itwill.mapper.MyCommentMapper">
<resultMap type="MyComment3" id="myComment3ResultMap">
<id column="comment_no" property="no"/>
<!-- <result column="comment_id" property="id"/> -->
<result column="user_id" property="id"/>
<result column="user_name" property="name"/>
<result column="comment_content" property="content"/>
<result column="comment_date" property="date"/>
</resultMap>
<select id="selectCommentList3" resultMap="myComment3ResultMap">
select * from mycomment join myuser on comment_id=user_id order by comment_no desc
</select>
</mapper>
★★★★★
필수속성
1. environments
└ DBMS 서버에 접속하기 위한 정보를 제공하기 위한 상위 엘리먼트
2. mappers
└ mapper : SQL 명령이 등록된 맵퍼 파일을 설정하기 위한 엘리먼트
<configuration>
<!-- properties : property 엘리먼트를 설정하기 위한 상위 엘리먼트 -->
<!-- resource 속성 : Properties 파일의 경로를 속성값으로 설정 -->
<!-- => property 엘리먼트 대신 Properties 파일에서 제공되는 이름과 값을 이용 -->
<properties resource="db.properties">
<!-- property : XML 환경설정파일에 필요한 값을 제공하기 위한 엘리먼트 -->
<!-- => 다른 엘리먼트에서 ${이름} 형식으로 표현하여 설정값을 제공받아 사용 -->
<!-- => 다수의 엘리먼트에서 공통적으로 사용되는 값을 좀더 쉽게 이용하거나 변경하기 위해 선언 -->
<property name="oracleDriver" value="oracle.jdbc.driver.OracleDriver"/>
</properties>
<!-- settings : setting 엘리먼트를 설정하기 위한 상위 엘리먼트 -->
<settings>
<!-- setting : mybatis 실행시 필요한 값을 제공하기 위한 엘리먼트 -->
<setting name="callSettersOnNulls" value="true"/>
<setting name="jdbcTypeForNull" value="NULL"/>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!-- typeAliases : typeAlias 엘리먼트를 설정하기 위한 상위 엘리먼트 -->
<typeAliases>
<!-- typeAlias : 맵퍼에서 사용되는 Java 자료형의 별칭(AliasName)을 설정하기 위한 엘리먼트 - 대소문자 구분 -->
<!-- => 맵퍼에서 Java 자료형을 보다 쉽게 표현하기 위해 사용 -->
<!-- => mybatis 내부적으로 설정된 Java 자료형에 대한 별칭 존재 -->
<!-- type 속성 : Java 자료형을 속성값으로 설정 -->
<!-- alias 속성 : Java 자료형에 대한 별칭을 속성값으로 설정 -->
<!--
<typeAlias type="xyz.itwill.dto.Student" alias="Student"/>
<typeAlias type="xyz.itwill.dto.MyMember" alias="MyMember"/>
-->
<!-- package : 특정 패키지에 선언된 모든 클래스에 대한 별칭을 제공하는 엘리먼트 -->
<!-- => 패키지에 선언된 모든 클래스는 패키지를 제외한 클래스명이 별칭으로 자동 등록 -->
<!-- name 속성 : 별칭을 설정하고 하는 클래스가 선언된 패키지를 속성값으로 설정 -->
<package name="xyz.itwill.dto"/>
</typeAliases>
<!-- environments : environment 엘리먼트를 설정하기 위한 상위 엘리먼트 -->
<!-- default 속성 : mybatis 프레임워크에서 사용할 environment 엘리먼트의 식별자을 속성값으로 설정 -->
<environments default="development">
<!-- environment : DBMS 서버에 접속하기 위한 정보를 제공하기 위한 상위 엘리먼트 -->
<!-- id 속성 : environment 엘리먼트를 구분하기 위한 식별자를 속성값으로 설정 -->
<environment id="development">
<!-- transactionManager : 트렌젝션 관리자를 설정하기 위한 엘리먼트 -->
<!-- 트렌젝션 관리자(TransactionManager) : 트렌젝션의 SQL 명령을 커밋하거나 롤백하기 위한 관리자 -->
<transactionManager type="JDBC"/>
<!-- dataSource : Connection 인스턴스를 생성하기 위한 정보를 설정하는 엘리먼트 -->
<!-- type 속성 : [UNPOOLED], [POOLED], [JNDI] 중 하나를 속성값으로 설정 -->
<!-- => UNPOOLED 속성값 : DBCP 기능을 사용하지 않고 Connection 인스턴스 제공 -->
<!-- => POOLED 속성값 : DBCP 기능을 사용하여 Connection 인스턴스 제공 -->
<dataSource type="POOLED">
<!-- property : Connection 인스턴스를 생성하기 위한 값을 제공하기 위한 엘리먼트 -->
<!-- <property name="driver" value="oracle.jdbc.driver.OracleDriver"/> -->
<property name="driver" value="${oracleDriver}"/>
<!-- <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe"/> -->
<property name="url" value="${localDB}"/>
<property name="username" value="BITUSER"/>
<property name="password" value="1004"/>
</dataSource>
</environment>
</environments>
<!-- mappers : mapper 엘리먼트를 설정하기 위한 상위 엘리먼트 -->
<mappers>
<!-- mapper : SQL 명령이 등록된 맵퍼 파일을 설정하기 위한 엘리먼트 -->
<package name="xyz.itwill.mapper"/>
</mappers>
</configuration>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p - %m%n"/>
</layout>
</appender>
<root>
<level value="DEBUG"/>
<appender-ref ref="console"/>
</root>
</log4j:configuration>
- EncodingFilter
public class EncodingFilter implements Filter {
//변경할 캐릭터셋의 인코딩을 저장하기 위한 필드
private String encoding;
//필터 클래스가 인스턴스로 생성된 후 가장 먼저 한번만 호출되는 메소드 - 초기화 작업
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//encoding="utf-8";
//web.xml 파일에서 제공되는 값을 반환받아 필드값 변경
encoding=filterConfig.getInitParameter("encoding");
}
//필터가 동작될 웹프로그램에 대한 요청마다 반복 호출되는 메소드
// => 클라언트에 요청에 의해 동작될 웹프로그램의 처리 전 또는 후에 실행될 명령을 작성
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
//웹프로그램 동작 전에 실행될 명령 작성 - 리퀘스트 메세지 변경
if(request.getCharacterEncoding()==null ||
!request.getCharacterEncoding().equalsIgnoreCase(encoding)) {
request.setCharacterEncoding(encoding);//전달값에 대한 캐릭터셋 변경
}
//FilterChain.doFilter(ServletRequest request, ServletResponse response) : 클라이언트가
//요청한 웹프로그램을 연결하여 실행되도록 설정하는 메소드
chain.doFilter(request, response);//요청 웹프로그램 실행
//웹프로그램 동작 후에 실행될 명령 작성 - 리스폰즈 메세지 변경
}
}
- xxxService.java
Service 클래스 : 모델 클래스의 요청 처리 메소드에게 처리 기능을 제공하기 위한 클래스
=> 컴퍼넌트 클래스 - 단위 프로그램(모듈)
=> DAO 클래스의 메소드를 호출하여 웹프로그램 요청에 대한 처리 기능을 메소드로 제공
잘보니 mvc에서 dao와 mybatis에서의 dao 와 같네 합치고 service가 갖다 쓰는 방식으로 하면 되겠다.
//모든 모델 클래스가 반드시 상속 받아야 되는 인터페이스
// => 모델 클래스의 요청 처리 메소드 작성 규칙 제공
// => 요청 처리 메소드 호출 편의성과 유지보수의 효율성 증가
//요청 처리 메소드는 HttpServletRequest 인스턴스와 HttpServletResponse 인스턴스를 매개변수로 전달
//받아 요청에 대한 처리를 실행하고 뷰 관련 정보(이동 관련 정보)를 반환하도록 작성
public interface Action {
ActionForward execute(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException;
}
public class ActionForward {
//이동 형식 관련 정보를 저장하기 위한 필드
// => false : 리다이렉트 이동, true : 포워드 이동
//리다이렉트 이동 : 클라이언트에게 URL 주소(XXX.do)를 전달하여 다시 요청하도록 응답 처리
// => 클라이언트 브라우저의 URL 주소 변경
//포워드 이동 : 현재 웹프로그램(Controller)에서 다른 웹프로그램(View - JSP)으로 스레드를 이동하여 응답 처리
// => 클라이언트 브라우저의 URL 주소 미변경
private boolean forward;
//이동될 웹프로그램 경로를 저장하기 위한 필드
// => 리다이렉트 이동 : XXX.do, 포워드 이동 : XXX.jsp
private String path;
public ActionForward() {
// TODO Auto-generated constructor stub
}
public boolean isForward() {
return forward;
}
public void setForward(boolean forward) {
this.forward = forward;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
}
진짜 정말 중요한 컨트롤러..
public class ControllerServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private Map<String, Action> actionMap;
@Override
public void init(ServletConfig config) throws ServletException {
actionMap=new HashMap<String, Action>();
Properties properties=new Properties();
String configFile=config.getInitParameter("configFile");
String configFilePath=config.getServletContext().getRealPath(configFile);
try {
FileInputStream in=new FileInputStream(configFilePath);
properties.load(in);
} catch (IOException e) {
e.printStackTrace();
}
for(Object key:properties.keySet()) {
String actionCommand=(String)key;
String actionClass=(String)properties.get(key);
try {
Action actionObject=(Action)Class.forName(actionClass).getDeclaredConstructor().newInstance();
actionMap.put(actionCommand, actionObject);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String requestURI=request.getRequestURI();
String contextPath=request.getContextPath();
String command=requestURI.substring(contextPath.length());
Action action=actionMap.get(command);
if(action==null) {//클라이언트 요청에 대한 모델 인스턴스가 없는 경우
action=new ErrorModel();
}
ActionForward actionForward=action.execute(request, response);
//4.반환받은 뷰 관련 정보(ActionForward 인스턴스)를 이용하여 클라이언트에게 응답 처리
if(actionForward.isForward()) {//forward 필드값이 [true]인 경우 - 포워드 이동
request.getRequestDispatcher(actionForward.getPath()).forward(request, response);
} else {//forward 필드값이 [false]인 경우 - 리다이렉트 이동
response.sendRedirect(actionForward.getPath());
}
}
}
진짜 중요한 web.xml...
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<display-name>mvc</display-name>
<!-- filter : 필터 클래스를 필터로 설정하는 엘리먼트 -->
<!-- => servlet 엘리먼트 선언 전에 작성하는 것을 권장 -->
<filter>
<filter-name>encoding filter</filter-name>
<filter-class>xyz.itwill.filter.EncodingFilter</filter-class>
<!-- init-param : 필터 프로그램에게 값을 제공하기 위한 엘리먼트 -->
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<!-- 앞으로 스프링은 xml을 분석하는거부터 시작임 -->
<!-- filter-mapping : 필터가 동작되기 위한 URL 주소를 설정하는 엘리먼트 -->
<filter-mapping>
<filter-name>encoding filter</filter-name>
<!-- 클라이언트의 모든 요청에 대한 필터가 동작되도록 설정 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- servlet : 서블릿 클래스를 웹프로그램(서블릿)으로 설정하는 엘리먼트 -->
<servlet>
<servlet-name>controller</servlet-name>
<servlet-class>xyz.itwill.mvc.ControllerServlet</servlet-class>
<!-- init-param : 웹프로그램(서블릿)에게 값을 제공하기 위한 엘리먼트 -->
<init-param>
<param-name>configFile</param-name>
<param-value>/WEB-INF/model.properties</param-value>
</init-param>
<!-- load-on-startup : WAS 실행시 서블릿 클래스를 인스턴스로 생성하는 엘리먼트 -->
<!-- => 클라이언트가 요청하지 않아도 서블릿 클래스를 인스턴스로 생성 - init() 메소드 -->
<!-- => 엘리먼트값은 0 이상의 정수로 설정하며 값이 적을수록 먼저 인스턴스로 생성 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- servlet-mapping : 웹프로그램(서블릿)에 URL 주소를 설정하는 엘리먼트 -->
<servlet-mapping>
<servlet-name>controller</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<!-- context-param : 모든 웹프로그램에게 값을 제공하기 위한 엘리먼트 -->
<context-param>
<param-name>name</param-name>
<param-value>홍길동</param-value>
</context-param>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
그럼 이제 만들어볼까요?
1.mvc 구조 잡기
2.mybatis 적용하기
3.필요한 메소드 정리하기
'일기장 > 하루 정리' 카테고리의 다른 글
220302 [수] 부트스트랩(마이페이지) / 멋쟁이사자 자소서 / 동적 sql (0) | 2022.03.02 |
---|---|
220228 [월] resultMap , 동적 SQL (0) | 2022.02.28 |
[220225] 금 Join table 수동 매핑 (0) | 2022.02.25 |
220223 [수] myBatis (0) | 2022.02.23 |
220218 [금] MVC 디자인패턴을 활용한jsp 모델2 (3) (0) | 2022.02.18 |