Spring MVC로 작업중 입려된 파라미터 검증이 필요하면 공통 성질을 뽑아 aspect로 작업해도 괜찮을 듯 싶다. 공통 성질로는 파라미터 타입, 사이즈, 널체크 등이 있겠지만.. 우선은 널 체크만 작업해보자.


1. @annotation 생성

- 입력값이 필수인 필드명을 array로 받는 단순한 annotation을 생성하자.


사용예) 

@HPNullCheck(parameters={"name", "id", "password"})

public ModelAndView DEMO01(HttpServletRequest request, HttpServletResponse response) {

    ...............

}


@annotation 클래스)

import java.lang.annotation.ElementType;


import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;


@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public @interface HPNullCheck {


String[] parameters();

}


2. @annotation 구현 클래스

- Reflection 기능을 사용하여 @annotation 클래스 기능(널 체크)을 구현한다.


RequestFacade 처리)

- 요청 객체가 RequestFacade 이면 아래와 같이 처리한다.

public void requestFacadeNullCheck(RequestFacade request) throws BizException {

Method[] methods = delcaringClass.getMethods();

for(Method method : methods) {

if(method.getName().equals(methodName)) {

HPNullCheck hpNullCheck = (HPNullCheck) method.getAnnotation(HPNullCheck.class);

if(hpNullCheck != null) {

String[] parameters = hpNullCheck.parameters();        

                        if(parameters == null) return;

     

                        for(int i = 0;i<parameters.length;i++) {

                          if(!parameters[i].equals("")) {

                  String value = request.getParameter(parameters[i]);        

                                    

                                    if(StringUtils.isEmpty(value)) {

                                        throw new BizException("ERO001", "["+parameters[i]+"] 값을 확인하세요.");

                                    }

                                }

    }

}

}

}

}


MultipartHttpServletRequest 처리)

- 요쳥 객체가 DefaultMultipartHttpServletRequest 이면 아래와 같이 처리한다.

public void defaultMultipartHttpServletRequestNullCheck(MultipartHttpServletRequest request) throws BizException {

Method[] methods = delcaringClass.getMethods();

for(Method method : methods) {

HPNullCheck hpNullCheck = (HPNullCheck) method.getAnnotation(HPNullCheck.class);

if(hpNullCheck != null) {

String[] parameters = hpNullCheck.parameters();        

if(parameters == null) return;

for(int i = 0;i<parameters.length;i++) {

if(!parameters[i].equals("")) {

String value = request.getParameter(parameters[i]);        

if(StringUtils.isEmpty(value)) {

throw new BizException("ERO001", "["+parameters[i]+"] 값을 확인하세요.");

}

}

}

}

}

}


Aspect로 Controller 클래스의 메소드를 @Around로 걸고 요청객체의 타입에 따라 위와 같이 Reflect를 활용하여 처리한다.


Posted by 짱가쟁이

<bean id="weatherProcCronTrigger"
        class="org.springframework.scheduling.quartz.CronTriggerBean">
        <property name="jobDetail"><ref bean="weatherProcMethodInvokingJobDetail"/></property>         
        <property name="cronExpression">
            <value>0/5 * 17-18 * * ?</value>
        </property>
</bean>

<value>0/5 * 17-18 * * ?</value>
    17시 부터 시작해서 18시 59분 55초 까지 동작 (5초 주기로)

Posted by 짱가쟁이

log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader).
log4j:WARN Please initialize the log4j system properly.

위와 같은 오류가 발생..

web.xml (before)
<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

web.xml 설정을 보니.. 저런 식으로 선언했더니. 위와 같은 오류가 나면서 로그를 제대로 기록하지 못하더라.

혹시나.. 로그 리스너를 먼저 선언해야 할까? 하는 무식한 생각에 위치를 바꿨더니. 제대로 동작하더라.. 뭐밍??

web.xml(after)
<listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

뭐.. 생각해보니. 스프링컨텍스트로더를 마지막에 올리는게 맞을거 같다는 생각을 해보면서두.. 쩌ㅃ~
Posted by 짱가쟁이
뭐 오래전에 quartz를 한번 사용해봤었고.. 나름 편한듯 싶어.. 이번 프로젝트에서도 요넘을 사용하고자 프로토타입을 제작중.. 짜증나는 문제(??) 가 발생함..

Spring + quartz 를 사용하는데.. 요넘들을 같이 사용하면 어플 구동할때 처음에 무조건 실행하게 만드는게 쉽지 않음.. 뭐 다른 방법이 있는데 내가 찾지를 못하는 건지.. 찾다 귀찮아서 그냥 하나 제작함.

뭐.. 다행인건.. Job class 를 구동하는데.. 특별한 parameter가 필요하지 않기 때문에 좀더 쉽게 끝난듯..

MethodInvokingJobDetailFactoryBean.java
package com.quartz;

import java.lang.reflect.Method;

import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;

/**
 * 스케쥴러를 돌리고 싶고.. 무조건 어플이 처음 구동할 때.. 한번은 돌아줘야 하고..
 * 뭐 이런 경우가 가끔 생길지도 모른다.
 * 이럴때 도통 방법을 모르것더라.. 그래서 그냥 MethodInvokingJobDetailFactoryBean 이넘 상속받아서 하나 맹갔다.
 * 스프링 설정시 <property name="fisrtStart"><value>true</value></property> 만 넣어주면 됨.
 *
 * @author 배명훈
 *
 */
public class CtmMethodInvokingJobDetailFactoryBean extends MethodInvokingJobDetailFactoryBean {

    public void setFisrtStart(boolean fisrtStart) {
       
        if(fisrtStart) {
       
            try {
                // spring di로 삽입한 job object
                Class dymClass     = getTargetObject().getClass();            
                Method[] methods = dymClass.getMethods();
               
                for(int i = 0;i<methods.length;i++) {
                    String methodName = methods[i].getName();
                   
                    // spring di로 삽입한 target method를 찾자.
                    if(methodName.equals(getTargetMethod())) {
                        methods[i].invoke(getTargetObject(), null);
                    }
                }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }  
    }
}

Spring 설정파일
<bean id="weatherProcMethodInvokingJobDetail"
        class="com.quartz.CtmMethodInvokingJobDetailFactoryBean">
        <property name="targetObject"><ref bean="weatherProc"/></property>
        <property name="targetMethod"><value>execute</value></property>
        <property name="concurrent"><value>false</value></property>
        <property name="fisrtStart"><value>true</value></property>
</bean>

스프링 설정 파일을 보면 알것지만.. MethodInvokingJobDetailFactoryBean 을 사용하는 것과 차이점은
firstStart 설정하는 것 밖에 없음..

ps.
    java reflection 은 정말 유용한 기술인듯..
Posted by 짱가쟁이

<?xml version="1.0" encoding="UTF-8"?>

<beans default-autowire="no" default-lazy-init="false"
 default-dependency-check="none"
 xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xmlns:jee="http://www.springframework.org/schema/jee"
 xsi:schemaLocation="
 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
 http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd">

 <!-- DB 설정파일 위치 지정 -->
 <bean id="dbConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="location"><value>WEB-INF/config/db.properties</value></property>
 </bean>

    <!-- dataSource 정의 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName"><value>${jdbc.driverClassName}</value></property>
        <property name="url"><value>${jdbc.url}</value></property>
        <property name="username"><value>${jdbc.username}</value></property>
        <property name="password"><value>${jdbc.password}</value></property>
        <property name="maxActive"><value>${jdbc.maxActive}</value></property>
        <property name="maxIdle"><value>${jdbc.maxIdle}</value></property>
        <property name="maxWait"><value>${jdbc.maxWait}</value></property>
    </bean>
 
    <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
     <property name="dataSource" ref="dataSource" />
     <property name="configLocation" value="WEB-INF/config/sqlMapConfig.xml" />
    </bean>    
   
    <bean id="transactionManager"
  class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource"/>
 </bean>
 
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
     <tx:attributes>
      <tx:method name="execute*" read-only="false" rollback-for="BizException" propagation="REQUIRED"/>
     </tx:attributes>
    </tx:advice>
   
    <aop:config>
     <aop:pointcut id="testServiceProcOperation" expression="execution(* test.logic.proc.*Proc.*(..))" />
     <aop:advisor advice-ref="txAdvice" pointcut-ref="testServiceProcOperation"/>
    </aop:config>
</beans>

Posted by 짱가쟁이
이전버튼 1 이전버튼