1. Spring Framework에서의 FileUpload
2. Command Pattern을 이용한 PageController 관리
3. Filter & Interceptor

4. Mybatis의 Injection Mapping 기능을 이용하여 Dao 구현클래스 삭제
5. HTML기초

 

 

1. Spring Framework에서의 FileUpload

Controller에 관한 객체는 DispatchServlet에서 관여하기 때문에 FileUpload에 대한 것은 dispatch-servlet.xml 설정파일에 등록하여야 한다.

 

A. dispatch-servlet.xml

(스프링 Docs참고)17 .10.2. Using a MultipartResolver  with Commons FileUpload

 

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="1000000" />

</bean>


* Spring framework 2.5 미만에서는 아래 설정을 따르면 된다.

<bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver">
</bean>

 

B. Controller 

* 파일 경로에 주의 한다

 

@Controller
@RequestMapping("/upload/upload")
public class FileUploadAction {


@Autowired
ServletContext ctx;

 

@RequestMapping
public String execute(@RequestParam("name") String name, @RequestParam(value = "age", defaultValue = "0") int age, @RequestParam("photo1") MultipartFile photo1, @RequestParam("photo2") MultipartFile photo2, Model model) throws Exception {

 

model.addAttribute("name", name);
model.addAttribute("age", age);

 

File photo1File = getNewFile();
photo1.transferTo(photo1File);

 

File photo2File = getNewFile();
photo2.transferTo(photo2File);

 

model.addAttribute("photo1", photo1File.getName());
model.addAttribute("photo2", photo2File.getName());

 

return "upload/upload";
}

 

private File getNewFile() {
String repositoryPath = ctx.getRealPath("/files");
String newFileName = "file_" + System.currentTimeMillis() + Math.random();
return new File(repositoryPath + "/" + newFileName);
}

 

}

 

C. 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=UTF-8">
<title>업로드 결과</title>
</head>
<body>
이름: ${name}<br>

나이: ${age}<br>

사진1: ${photo1}<br>
<img src="../files/${photo1}"><br>

사진2: ${photo2}<br>
<img src="../files/${photo2}"><br>
</body>
</html>

 

 

 

2. Command Pattern을 이용한 PageController 관리

 

Command Pattern: 메서드의 호출을 캡슐화(클래스화) -> 메서드를 클래스화

 

왜 쓰나?
클래스 하나에 메서드가 계속 추가될 경우 문제점이 발생할 수 있기 때문에 거대화된 클래스의 메서드를 각각 분리
1. 클래스의 변경이 잦은 경우(유지보수 차원에서 메서드의 추가 변경이 잦다)
2. 이 클래스를 사용하는 다른 클래스가 영향을 받을 수 있고, 하나의 클래스에 많은 메서드가 있음으로 가독성이 떨어지게된다.
3. 메서드를 분리하여 각각 클래스화 함으로 문제를 해결

 

* 만약 한 클래스에 계속 메서드가 추가되는 상황이 발생하게 된다면 커맨드 패턴을 사용해서 클래스로 분리하라

 

여러 기능을 수행하는 메서드들을 가지고 있는 통합된 Action클래스인 EmployeeController.java

@Controller
@RequestMapping("/hr")
public class EmployeeController {

 

@Autowired
EmployeeDao employeeDao;

 

@InitBinder
public void initBinder(WebDataBinder binder) { }

 

@RequestMapping("/searchEmp")
public ModelAndView list(@RequestParam(defaultValue = "0") int deptno) throws Exception { }

 

@RequestMapping(value = "/addEmp", method = RequestMethod.GET)
public String addForm() throws Exception { }

 

@RequestMapping(value = "/addEmp", method = RequestMethod.POST)
public String add(Employee employee, BindingResult result) throws Exception { }

 

@RequestMapping("/retrieveEmp")
public String retrieve(@RequestParam("empno") int empno, ModelMap modelMap) throws Exception { }

 

@RequestMapping(value = "/updateEmp", method = RequestMethod.GET)
public String updateForm(@RequestParam("empno") int empno, Model model) throws Exception { }

 

@RequestMapping(value = "/updateEmp", method = RequestMethod.POST)
public String update(Employee employee, BindingResult result) throws Exception { }

 

@RequestMapping("/deleteEmp")
public String delete(@RequestParam("empno") int empno) throws Exception { }

}


각각 기능(메서드)을 갖는 클래스로 분리한다

@Controller
public class EmployeeAddAction {

@Autowired
EmployeeDao employeeDao;

@InitBinder
public void initBinder(WebDataBinder binder) { }
 
@RequestMapping(value="/hr/addEmp",method=RequestMethod.GET)
public String form() throws Exception { }

 

@RequestMapping(value="/hr/addEmp",method=RequestMethod.POST)
public String add(Employee employee, BindingResult result) throws Exception { }

 

}

 

@Controller
public class EmployeeDeleteAction {

 

@Autowired
EmployeeDao employeeDao;

 

@RequestMapping("/hr/deleteEmp")
public String execute(int empno) throws Exception { }
 
}

 

@Controller
public class EmployeeListAction {

 

@Autowired
EmployeeDao employeeDao;

 

@RequestMapping("/hr/searchEmp")
public ModelAndView execute(@RequestParam(defaultValue="0") int deptno) throws Exception { }
 
}

 

@Controller
public class EmployeeUpdateAction {

 

@Autowired
EmployeeDao employeeDao;

 

@InitBinder
 public void initBinder(WebDataBinder binder) { }
 
@RequestMapping(value="/hr/updateEmp", method=RequestMethod.GET)
public String form(int empno, Model model) throws Exception{ }
 
@RequestMapping(value="/hr/updateEmp", method=RequestMethod.POST)
public String execute(Employee employee, BindingResult result) throws Exception { }
 
}

 

@Controller
public class EmployeeDetailAction {

 

@Autowired
EmployeeDao employeeDao;

 

@RequestMapping("/hr/retrieveEmp")
public String execute(@RequestParam("empno") int empno, ModelMap modelMap) throws Exception { }

 

}

 

 


3. Filter & Interceptor(핸들러 인터셉터)

 

Filter:

인터페이스 javax.servlet.Filter를 구현한 클래스로 다음의 메서드를 갖는다

init(FilterConfig arg0)

doFilter(ServletRequest request, ServletResponse response, FilterChain next)

destroy( )

 

Interceptor:

추상클래스 org.springframework.web.servlet.handler.HandlerInterceptorAdapter를 상속받은 클래스로 다음의 메서드를 갖는다

preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)

postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)

afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)

 

공통점: PageController의 실행 전,후로 꽂아넣을 수 있는 기능을 수행한다(ex.암호화, 복호화 등..)
차이점: Filter는 FrontController인 DispatchServlet 앞에, Interceptor는 뒤에 위치한다

 

* 인터셉터 내부 메서드의 실행순서
preHandler() -> Action실행 -> posthandler() -> JSP실행 -> afterCompletion()

 

* 언제 인터셉터를 사용하나?(인터셉터를 사용하는 예)

Request부터 Response까지의 시간을 측정할 때 사용한다.

어떤 부분이 실행중 일 때 지연시간이 큰지 알아낼 수 있다(인터셉터 내부 메서드 실행순서를 이용)

 

* 인터셉터를 사용하기 위해서는 dispatch-servlet.xml에 아래와 같이 설정을 등록하여야 한다.

<bean id="handlerMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">

<property name="interceptors">

<list>
    <ref bean="testInterceptor"/>
</list>

</property>

</bean>
<bean id="testInterceptor" class="bit.java39.interceptors.TestInterceptor"/>
</beans>

 

 

 

4. Mybatis의 Injection Mapping 기능을 이용하여 Dao 구현클래스 제거

 

* Dao인터페이스와 Mapper.xml 설정파일만으로 실행 가능하다(Mybatis 3.0이상에서 정상 작동한다)

 

참고자료: http://mybatis.github.io/spring/mappers.html#scan

MapperScannerConfigurer

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="org.mybatis.spring.sample.mapper" />
</bean>

 

Dao의 설정에 관여하는 services.xml에 추가하여 사용한다.(Dao의 메서드와 Mapper의 ResultType에 주의)

 

services.xml에 설정추가

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="bit.java39.dao" />
</bean>

 

EmployeeDao.java 인터페이스
public interface EmployeeDao { 

List<Employee> getEmployeeList(int departmentNo) throws Exception;
int insert(Employee employee) throws Exception;
Employee getEmployee(int empNo) throws Exception;
int delete(int empNo) throws Exception;
int update(Employee employee) throws Exception;

}

 

EmployeeMapper.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="bit.java39.dao.EmployeeDao">


<select id="getEmployeeList" resultType="Employee">
    select 
        e.empno as no, 
        e.ename as name, 
        e.job, 
        e.sal as salary, 
        d.dname as departmentName, 
        d.loc as departmentLocation, 
        m.ename as managerName
    from emp e 
        left join dept d on e.deptno=d.deptno
        left join emp m on e.mgr=m.empno
</select> 
 
<insert id="insert" parameterType="Employee">
    insert into emp (empno,ename,job,mgr,hiredate,sal,comm,deptno) 
        values (
        #{no}, #{name}, #{job}, #{managerNo}, 
        #{hireDate}, #{salary}, #{commission}, #{departmentNo})
</insert>
   
<select id="getEmployee" parameterType="int" resultType="Employee">
    select 
        empno no,
        ename name,
        job,
        mgr managerNo,
        hiredate,
        sal salary,
        comm commission,
        deptno departmentNo
from emp
where empno=#{value}
</select>
   
<delete id="delete" parameterType="int">
    delete emp where empno=#{value}
</delete>
   
<update id="update" parameterType="Employee">
    update emp set
        ename=#{name},
        job=#{job},
        mgr=#{managerNo},
        hiredate=#{hireDate},
        sal=#{salary},
        comm=#{commission},
        deptno=#{departmentNo}
        where empno=#{no}
</update>
</mapper>   

 

 


5. HTML

 

A. Semantic Web(구조화된 웹): 각각 태그에 의미를 부여한다(태그의 용도대로 사용하자)
B. DOM: HTML 엘리먼트를 객체화시켜 tree구조로 관리
C. block 태그: 라인을 점유하는 태그들(라인의 변경)
   inline 태그: 라인속에 참여하는 태그들(라인이 바뀌지 않는다)
D. Doctype

 

block 태그
-> <h*> 헤더태그
-> <p> 문단태그
-> <ol> 순서있는줄태그
-> <ul> 순서없는줄태그
-> <li> 라인아이템태그
-> <div> 분할태그
-> <address> 주소태그
-> <blockquote> 인용문태그

 

inline 태그
-> <a> 앵커태그
-> <i> 이탤릭체태그
-> <b> 볼드체태그
-> <em> 엠퍼사이즈태그
-> <span> 확장태그
-> <img> 이미지태그
-> <q> 인용문태그

* 각 태그에 대한 자세한 설명은 검색하면 잘 나오므로 알아서 찾아보자.....

 

 

 

 

 


 

'학습정리 > by H2K' 카테고리의 다른 글

node.js, CORDOVA, PhoneGap  (0) 2013.07.11
javaScript, jQuery 함수  (0) 2013.07.08
NegotiatingViewResolver  (0) 2013.07.07
by 알 수 없는 사용자 2013. 6. 25. 11:24



금일 배운 학습 내용




  • GIT Server 구축
  • DB분리 작업
  • Log 설정




  • GIT Server 구축


Eclipse -> Help -> Eclipse Marketplace에서 Git 검색 후 EGit - Git Team Provider를 Install 시킨다.



http://www.springsource.org -> Code Samples -> Spring Framework Samples ->

 

Git Read-Only -> URI 가져오기




Eclipse -> Git Repositories -> Clone a Git repository





Next -> Next -> Finish




SVN Repositories에서 하는 것처럼 별다른 것 없이 URI에 Git Source 주소를 적어 등록시킨다.









등록이 되었으면 spring-petclinic -> Working Directory -> Import Projects






Import 시키면 Package Explorer에 등록된 것을 확인 할 수 있다.





  • DB분리 작업



Services.xml에 보관해둔 DB정보를 분리 작업을 한다.



Step1. data-access.properties


Import해둔 spring-petclinic -> src -> main -> resources -> spring ->

 

data-access.properties 파일을 작업 할 프로젝트 resources에 가져와서


DB정보를 data-access.properties 파일에다 저장해준다.


jdbc.driverClassName=oracle.jdbc.driver.OracleDriver

jdbc.url=jdbc:oracle:thin:@localhost:1521:xe

jdbc.username=scott

jdbc.password=tiger



Step2. Services.xml


  <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

  <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>

  <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe"/>

  <property name="username" value="scott"/>

  <property name="password" value="tiger"/>

  </bean>


위 DB정보를 EL(Expression Language)로 적어준다.


<bean id="dataSource" class="org.apache.commons.dbcp.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>



위 DB정보를 data-access.properties 파일로 생성해 저장한다.


context:property-placeholder location="classpath:data-access.properties" />


 



Spring framework 2.5 미만에서는 위 코드를 사용하지 못하고, 아래 코드를 사용하게 된다.


<bean

class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

<property name="locations" value="classpath:data-access.properties" />

</bean>







  • Log 설정



Pom.xml -> Dependencies 에서 log4j 검색 후 1.2.14 버전을 추가한다.



  •  log4j 설정
1. web.xml에 context-param과 Listener 설정을 안해줘도 classpath의 루트 경로에
log4j.properties 파일을 두면 자동으로 loggin이 활성화 된다.

2. 또는, WEB-INF/.../log4j.properties 파일을 둔 경우, 아래와 같이 web.xml 파일에
log4jConfigLocation 이라는 이름으로 파라메터 정보를 설정하고,
log4jConfigListener를 사용하여 로딩하는 방법도 있다.

  • log4j 설정파일 위치 설정 (2번방법)
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/log4j.properties</param-value>
</context-param>

  • web.xml에서 Listener 설정 (2번방법)
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

  • log4j.properties 생성 및 설정

WEB-INF 폴더안에 log4j.properties (File) 생성하고 작성한다.


# DEBUG < INFO < WARN < ERROR < FATAL

log4j.rootCategory=DEBUG, stdout, dailyfile


# setting stdout logger

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

#log4j.appender.stdout.ImmediateFlush=true

#log4j.appender.stdout.Target=System.err

log4j.appender.stdout.layout.ConversionPattern=[%5p] [%t] (%F) - %m%n


# setting dailyfile logger

log4j.appender.dailyfile=org.apache.log4j.DailyRollingFileAppender

log4j.appender.dailyfile.layout=org.apache.log4j.PatternLayout

log4j.appender.dailyfile.layout.ConversionPattern=[%5p] [%t] (%F) - %m%n

log4j.appender.dailyfile.DatePattern='.'yyyy-MM-dd

log4j.appender.dailyfile.threshold=DEBUG


#시스템 properties에 집어넣을 경로 ${webapp.root} 설정

#1. context-param web.xml에 집어 넣기.

#-> context-param 정의

# <context-param>

# <param-name>webAppRootKey</param-name>

# <param-value>webapp.root</param-value>

# </context-param>


#2. log4jConfigListener 또는 WebAppRootListener에 추가하기.



log4j.appender.dailyfile.File=${webapp.root}/WEB-INF/log/web03.log


#log4j.logger.org.springframework=DEBUG

#log4j.logger.org.apache=DEBUG

#log4j.logger.org.mybatis=DEBUG


#log4j.logger.java.sql=DEBUG

#log4j.logger.java.sql.Connection=DEBUG

#log4j.logger.java.sql.Statement=DEBUG

#log4j.logger.java.sql.PreparedStatement=DEBUG

#log4j.logger.java.sql.ResultSet=DEBUG


log4j.logger.bit.java39.dao=TRACE




[%p]

 로그 기록 범위 

 [%t]

 스레드

 (%F)

 현 파일명

 %m

 메시지를 출력

 %n

 다음라인으로 이동





  • 시스템 properties에 집어넣을 경로 설정하기
    <!-- 다음 파라메터는 log4jConfigListener에 의해 시스템 프로퍼티로 등록된다.
    -> log4jConfigListener는 webapp.root 이름으로 웹 애플리케이션 루트 경로를 저장한다.
     -->

1. context-param web.xml에 집어넣기
- context-param 정의

<context-param>
    <param-name>webAppRootKey</param-name> <!-- 시스템 프로퍼티에 넣으려면 반드시 이 이름으로 설정해야 한다. -->
    <param-value>webapp.root</param-value>     <!-- 값은 마음대로. log4j.properties에서 사용할 이름이다. -->
</context-param>


2. log4jConfigListener 또는 WebAppRootListener 추가하기



  • Log4j 설정

기본 디폴트는 DEBUG이다.

  • logger 지정
    • 로그 기록의 범위 지정
      • DEBUG < INFO < WARN < ERROR < FATAL
        • 지정한 것보다 같거나 작은 것 모두 출력

예시) DEBUG로 지정하면 그 아래 모든 것이 출력된다.


  • 로그 출력 방법 (이름은 마음대로 설정해도 상관없다.)
예시) log4j.rootCategory=DEBUG, stdout, dailyfile
예시) 각 출력 방법을 지정
- log4j.appender.방법이름=방법지정

  • 출력할 대상 지정
    • log4j.logger


  • 선언 방법
private Logger logger = Logger.getLogger(Logger.class);

static 사용하지 말고 private로 사용한다.

  • 사용방법

logger.debug("오호라...debug...");

logger.info("오호라...info...");

logger.warn("오호라...warn...");

logger.fatal("오호라...fatal...");



  • File로 추출할때 방법 (log4j.properties)

log4j.appender.dailyfile.File=${webapp.root}/web03/WEB-INF/log/web03.log


- 시스템루트를 지정하지 않고 동적으로 받아와 해당 루트에 로그파일을 생성하기 위함.





  • 실제 경로 확인하는 방법

Properties props = System.getProperties();
for(Object key : props.keySet()){
System.out.println(key + " , " + props.getProperty((String)key));
}




- a.k.a. aking -


'학습정리 > by aking' 카테고리의 다른 글

사이트정리  (0) 2013.07.21
안드로이드 NFC  (0) 2013.07.19
Java Script  (0) 2013.07.09
HTML & CSS  (0) 2013.06.25
by 알 수 없는 사용자 2013. 6. 24. 22:18
| 1 2 3 |