no message
parent
f8c2e49029
commit
f9c8c01406
@ -1,16 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.cache;/*
|
||||
package cokr.xit.fims.framework.support.cache;
|
||||
|
||||
import org.ehcache.event.CacheEvent;
|
||||
import org.ehcache.event.CacheEventListener;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class EhCacheEventLogger implements CacheEventListener<Object, Object> {
|
||||
@Override
|
||||
public void onEvent(CacheEvent<?, ?> cacheEvent) {
|
||||
log.info("cache event logger message::getKey: {} / getOldValue: {} / getNewValue:{}", cacheEvent.getKey(), cacheEvent.getOldValue(), cacheEvent.getNewValue());
|
||||
}
|
||||
}
|
||||
*/
|
@ -1,203 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.cert;/*
|
||||
* Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Sun Microsystems nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* check out this {@link https://www.lesstif.com/pages/viewpage.action?pageId=12451848}
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* 1. download source
|
||||
* curl -O https://gist.githubusercontent.com/lesstif/cd26f57b7cfd2cd55241b20e05b5cd93/raw/InstallCert.java
|
||||
*
|
||||
* 2. compiling
|
||||
* javac InstallCert.java
|
||||
*
|
||||
* 3. Run
|
||||
* java -cp . InstallCert https://google.com:443
|
||||
*
|
||||
* 4. save peer's ssl cert to keystore(name is jssecacerts)
|
||||
*
|
||||
* 5. extract cert from saved keystore
|
||||
* keytool -exportcert -keystore jssecacerts -storepass changeit -file output.cert -alias letsencrypt
|
||||
*
|
||||
* 6. import cert into JDK's keystore
|
||||
* keytool -importcert -keystore ${JAVA_HOME}/jre/lib/security/cacerts -storepass changeit -file output.cert -alias letsencrypt
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* http://blogs.sun.com/andreas/resource/InstallCert.java
|
||||
* Use:
|
||||
* java InstallCert hostname
|
||||
* Example:
|
||||
*% java InstallCert ecc.fedora.redhat.com
|
||||
*/
|
||||
|
||||
import javax.net.ssl.*;
|
||||
import java.io.*;
|
||||
import java.security.KeyStore;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
/**
|
||||
* Class used to add the server's certificate to the KeyStore
|
||||
* with your trusted certificates.
|
||||
*/
|
||||
public class InstallCert {
|
||||
public static void main(String[] args) throws Exception {
|
||||
String host;
|
||||
int port;
|
||||
char[] passphrase;
|
||||
if ((args.length == 1) || (args.length == 2)) {
|
||||
String[] c = args[0].split(":");
|
||||
host = c[0];
|
||||
port = (c.length == 1) ? 443 : Integer.parseInt(c[1]);
|
||||
String p = (args.length == 1) ? "changeit" : args[1];
|
||||
passphrase = p.toCharArray();
|
||||
} else {
|
||||
System.out.println("Usage: java InstallCert <host>[:port] [passphrase]");
|
||||
return;
|
||||
}
|
||||
File file = new File("jssecacerts");
|
||||
if (file.isFile() == false) {
|
||||
char SEP = File.separatorChar;
|
||||
File dir = new File(System.getProperty("java.home") + SEP
|
||||
+ "lib" + SEP + "security");
|
||||
file = new File(dir, "jssecacerts");
|
||||
if (file.isFile() == false) {
|
||||
file = new File(dir, "cacerts");
|
||||
}
|
||||
}
|
||||
System.out.println("Loading KeyStore " + file + "...");
|
||||
InputStream in = new FileInputStream(file);
|
||||
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
ks.load(in, passphrase);
|
||||
in.close();
|
||||
SSLContext context = SSLContext.getInstance("TLS");
|
||||
TrustManagerFactory tmf =
|
||||
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
tmf.init(ks);
|
||||
X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0];
|
||||
SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
|
||||
context.init(null, new TrustManager[]{tm}, null);
|
||||
SSLSocketFactory factory = context.getSocketFactory();
|
||||
System.out.println("Opening connection to " + host + ":" + port + "...");
|
||||
SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
|
||||
socket.setSoTimeout(10000);
|
||||
try {
|
||||
System.out.println("Starting SSL handshake...");
|
||||
socket.startHandshake();
|
||||
socket.close();
|
||||
System.out.println();
|
||||
System.out.println("No errors, certificate is already trusted");
|
||||
} catch (SSLException e) {
|
||||
System.out.println();
|
||||
e.printStackTrace(System.out);
|
||||
}
|
||||
X509Certificate[] chain = tm.chain;
|
||||
if (chain == null) {
|
||||
System.out.println("Could not obtain server certificate chain");
|
||||
return;
|
||||
}
|
||||
BufferedReader reader =
|
||||
new BufferedReader(new InputStreamReader(System.in));
|
||||
System.out.println();
|
||||
System.out.println("Server sent " + chain.length + " certificate(s):");
|
||||
System.out.println();
|
||||
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
|
||||
MessageDigest md5 = MessageDigest.getInstance("MD5");
|
||||
for (int i = 0; i < chain.length; i++) {
|
||||
X509Certificate cert = chain[i];
|
||||
System.out.println
|
||||
(" " + (i + 1) + " Subject " + cert.getSubjectDN());
|
||||
System.out.println(" Issuer " + cert.getIssuerDN());
|
||||
sha1.update(cert.getEncoded());
|
||||
System.out.println(" sha1 " + toHexString(sha1.digest()));
|
||||
md5.update(cert.getEncoded());
|
||||
System.out.println(" md5 " + toHexString(md5.digest()));
|
||||
System.out.println();
|
||||
}
|
||||
System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]");
|
||||
String line = reader.readLine().trim();
|
||||
int k;
|
||||
try {
|
||||
k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1;
|
||||
} catch (NumberFormatException e) {
|
||||
System.out.println("KeyStore not changed");
|
||||
return;
|
||||
}
|
||||
X509Certificate cert = chain[k];
|
||||
String alias = host + "-" + (k + 1);
|
||||
ks.setCertificateEntry(alias, cert);
|
||||
OutputStream out = new FileOutputStream("jssecacerts");
|
||||
ks.store(out, passphrase);
|
||||
out.close();
|
||||
System.out.println();
|
||||
System.out.println(cert);
|
||||
System.out.println();
|
||||
System.out.println
|
||||
("Added certificate to keystore 'jssecacerts' using alias '"
|
||||
+ alias + "'");
|
||||
}
|
||||
private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();
|
||||
private static String toHexString(byte[] bytes) {
|
||||
StringBuilder sb = new StringBuilder(bytes.length * 3);
|
||||
for (int b : bytes) {
|
||||
b &= 0xff;
|
||||
sb.append(HEXDIGITS[b >> 4]);
|
||||
sb.append(HEXDIGITS[b & 15]);
|
||||
sb.append(' ');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
private static class SavingTrustManager implements X509TrustManager {
|
||||
private final X509TrustManager tm;
|
||||
private X509Certificate[] chain;
|
||||
SavingTrustManager(X509TrustManager tm) {
|
||||
this.tm = tm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return new X509Certificate[0];
|
||||
}
|
||||
|
||||
public void checkClientTrusted(X509Certificate[] chain, String authType)
|
||||
throws CertificateException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
public void checkServerTrusted(X509Certificate[] chain, String authType)
|
||||
throws CertificateException {
|
||||
this.chain = chain;
|
||||
tm.checkServerTrusted(chain, authType);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.exception;
|
||||
|
||||
import cokr.xit.fims.framework.support.util.Checks;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.BindingResult;
|
||||
|
||||
/**
|
||||
* 비지니스 로직 처리 도중 예외 사항에 대해서 다국어 메시지 처리를 해야 할 상황일 때 이에 대한
|
||||
* 처리를 관리한다.
|
||||
* @author julim
|
||||
*/
|
||||
@Slf4j
|
||||
public class BizRuntimeException extends RuntimeException {
|
||||
|
||||
private String code;
|
||||
//private String message;
|
||||
|
||||
private Object[] arguments;
|
||||
|
||||
private BindingResult bindingResult;
|
||||
|
||||
private BizRuntimeException() {
|
||||
super();
|
||||
}
|
||||
|
||||
private BizRuntimeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
private BizRuntimeException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
private BizRuntimeException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public static BizRuntimeException create(BindingResult bindingResult) {
|
||||
BizRuntimeException ex = new BizRuntimeException();
|
||||
ex.setBindingResult(bindingResult);
|
||||
return ex;
|
||||
}
|
||||
|
||||
public static BizRuntimeException create(String message) {
|
||||
return new BizRuntimeException(message);
|
||||
}
|
||||
|
||||
public static BizRuntimeException create(String errorCode, Object[] arguments) {
|
||||
log.debug("BizRuntimeException::create ==>>>> errorCode:{}, arguments:{}", errorCode, arguments);
|
||||
BizRuntimeException ex = new BizRuntimeException();
|
||||
ex.setCode(errorCode);
|
||||
ex.setArguments(arguments);
|
||||
return ex;
|
||||
}
|
||||
|
||||
public static BizRuntimeException create(String errorCode, String message) {
|
||||
log.debug("BizRuntimeException::create ==>>>> errorCode:{}, message:{}", errorCode, message);
|
||||
BizRuntimeException ex = new BizRuntimeException();
|
||||
ex.setCode(errorCode);
|
||||
ex.setArguments(!Checks.isEmpty(message) ? new Object[]{message}: new Object[]{});
|
||||
return ex;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String errorCode) {
|
||||
this.code = errorCode;
|
||||
}
|
||||
|
||||
public Object[] getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
public void setArguments(Object[] arguments) {
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
public BindingResult getBindingResult() {
|
||||
return bindingResult;
|
||||
}
|
||||
|
||||
public void setBindingResult(BindingResult bindingResult) {
|
||||
this.bindingResult = bindingResult;
|
||||
}
|
||||
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.exception;
|
||||
|
||||
import cokr.xit.fims.framework.core.constants.ErrorCode;
|
||||
import lombok.Getter;
|
||||
import org.springframework.context.support.MessageSourceAccessor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Getter
|
||||
@ResponseStatus(code = HttpStatus.BAD_REQUEST, reason = "Invalid parameter")
|
||||
public class CustomBaseException extends RuntimeException {
|
||||
@Resource
|
||||
MessageSourceAccessor messageSourceAccessor;
|
||||
|
||||
private ErrorCode errorCode;
|
||||
private String code;
|
||||
|
||||
public CustomBaseException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public CustomBaseException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public CustomBaseException(ErrorCode errorCode) {
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
public CustomBaseException(String code, String msg) {
|
||||
super(msg);
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public CustomBaseException(Throwable e) {
|
||||
super(e);
|
||||
}
|
||||
|
||||
public CustomBaseException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
public HttpStatus getHttpStatus(){
|
||||
return HttpStatus.BAD_REQUEST;
|
||||
};
|
||||
|
||||
@Override
|
||||
public String getMessage(){
|
||||
return super.getMessage();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.exception;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonEncoding;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import cokr.xit.fims.framework.support.util.AjaxMessageMapRenderer;
|
||||
import cokr.xit.fims.framework.support.util.constants.Globals;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* JacksonJsonView에 의해 데이터 변환중 에러가 발생할 경우 메시지 처리를 제공한다.
|
||||
* @author jeonghoyeol
|
||||
*/
|
||||
public abstract class JSONExceptionMessageWriter {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(JSONExceptionMessageWriter.class);
|
||||
|
||||
/**
|
||||
* JacksonJsonView에 의해 데이터 변환중 에러가 발생할 경우 에러 메시지를 response 객체에 넣어 전달한다.
|
||||
* @param response HttpServletResponse
|
||||
* @param httpStatus Http Status Number
|
||||
* @param errorMessageKey error message key
|
||||
*/
|
||||
public static void writer(HttpServletResponse response, int httpStatus, String errorMessageKey) {
|
||||
response.setStatus(httpStatus);
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
JsonGenerator generator = null;
|
||||
|
||||
try {
|
||||
//objectMapper.enable(JsonReadFeature.ALLOW_NON_NUMERIC_NUMBERS);
|
||||
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
|
||||
generator = objectMapper.getFactory().createGenerator(response.getOutputStream(), JsonEncoding.UTF8);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
|
||||
Map<String, Object> errorMap = AjaxMessageMapRenderer.error(errorMessageKey);
|
||||
|
||||
resultMap.put(Globals.JSON_ERROR_ROOT_ELEMENT_VALUE, errorMap);
|
||||
|
||||
logger.error("error_code : {}", errorMessageKey);
|
||||
logger.error("error_message : {}", resultMap);
|
||||
|
||||
try {
|
||||
objectMapper.writeValue(generator, resultMap);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.exception.filter;
|
||||
|
||||
|
||||
import cokr.xit.fims.framework.support.exception.JSONExceptionMessageWriter;
|
||||
import cokr.xit.fims.framework.support.util.constants.MessageKey;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.util.ThrowableAnalyzer;
|
||||
import org.springframework.security.web.util.ThrowableCauseExtractor;
|
||||
import org.springframework.web.filter.GenericFilterBean;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 비지니스 로직 처리 도중 세션 타임 아웃이 되었을 때 만약 Ajax 형태의 요청이었을 때와 일반 요청이었을 때를 각각
|
||||
* 구분 하여 처리한다.
|
||||
* @author jeonghoyeol
|
||||
*/
|
||||
public class ExceptionTimeoutRedirectFilter extends GenericFilterBean {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ExceptionTimeoutRedirectFilter.class);
|
||||
private final ThrowableAnalyzer throwableAnalyzer = new DefaultThrowableAnalyzer();
|
||||
private final AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
|
||||
private int customSessionExpiredErrorCode = 901;
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
try {
|
||||
chain.doFilter(request, response);
|
||||
//logger.debug("Chain processed normally");
|
||||
|
||||
}catch (IOException ex) {
|
||||
throw ex;
|
||||
|
||||
}catch (Exception ex) {
|
||||
Throwable[] causeChain = throwableAnalyzer.determineCauseChain(ex);
|
||||
RuntimeException ase = (AuthenticationException) throwableAnalyzer.getFirstThrowableOfType(AuthenticationException.class, causeChain);
|
||||
if (ase == null) {
|
||||
ase = (AccessDeniedException) throwableAnalyzer.getFirstThrowableOfType(AccessDeniedException.class, causeChain);
|
||||
}
|
||||
|
||||
if (ase != null) {
|
||||
if (ase instanceof AuthenticationException) {
|
||||
throw ase;
|
||||
}
|
||||
|
||||
else if (ase instanceof AccessDeniedException) {
|
||||
if (authenticationTrustResolver.isAnonymous(SecurityContextHolder.getContext().getAuthentication())) {
|
||||
logger.info("User session expired or not logged in yet");
|
||||
String ajaxHeader = ((HttpServletRequest) request).getHeader("X-Requested-With");
|
||||
if ("XMLHttpRequest".equals(ajaxHeader)) {
|
||||
logger.info(
|
||||
"Ajax call detected, send {} error code",
|
||||
this.customSessionExpiredErrorCode);
|
||||
HttpServletResponse resp = (HttpServletResponse) response;
|
||||
|
||||
resp.setStatus(customSessionExpiredErrorCode);
|
||||
|
||||
JSONExceptionMessageWriter.writer(resp, customSessionExpiredErrorCode, MessageKey.WARN_SESSION_END);
|
||||
}else{
|
||||
logger.info("Redirect to login page");
|
||||
throw ase;
|
||||
}
|
||||
}else{
|
||||
throw ase;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static final class DefaultThrowableAnalyzer extends ThrowableAnalyzer {
|
||||
protected void initExtractorMap() {
|
||||
super.initExtractorMap();
|
||||
registerExtractor(ServletException.class, new ThrowableCauseExtractor() {
|
||||
public Throwable extractCause(Throwable throwable) {
|
||||
ThrowableAnalyzer.verifyThrowableHierarchy(throwable, ServletException.class);
|
||||
return ((ServletException) throwable).getRootCause();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void setCustomSessionExpiredErrorCode(int customSessionExpiredErrorCode) {
|
||||
this.customSessionExpiredErrorCode = customSessionExpiredErrorCode;
|
||||
}
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.exception.resolver;
|
||||
|
||||
import cokr.xit.fims.framework.support.exception.BizRuntimeException;
|
||||
import cokr.xit.fims.framework.support.util.AjaxUtils;
|
||||
import cokr.xit.fims.framework.support.util.Checks;
|
||||
import cokr.xit.fims.framework.support.util.constants.MessageKey;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerExceptionResolver;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.View;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@Slf4j
|
||||
public abstract class AbstractExceptionViewResolver implements HandlerExceptionResolver, Ordered {
|
||||
private int order = Ordered.LOWEST_PRECEDENCE;
|
||||
|
||||
private View view;
|
||||
|
||||
@Override
|
||||
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object obj, Exception exception) {
|
||||
log.error("AbstractExceptionViewResolver::resolveException : ", exception);
|
||||
log.error("========================================================================================");
|
||||
exception.printStackTrace();
|
||||
log.error("========================================================================================");
|
||||
|
||||
String errorCode = getErrorCode(exception);
|
||||
Object[] errorArguments = getErrorArguments(exception);
|
||||
|
||||
return doResolveException(request, response, obj, errorCode, errorArguments, exception);
|
||||
}
|
||||
|
||||
public abstract ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object obj, String errorCode, Object[] arguments, Exception exception);
|
||||
|
||||
protected boolean isValidationError(Exception exception) {
|
||||
if(! (exception instanceof BizRuntimeException) ) {
|
||||
return false;
|
||||
}
|
||||
BizRuntimeException bizException = ((BizRuntimeException)exception);
|
||||
return bizException.getBindingResult() != null;
|
||||
}
|
||||
|
||||
protected boolean isJSONResponseType(HttpServletRequest request, HandlerMethod handlerMethod) {
|
||||
/** 추후 조건 더 추가 될 수 있음 null 체크 해야 함. */
|
||||
if(handlerMethod == null
|
||||
|| handlerMethod.getReturnType() == null
|
||||
|| handlerMethod.getReturnType().getParameterType() == null
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return AjaxUtils.isAjaxRequest(request)
|
||||
|| handlerMethod.getReturnType().getParameterType().isAssignableFrom(ResponseEntity.class);
|
||||
}
|
||||
|
||||
private String getErrorCode(Exception exception) {
|
||||
if(! (exception instanceof BizRuntimeException) ) {
|
||||
return MessageKey.CMM_FAIL;
|
||||
}
|
||||
BizRuntimeException bizException = ((BizRuntimeException)exception);
|
||||
|
||||
if (!Checks.isEmpty(bizException.getCode())) {
|
||||
return bizException.getCode();
|
||||
}
|
||||
return MessageKey.CMM_FAIL;
|
||||
}
|
||||
|
||||
private Object[] getErrorArguments(Exception exception) {
|
||||
if(exception instanceof BizRuntimeException) return ((BizRuntimeException)exception).getArguments();
|
||||
return new Object[]{};
|
||||
}
|
||||
|
||||
public View getView() {
|
||||
return view;
|
||||
}
|
||||
|
||||
public void setView(View view) {
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
return this.order;
|
||||
}
|
||||
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.exception.resolver;
|
||||
|
||||
import cokr.xit.fims.framework.support.exception.BizRuntimeException;
|
||||
import cokr.xit.fims.framework.support.util.AjaxMessageMapRenderer;
|
||||
import cokr.xit.fims.framework.support.util.constants.Globals;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.sql.SQLIntegrityConstraintViolationException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
public class AjaxExceptionViewResolver extends AbstractExceptionViewResolver {
|
||||
|
||||
private boolean EXCEPTION_LOG_TRACE = true;
|
||||
|
||||
//TODO : error 처리 - alert??
|
||||
@Override
|
||||
public ModelAndView doResolveException(HttpServletRequest request,
|
||||
HttpServletResponse response, Object obj, String errorCode, Object[] errorArguments, Exception exception) {
|
||||
log.error("AjaxExceptionViewResolver::doResolveException");
|
||||
|
||||
// ajax 호출이 아닌 경우 NormalExceptionViewResolver로 이동
|
||||
if(!isJSONResponseType(request, (HandlerMethod)obj)) {
|
||||
Enumeration<String> e = request.getHeaderNames();
|
||||
while(e.hasMoreElements()){
|
||||
String name = e.nextElement();
|
||||
log.debug("{} = [{}]", name, request.getHeader(name));
|
||||
}
|
||||
log.error("request Header :: {}", "응답 객체가 JSON 타입이 아닙니다[X-Requested-With]");
|
||||
log.error("AjaxExceptionViewResolver::doResolveException-{}", "응답 객체가 JSON 타입이 아닙니다.");
|
||||
return null;
|
||||
|
||||
// String viewName = "base/error/error";
|
||||
// if("Authentication error".equals(exception.getMessage())){
|
||||
// viewName = "base/error/authError";
|
||||
// }
|
||||
// return new ModelAndView(viewName, AjaxMessageMapRenderer.error(errorCode, errorArguments));
|
||||
}
|
||||
response.setStatus(Globals.JSON_ERROR_STATUS_CODE);
|
||||
|
||||
if(isValidationError(exception)) {
|
||||
return new ModelAndView(getView(), Globals.JSON_ERROR_VALIDATION_ROOT_ELEMENT_VALUE,
|
||||
AjaxMessageMapRenderer.validationError(((BizRuntimeException)exception).getBindingResult()));
|
||||
}
|
||||
|
||||
Map<String, Object> errorMessage = AjaxMessageMapRenderer.error(errorCode, errorArguments);
|
||||
|
||||
log.error("error_code : {}\nerror_message : {}", errorCode, errorMessage);
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
//PrintStream pinrtStream = new PrintStream(out);
|
||||
Map<String,Object> tempMap = EXCEPTION_LOG_TRACE ? AjaxMessageMapRenderer.errorTrace(errorCode, errorArguments): AjaxMessageMapRenderer.error(errorCode, errorArguments);
|
||||
String stackTraceString = EXCEPTION_LOG_TRACE ? out.toString() : "";
|
||||
|
||||
tempMap.put("result", false);
|
||||
|
||||
// Duplicate exception
|
||||
if(exception instanceof SQLIntegrityConstraintViolationException
|
||||
|| exception instanceof DataIntegrityViolationException){
|
||||
tempMap.put("message", "요청 처리에 실패하였습니다[이미 등록된 데이타 요청]");
|
||||
}
|
||||
|
||||
if(EXCEPTION_LOG_TRACE) tempMap.put("message", tempMap.get("message")+"\n"+stackTraceString);
|
||||
else tempMap.put("message", tempMap.get("message"));
|
||||
return new ModelAndView(getView(), tempMap);
|
||||
}
|
||||
|
||||
// return new ModelAndView(getView(), Globals.JSON_ERROR_ROOT_ELEMENT_VALUE,
|
||||
// AjaxMessageMapRenderer.error(errorCode, errorArguments));
|
||||
// }
|
||||
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.exception.resolver;
|
||||
|
||||
import cokr.xit.fims.framework.support.util.AjaxMessageMapRenderer;
|
||||
import cokr.xit.fims.framework.support.util.constants.Globals;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.sql.SQLIntegrityConstraintViolationException;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
public class NormalExceptionViewResolver extends AbstractExceptionViewResolver {
|
||||
|
||||
|
||||
private boolean EXCEPTION_LOG_TRACE = true;
|
||||
|
||||
|
||||
@Override
|
||||
public ModelAndView doResolveException(HttpServletRequest request,
|
||||
HttpServletResponse response, Object obj, String errorCode, Object[] errorArguments, Exception exception) {
|
||||
log.error("NormalExceptionViewResolver::doResolveException");
|
||||
|
||||
//TODO : error page 확인??
|
||||
String viewName = "base/error/error";
|
||||
if("Authentication error".equals(exception.getMessage())){
|
||||
viewName = "base/error/authError";
|
||||
}
|
||||
ModelAndView mav = new ModelAndView(viewName);
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
//PrintStream pinrtStream = new PrintStream(out);
|
||||
String stackTraceString = EXCEPTION_LOG_TRACE ? out.toString() : "";
|
||||
Map<String,Object> tempMap = EXCEPTION_LOG_TRACE ? AjaxMessageMapRenderer.errorTrace(errorCode, errorArguments): AjaxMessageMapRenderer.error(errorCode, errorArguments);
|
||||
|
||||
tempMap.put("result", false);
|
||||
|
||||
// Duplicate exception
|
||||
if(exception instanceof SQLIntegrityConstraintViolationException
|
||||
|| exception instanceof DataIntegrityViolationException){
|
||||
tempMap.put("message", "요청 처리에 실패하였습니다[이미 등록된 데이타 요청]");
|
||||
}
|
||||
|
||||
if(EXCEPTION_LOG_TRACE) tempMap.put("message", tempMap.get("message")+"\n"+stackTraceString);
|
||||
else tempMap.put("message", tempMap.get("message"));
|
||||
|
||||
mav.addObject(Globals.JSON_ERROR_ROOT_ELEMENT_VALUE, tempMap);
|
||||
// mav.addObject(Globals.JSON_ERROR_ROOT_ELEMENT_VALUE, AjaxMessageMapRenderer.error(errorCode, errorArguments));
|
||||
|
||||
log.error("error_code : {}\n" + "error_message : {}", errorCode, tempMap);
|
||||
|
||||
return mav;
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.jpa;// package cokr.xit.fims.framework.support.jpa;
|
||||
//
|
||||
// import framework.xitfamework.xit.cmmn.utils.Checks;
|
||||
// import org.springframework.data.domain.PageRequest;
|
||||
// import org.springframework.data.domain.Pageable;
|
||||
// import org.springframework.data.domain.Sort;
|
||||
// import org.springframework.data.jpa.repository.JpaRepository;
|
||||
//
|
||||
// import java.util.Objects;
|
||||
//
|
||||
//
|
||||
// public class JpaUtil {
|
||||
// private static final int pageNumber = 0;
|
||||
// private static final int pageSize = 20;
|
||||
//
|
||||
// public static Pageable getPagingInfo(Pageable pageable){
|
||||
// if(Checks.isEmpty(pageable)){
|
||||
// return PageRequest.of(pageNumber, pageSize);
|
||||
// }
|
||||
// int page = Checks.isEmpty(pageable.getPageNumber())? pageNumber: pageable.getPageNumber();
|
||||
// int limit = Checks.isEmpty(pageable.getPageSize())? pageSize: pageable.getPageSize();
|
||||
// Sort sort = Checks.isEmpty(pageable.getSort())? null: pageable.getSort();
|
||||
// if(Checks.isEmpty(sort)) return PageRequest.of(page, limit);
|
||||
// else return PageRequest.of(page, limit, Objects.requireNonNull(sort));
|
||||
// // if(Checks.isEmpty(sort)) return PageRequest.of(limit*(page-1), limit);
|
||||
// // else return PageRequest.of(limit*(page-1), limit, Objects.requireNonNull(sort));
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 신규인 경우 저장 처리
|
||||
// * @param id Long
|
||||
// * @param repository JpaRepository
|
||||
// * @param entity Object
|
||||
// */
|
||||
// @SuppressWarnings({"unchecked", "rawtypes"})
|
||||
// public static void saveIfNullId(Long id, JpaRepository repository, Object entity) {
|
||||
// if(id == null) repository.save(entity);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 신규인 경우 저장 처리
|
||||
// * @param id Long
|
||||
// * @param repository JpaRepository
|
||||
// * @param entity Object
|
||||
// */
|
||||
// @SuppressWarnings({"unchecked", "rawtypes"})
|
||||
// public static void saveIfNullId(String id, JpaRepository repository, Object entity) {
|
||||
// if(id == null) repository.save(entity);
|
||||
// }
|
||||
// }
|
@ -1,144 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.jpa;
|
||||
|
||||
import cokr.xit.fims.framework.support.mybatis.PagingConstants;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class Paginator implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final int limit;
|
||||
private int pageNum = 1;
|
||||
private final int totalSize;
|
||||
|
||||
public Paginator(int pageNum, int limit, int totalSize) {
|
||||
super();
|
||||
this.limit = limit;
|
||||
this.totalSize = totalSize;
|
||||
this.pageNum = computePageNo(pageNum);
|
||||
}
|
||||
|
||||
public void setSessionPagination(Paginator paginator){
|
||||
RequestContextHolder.currentRequestAttributes().setAttribute(PagingConstants.Session.PAGE_INFO.getCode(), paginator, RequestAttributes.SCOPE_REQUEST);
|
||||
}
|
||||
|
||||
public int getPageNum() {
|
||||
return pageNum;
|
||||
}
|
||||
|
||||
public void setPage(int pageNum) {
|
||||
this.pageNum = pageNum;
|
||||
}
|
||||
|
||||
public int getLimit() {
|
||||
return limit;
|
||||
}
|
||||
|
||||
public int getTotalSize() {
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
public boolean isFirstPage() {
|
||||
return pageNum <= 1;
|
||||
}
|
||||
|
||||
public boolean isLastPage() {
|
||||
return pageNum >= getTotalPages();
|
||||
}
|
||||
|
||||
public int getPrePage() {
|
||||
if (isHasPrePage()) {
|
||||
return pageNum - 1;
|
||||
} else {
|
||||
return pageNum;
|
||||
}
|
||||
}
|
||||
|
||||
public int getNextPage() {
|
||||
if (isHasNextPage()) {
|
||||
return pageNum + 1;
|
||||
} else {
|
||||
return pageNum;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDisabledPage(int page) {
|
||||
return ((page < 1) || (page > getTotalPages()) || (page == this.pageNum));
|
||||
}
|
||||
|
||||
public boolean isHasPrePage() {
|
||||
return (pageNum - 1 >= 1);
|
||||
}
|
||||
|
||||
public boolean isHasNextPage() {
|
||||
return (pageNum + 1 <= getTotalPages());
|
||||
}
|
||||
|
||||
public int getStartRow() {
|
||||
if (getLimit() <= 0 || totalSize <= 0)
|
||||
return 0;
|
||||
return pageNum > 0 ? (pageNum - 1) * getLimit() + 1 : 0;
|
||||
}
|
||||
|
||||
public int getEndRow() {
|
||||
return pageNum > 0 ? Math.min(limit * pageNum, getTotalSize()) : 0;
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return pageNum > 0 ? (pageNum - 1) * getLimit() : 0;
|
||||
}
|
||||
|
||||
public int getTotalPages() {
|
||||
if (totalSize <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (limit <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int count = totalSize / limit;
|
||||
if (totalSize % limit > 0) {
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
protected int computePageNo(int pageNum) {
|
||||
return computePageNumber(pageNum, limit, totalSize);
|
||||
}
|
||||
|
||||
private static int computeLastPageNumber(int totalItems, int pageSize) {
|
||||
if (pageSize <= 0)
|
||||
return 1;
|
||||
int result = (int) (totalItems % pageSize == 0 ? totalItems / pageSize
|
||||
: totalItems / pageSize + 1);
|
||||
if (result <= 1)
|
||||
result = 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int computePageNumber(int pageNum, int pageSize, int totalItems) {
|
||||
if (pageNum <= 1) {
|
||||
return 1;
|
||||
}
|
||||
if (Integer.MAX_VALUE == pageNum
|
||||
|| pageNum > computeLastPageNumber(totalItems, pageSize)) { // last
|
||||
// page
|
||||
return computeLastPageNumber(totalItems, pageSize);
|
||||
}
|
||||
return pageNum;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("Paginator");
|
||||
sb.append("{pageNum=").append(pageNum);
|
||||
sb.append(", limit=").append(limit);
|
||||
sb.append(", totalSize=").append(totalSize);
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -1,175 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.listener;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
import javax.servlet.http.HttpSessionEvent;
|
||||
import javax.servlet.http.HttpSessionListener;
|
||||
import java.io.InputStream;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* 동시 접속자 세션관리 HttpListener
|
||||
* /WEB-INF/classes/session.properties 설정파일을 참조
|
||||
* 동시접속자 허용수를 setting 할 수 있도록 함. (제한접속자 수를 늘려야 할 경우 클래스 Compile없이 사용하도록)
|
||||
* Site 접속시점 세션생성
|
||||
* Site 로그인시점 세션생성을 분리하여 접속자 수 Counting!
|
||||
*
|
||||
*/
|
||||
public class SessionListener implements HttpSessionListener {
|
||||
public static SessionListener sessionManager = null;
|
||||
public static Hashtable<String, HttpSession> sessionMonitor;
|
||||
public static Hashtable<String, HttpSession> loginSessionMonitor;
|
||||
public static int maxSessionValidCount;
|
||||
|
||||
public SessionListener() {
|
||||
if (sessionMonitor == null) sessionMonitor = new Hashtable<String, HttpSession>();
|
||||
if (loginSessionMonitor == null) loginSessionMonitor = new Hashtable<String, HttpSession>();
|
||||
sessionManager = this;
|
||||
|
||||
Properties prop = new Properties();
|
||||
try {
|
||||
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("session.properties");
|
||||
prop.load(inputStream);
|
||||
} catch (Exception e) {
|
||||
maxSessionValidCount = 300;
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
maxSessionValidCount = Integer.parseInt((String) prop.get("maxSessionValidCount"));
|
||||
// System.out.println(" ########################### maxSessionValidCount : " + maxSessionValidCount);
|
||||
}
|
||||
|
||||
public static synchronized SessionListener getInstance() {
|
||||
if (sessionManager == null)
|
||||
sessionManager = new SessionListener();
|
||||
return sessionManager;
|
||||
}
|
||||
|
||||
/** 현재 활성화 된 session의 수를 반환한다.
|
||||
*
|
||||
* @return int int
|
||||
*/
|
||||
public int getActiveSessionCount() {
|
||||
return sessionMonitor.size();
|
||||
}
|
||||
|
||||
/** 현재 등록된 session의 id목록을 반환한다.
|
||||
* @return Enumeration Enumeration
|
||||
*/
|
||||
public Enumeration<String> getIds() {
|
||||
return sessionMonitor.keys();
|
||||
}
|
||||
|
||||
/** 전체 세션갯수를 측정하여 로그인(대기)상태 메세지 창 호출
|
||||
* @return boolean boolean
|
||||
*/
|
||||
public boolean isMaxLoginSessions() {
|
||||
return maxSessionValidCount <= getActiveLoginSessionCount();
|
||||
}
|
||||
|
||||
/** 현재 활성화 된 session의 수를 반환한다.
|
||||
* @return int int
|
||||
*/
|
||||
public int getActiveLoginSessionCount() {
|
||||
return loginSessionMonitor.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 로그인한 Session Put
|
||||
* @param session session
|
||||
*/
|
||||
public void setLoginSession(HttpSession session) {
|
||||
synchronized (loginSessionMonitor) {
|
||||
loginSessionMonitor.put(session.getId(), session);
|
||||
|
||||
System.out.println(" ############################################################################### ");
|
||||
System.out.println(" # 접속자 (로그인 허용인원수) : " + maxSessionValidCount + " 명#");
|
||||
System.out.println(" # 접속자 (사이트 접속자수) : " + getActiveSessionCount() + " 명#");
|
||||
System.out.println(" # 접속자 (로그인 사용자수) : " + getActiveLoginSessionCount() + " 명#");
|
||||
System.out.println(" ############################################################################### ");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 로그아웃한 Session Remove
|
||||
* @param session session
|
||||
*/
|
||||
public void setLogoutSession(HttpSession session) {
|
||||
synchronized (loginSessionMonitor) {
|
||||
loginSessionMonitor.remove(session.getId());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 현재 등록된 session중 현재 접속된 사용자 정보와 중복 여부 확인 후 중복 접속 이면 이전의 세션을 소멸 시킨다.
|
||||
*/
|
||||
/*public boolean checkDuplicationLogin(String sessionId, String userEeno) {
|
||||
boolean ret = false;
|
||||
Enumeration eNum = sessionMonitor.elements();
|
||||
System.out.println("session count : " + getActiveSessionCount());
|
||||
while (eNum.hasMoreElements()) {
|
||||
HttpSession sh_session = null;
|
||||
try {
|
||||
sh_session = (HttpSession) eNum.nextElement();
|
||||
} catch (Exception e) {
|
||||
continue;
|
||||
}
|
||||
UserModel baseModel = sh_session.getAttribute("UserInfo");
|
||||
if (baseModel != null) {
|
||||
if (userEeno.equals(baseModel.getUserId_())
|
||||
&& !sessionId.equals(sh_session.getId())) {
|
||||
// 전달 받은 사번과(userEeno) 기존 세션값 중 사번이 중복 되면
|
||||
// 기존 세션을 소멸 시킨다.
|
||||
// 사용자 로그아웃 이력(중복접속)을 저장한다.
|
||||
try {
|
||||
HashMap param = new HashMap();
|
||||
param.put("usrId", baseModel.getUserId_());
|
||||
param.put("ipAddr", baseModel.getRemoteIp_());
|
||||
param.put("logKind", "LOGOUT");
|
||||
param.put("logRsn", "DUPLICATE");
|
||||
// DB 처리
|
||||
xxxxxxxx.insertLoginLog(param);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// 해당 세션 무효화
|
||||
sh_session.invalidate();
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}*/
|
||||
|
||||
/** 세션 생성시 이벤트 처리 **/
|
||||
public void sessionCreated(HttpSessionEvent event) {
|
||||
HttpSession session = event.getSession();
|
||||
synchronized (sessionMonitor) {
|
||||
sessionMonitor.put(session.getId(), session);
|
||||
|
||||
System.out.println(" ############################################################################### ");
|
||||
System.out.println(" # 접속자 (로그인 허용인원수) : " + maxSessionValidCount + " 명#");
|
||||
System.out.println(" # 접속자 (사이트 접속자수) : " + getActiveSessionCount() + " 명#");
|
||||
System.out.println(" # 접속자 (로그인 사용자수) : " + getActiveLoginSessionCount() + " 명#");
|
||||
System.out.println(" ############################################################################### ");
|
||||
}
|
||||
}
|
||||
|
||||
/** 세션 소멸(종료)시 이벤트 처리 **/
|
||||
public void sessionDestroyed(HttpSessionEvent event) {
|
||||
HttpSession session = event.getSession();
|
||||
synchronized (sessionMonitor) {
|
||||
sessionMonitor.remove(session.getId());
|
||||
loginSessionMonitor.remove(session.getId());
|
||||
|
||||
System.out.println(" ############################################################################### ");
|
||||
System.out.println(" # 접속자 (로그인 허용인원수) : " + maxSessionValidCount + " 명#");
|
||||
System.out.println(" # 접속자 (사이트 접속자수) : " + getActiveSessionCount() + " 명#");
|
||||
System.out.println(" # 접속자 (로그인 사용자수) : " + getActiveLoginSessionCount() + " 명#");
|
||||
System.out.println(" ############################################################################### ");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.listener;
|
||||
|
||||
import cokr.xit.fims.framework.support.LoggerHelper;
|
||||
import cokr.xit.fims.framework.support.mybatis.PagingConstants;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Framework Starting globals Configuration
|
||||
* </p>
|
||||
*/
|
||||
public class StartupListener implements ServletContextListener {
|
||||
private final static Logger log = LoggerHelper.getLogger();
|
||||
|
||||
public void contextInitialized(ServletContextEvent event) {
|
||||
log.debug("###########################################Simple Java Framework StartupListener##########################################################");
|
||||
log.debug("Initializing context...");
|
||||
// Operating mode
|
||||
if(System.getProperty(PagingConstants.KEY_OP_MODE) == null) System.setProperty(PagingConstants.KEY_OP_MODE, PagingConstants.OP_MODE_DEFAULT);
|
||||
log.debug("{} :: [{}]", PagingConstants.KEY_OP_MODE, System.getProperty(PagingConstants.KEY_OP_MODE));
|
||||
log.debug("Database DataSoure Connection :: [{}]", PagingConstants.OP_MODE_DEFAULT.equals(System.getProperty(PagingConstants.KEY_OP_MODE))? "jdbc":"jndi");
|
||||
log.debug("##########################################################################################################################################");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent sce) {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.listener;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* web.xml에 등록하여야 사용 할 수 있다
|
||||
* @author Administrator
|
||||
*
|
||||
*/
|
||||
public class ThreadPoolContextLoaderListener implements ServletContextListener {
|
||||
|
||||
private static final int NUMBER_OF_THREADS = Runtime.getRuntime().availableProcessors();
|
||||
public static final String THREADPOOL_ALIAS = "threadPoolAlias";
|
||||
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent event) {
|
||||
final ExecutorService threadPool = Executors.newFixedThreadPool(NUMBER_OF_THREADS); // starts thread pool
|
||||
final ServletContext servletContext = event.getServletContext();
|
||||
servletContext.setAttribute(THREADPOOL_ALIAS, threadPool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent event) {
|
||||
|
||||
final ExecutorService threadPool = (ExecutorService) event.getServletContext().getAttribute(THREADPOOL_ALIAS);
|
||||
threadPool.shutdownNow();
|
||||
}
|
||||
|
||||
/**
|
||||
* 참조
|
||||
* https://palpit.tistory.com/entry/Java-%EB%A9%80%ED%8B%B0-%EC%8A%A4%EB%A0%88%EB%93%9C-%EC%8A%A4%EB%A0%88%EB%93%9C%ED%92%80ThreadPool
|
||||
* https://codechacha.com/ko/java-executors/
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
TestParallelExcutorService service = new TestParallelExcutorService();
|
||||
System.out.println("NUMBER_OF_THREADS = " + NUMBER_OF_THREADS);
|
||||
|
||||
service.submit("job1-1");
|
||||
service.submit("job1-2");
|
||||
service.submit("job1-3");
|
||||
service.submit("job1-4");
|
||||
|
||||
service.submit2("job2-1");
|
||||
service.submit2("job2-2");
|
||||
service.submit2("job2-3");
|
||||
service.submit2("job2-4");
|
||||
|
||||
for (int i = 0 ; i < 8; i++) {
|
||||
String result = service.take();
|
||||
System.out.println(result);
|
||||
}
|
||||
|
||||
System.out.println("end");
|
||||
service.close();
|
||||
}
|
||||
|
||||
private static class TestParallelExcutorService {
|
||||
//웹에서 사용시 ServletContext에 저장한 pool 사용
|
||||
//private final ExecutorService executor = (ExecutorService)ContextLoader.getCurrentWebApplicationContext().getServletContext().getAttribute(ThreadPoolContextLoaderListener.THREADPOOL_ALIAS);
|
||||
private final ExecutorService executor = Executors.newFixedThreadPool(NUMBER_OF_THREADS);
|
||||
private final BlockingQueue<String> blockQueue = new ArrayBlockingQueue<>(10);
|
||||
|
||||
public TestParallelExcutorService() {
|
||||
}
|
||||
|
||||
// 익명 함수 처리
|
||||
public void submit(String job) {
|
||||
executor.submit(new Runnable() {
|
||||
public void run() {
|
||||
|
||||
String threadName = Thread.currentThread().getName();
|
||||
System.out.println("finished " + job);
|
||||
String result = job + ", " + threadName;
|
||||
try {
|
||||
blockQueue.put(result);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// lamda식 처리
|
||||
public void submit2(String job) {
|
||||
executor.submit(() -> {
|
||||
String threadName = Thread.currentThread().getName();
|
||||
System.out.println("finished " + job);
|
||||
String result = job + ", " + threadName;
|
||||
try {
|
||||
blockQueue.put(result);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public String take() {
|
||||
try {
|
||||
return blockQueue.take();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
executor.shutdown();
|
||||
// List<Runnable> unfinishedTasks = executor.shutdownNow();
|
||||
// if (!unfinishedTasks.isEmpty()) {
|
||||
// System.out.println("모든 태스크가 종료 되기 전에 서비스가 중단 되었습니다[미완료 태스크수 : " + unfinishedTasks.size());
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.listener;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.servlet.http.HttpSessionEvent;
|
||||
import javax.servlet.http.HttpSessionListener;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
@Slf4j
|
||||
public class UserDupCheckListener implements HttpSessionListener {
|
||||
private static UserDupCheckListener userDupCheckListener;
|
||||
private static HashMap<String,String> sessionMap;
|
||||
|
||||
public UserDupCheckListener() {
|
||||
if (sessionMap == null) sessionMap = new HashMap<String,String>();
|
||||
userDupCheckListener = this;
|
||||
}
|
||||
|
||||
public static synchronized UserDupCheckListener getInstance() {
|
||||
if (userDupCheckListener == null) userDupCheckListener = new UserDupCheckListener();
|
||||
return userDupCheckListener;
|
||||
}
|
||||
|
||||
public boolean isLogin(String sessionId, String userId) {
|
||||
System.out.printf("Login Check :: userId:%s\n", userId);
|
||||
if(sessionMap.containsValue(userId)){
|
||||
System.out.print("&&&&&&&&&&&&& Login User!!!\n");
|
||||
return true;
|
||||
|
||||
}else{
|
||||
sessionMap.put(sessionId, userId);
|
||||
System.out.printf("++++++++++++++Not Login User Session add :: %s=%s\n", sessionId, sessionMap.get(sessionId));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** 세션 생성시 이벤트 처리 */
|
||||
public void sessionCreated(HttpSessionEvent event) {
|
||||
System.out.printf("=====>>>>>sessionCreated : %s\n", event.getSession().getId());
|
||||
synchronized (sessionMap) {
|
||||
sessionMap.put(event.getSession().getId(), "non-login");
|
||||
log();
|
||||
}
|
||||
}
|
||||
|
||||
/** 세션 소멸(logout, sessionTimeout)시 이벤트 처리 */
|
||||
public void sessionDestroyed(HttpSessionEvent event) {
|
||||
System.out.printf("=====>>>>>sessionDestroyed:%s\n", event.getSession().getId());
|
||||
synchronized (sessionMap) {
|
||||
sessionMap.remove(event.getSession().getId());
|
||||
log();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private void log(){
|
||||
Set<String> set = sessionMap.keySet();
|
||||
Iterator<String> it = set.iterator();
|
||||
System.out.print("================================================\n");
|
||||
while (it.hasNext()) {
|
||||
String key = it.next();
|
||||
System.out.printf("%s=%s\n", key, sessionMap.get(key));
|
||||
}
|
||||
System.out.print("================================================\n");
|
||||
}
|
||||
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis;
|
||||
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.domain.Order;
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.domain.PageBounds;
|
||||
import cokr.xit.fims.framework.support.util.Checks;
|
||||
import org.apache.ibatis.session.RowBounds;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
public class MybatisUtils{
|
||||
public static <T> RowBounds getPagingInfo(Map<String,Object> map){
|
||||
if(Checks.isEmpty(map)){
|
||||
return new PageBounds(1, 10);
|
||||
}
|
||||
int page = Checks.isEmpty(map.get("pageNum")) || Integer.parseInt(String.valueOf(map.get("pageNum"))) < 0? 1: Integer.parseInt(String.valueOf(map.get("pageNum")));
|
||||
int limit = Checks.isEmpty(map.get("fetchSize")) || Integer.parseInt(String.valueOf(map.get("fetchSize"))) < 0? 20: Integer.parseInt(String.valueOf(map.get("fetchSize")));
|
||||
// 정렬필드명.direction,정렬필드명.direction,... 형태(정렬필드,정렬필드.desc)
|
||||
String sort = Checks.isEmpty(map.get("sidx"))? "": String.valueOf(map.get("sidx"));
|
||||
return new PageBounds(page, limit , Order.formString(sort));
|
||||
}
|
||||
|
||||
public static <T> RowBounds getPagingInfo(Object cls){
|
||||
int pageNum = 0;
|
||||
int limit = 0;
|
||||
int pageSize = 0;
|
||||
if(Checks.isNull(cls)){
|
||||
return new PageBounds(1, 10);
|
||||
}
|
||||
try {
|
||||
Method pageMethod = cls.getClass().getMethod("getPageNum");
|
||||
if(!Checks.isEmpty(pageMethod)) pageNum = (Integer)pageMethod.invoke(cls, null);
|
||||
|
||||
Method limitMethod = cls.getClass().getMethod("getFetchSize");
|
||||
if(!Checks.isEmpty(limitMethod)) limit = (Integer)limitMethod.invoke(cls, null);
|
||||
} catch (IllegalAccessException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
pageNum = pageNum == 0? 1: pageNum;
|
||||
limit = limit == 0? 20: limit;
|
||||
// 정렬필드명.direction,정렬필드명.direction,... 형태(정렬필드,정렬필드.desc)
|
||||
//String sort = Checks.isEmpty(map.get("sidx"))? "": String.valueOf(map.get("sidx"));
|
||||
//return new RowBounds(page == 1? 1: (page-1)*limit, limit);
|
||||
return new PageBounds(pageNum, limit);
|
||||
}
|
||||
|
||||
public static RowBounds getPagingInfo(final int pageNum, final int limit){
|
||||
return new PageBounds(pageNum, limit);
|
||||
}
|
||||
|
||||
public static RowBounds getPagingInfo(int pageNum, int row, String sort){
|
||||
|
||||
return new PageBounds(pageNum, row, Order.formString(sort));
|
||||
}
|
||||
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis;
|
||||
|
||||
import org.apache.ibatis.type.BaseTypeHandler;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.Date;
|
||||
|
||||
public class ObjectTypeHandler extends BaseTypeHandler<Object> {
|
||||
|
||||
@Override
|
||||
public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
|
||||
throws SQLException {
|
||||
ps.setObject(i, parameter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {
|
||||
Object value = "";
|
||||
Object object = rs.getObject(columnName);
|
||||
value = object;
|
||||
if(object instanceof Clob) {
|
||||
|
||||
Clob clob = (Clob) object;
|
||||
|
||||
if (clob != null) {
|
||||
try {
|
||||
int size = (int) clob.length();
|
||||
value = clob.getSubString(1, size);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (object instanceof java.sql.Date ) {
|
||||
Timestamp sqlTimestamp = rs.getTimestamp(columnName);
|
||||
if (sqlTimestamp != null) {
|
||||
value = new Date(sqlTimestamp.getTime());
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getNullableResult(ResultSet rs, int columnIndex)
|
||||
throws SQLException {
|
||||
Object value = "";
|
||||
Object object = rs.getObject(columnIndex);
|
||||
value = object;
|
||||
if(object instanceof Clob) {
|
||||
|
||||
Clob clob = (Clob) object;
|
||||
|
||||
if (clob != null) {
|
||||
try {
|
||||
int size = (int) clob.length();
|
||||
value = clob.getSubString(1, size);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (object instanceof java.sql.Date ) {
|
||||
Timestamp sqlTimestamp = rs.getTimestamp(columnIndex);
|
||||
if (sqlTimestamp != null) {
|
||||
value = new Date(sqlTimestamp.getTime());
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getNullableResult(CallableStatement cs, int columnIndex)
|
||||
throws SQLException {
|
||||
return cs.getObject(columnIndex);
|
||||
}
|
||||
}
|
@ -1,211 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.OffsetLimitInterceptor;
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.domain.Paginator;
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.jackson2.PageListJsonSerializer;
|
||||
import org.apache.ibatis.plugin.Invocation;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class PagingConstants {
|
||||
|
||||
public static final String KEY_OP_MODE = "spring.config.activate.on-profile";
|
||||
public static final String OP_MODE_DEFAULT = "local";
|
||||
|
||||
// RestTemplate 상수
|
||||
public static final int CONNECT_TIMEOUT = 30 * 1000; // 30초
|
||||
public static final int READ_TIMEOUT = 60 * 1000 * 3; // 3분
|
||||
public static final Charset CHARSET = StandardCharsets.UTF_8;
|
||||
public static final String DEFAULT_VIEW = ViewName.JSON_VIEW.getCode();
|
||||
|
||||
/**
|
||||
* CustomCommonsRequestLoggingFilter에서 로깅을 제외할 url 패턴 정의
|
||||
*/
|
||||
public static final String EXCLUDE_LOGGING_URL_PATTERN = "^(/webjars/|/swagger-ui/|/swagger-resources|/v2/api-docs|/h2-console)"; // "^(/webjars/|/sample/|/web/)"
|
||||
|
||||
public enum ActiveProfile {
|
||||
LOCAL("local"),
|
||||
DEV("dev"),
|
||||
STG("stg"),
|
||||
PROD("prod"),
|
||||
TEST("test");
|
||||
|
||||
private final String code;
|
||||
|
||||
ActiveProfile(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 인증정보 저장 방식
|
||||
*
|
||||
*/
|
||||
public enum AuthSaveType {
|
||||
SECURITY("security"), // SessionCreationPolicy.STATELESS인 경우는 SecurityContext 사용불가
|
||||
SESSION("session"), // TOKEN도 사용 가능은 하지만...
|
||||
HEADER("header"); // TOKEN
|
||||
|
||||
private final String code;
|
||||
|
||||
AuthSaveType(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
}
|
||||
|
||||
public enum JwtToken {
|
||||
// 토큰헤더명,
|
||||
HEADER_NAME("Authorization"),
|
||||
GRANT_TYPE("Bearer"),
|
||||
ACCESS_TOKEN_NAME("accessToken"),
|
||||
REFRESH_TOKEN_NAME("refreshToken"),
|
||||
AUTHORITIES_KEY("role"),
|
||||
TOKEN_USER_NAME("userName"),
|
||||
TOKEN_USER_MAIL("userEmail"),
|
||||
TOKEN_USER_ACNT("userAcnt");
|
||||
|
||||
private final String code;
|
||||
|
||||
JwtToken(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* JWT Token 통신 방식 지정
|
||||
* COOKIE : accessToken - header, refreshToken - cookie
|
||||
* HEADER : accessToken - header, refreshToken - DTO
|
||||
* DTO : accessToken - header, refreshToken - DTO
|
||||
*/
|
||||
public enum JwtTokenParamType {
|
||||
COOKIE,
|
||||
HEADER,
|
||||
DTO
|
||||
}
|
||||
|
||||
public enum ViewName{
|
||||
JSON_VIEW("mappingJackson2JsonView")
|
||||
;
|
||||
private String code;
|
||||
|
||||
ViewName(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mybatis paging 처리시 return list root attribute name
|
||||
* @see PageListJsonSerializer#serialize(PageList, JsonGenerator, SerializerProvider)
|
||||
*/
|
||||
public static final String RSLT_ATTR_NAME = "_item_";
|
||||
|
||||
/**
|
||||
* Maybatis / jpa 페이지 정보 저장
|
||||
* @see OffsetLimitInterceptor#intercept(Invocation)
|
||||
* @see Paginator#setSessionPagination(Paginator)
|
||||
* @see cokr.xit.fims.framework.support.jpa.Paginator#setSessionPagination(com.xit.core.support.jpa.Paginator)
|
||||
*/
|
||||
public enum Session {
|
||||
PAGE_INFO("_pageInfo_"),
|
||||
// DATASET_NAME("gds_pageInfo"),
|
||||
/** 세션에 저장되는 인증유저 객체 attribute name */
|
||||
AuthentSessionObject("AUTH_SS_OBJECT"),
|
||||
/** 세션에 저장되는 인증유저 권한종류 attribute name */
|
||||
AuthentSessionAuthority("AUTH_SS_AUTHORITY"),
|
||||
;
|
||||
|
||||
private String code;
|
||||
|
||||
Session( String code ) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
}
|
||||
|
||||
public enum LoginType {
|
||||
SSO,
|
||||
Login,
|
||||
Unknown
|
||||
}
|
||||
|
||||
public enum CharsetType {
|
||||
Default("default"),
|
||||
Utf8( "UTF-8" ),
|
||||
EucKr( "EUC-KR" ),
|
||||
Iso8859("8859_1");
|
||||
|
||||
private String code;
|
||||
|
||||
CharsetType( String code) {
|
||||
this.code = code;
|
||||
}
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public Charset getCharset() {
|
||||
if ( this == Default )
|
||||
return Charset.defaultCharset();
|
||||
|
||||
return Charset.forName( this.code);
|
||||
}
|
||||
|
||||
public byte[] getBytes( String str ) {
|
||||
return str.getBytes( this.getCharset() );
|
||||
}
|
||||
|
||||
public String getString( byte[] bytes ) {
|
||||
return new String( bytes, this.getCharset() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* String pad처리 시 추가문자 지정타입
|
||||
* @타입 : PadType
|
||||
*/
|
||||
public enum PadType {
|
||||
/** 문자열 왼쪽 */
|
||||
Left,
|
||||
/** 문자열 오른쪽 */
|
||||
Right
|
||||
}
|
||||
|
||||
public enum PageNavigator {
|
||||
DIV_ID("pager"),
|
||||
CLASS_NAME("pager"),
|
||||
FIRST_SYMBOLIC(" ◀ "),
|
||||
PREV_SYMBOLIC(" ◁ "),
|
||||
NEXT_SYMBOLIC(" ▷ "),
|
||||
LAST_SYMBOLIC(" ▶ ");
|
||||
|
||||
private String code;
|
||||
|
||||
PageNavigator(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,171 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.mybatis.spring.SqlSessionFactoryBean;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
/**
|
||||
* mybatis mapper 자동 감지 후 자동으로 서버 재시작이 필요 없이 반영
|
||||
*/
|
||||
public class RefreshableSqlSessionFactoryBean extends SqlSessionFactoryBean implements DisposableBean {
|
||||
private static final Log log = LogFactory.getLog(RefreshableSqlSessionFactoryBean.class);
|
||||
private SqlSessionFactory proxy;
|
||||
private int interval = 500;
|
||||
private Timer timer;
|
||||
private TimerTask task;
|
||||
private Resource[] mapperLocations;
|
||||
/**
|
||||
* 파일 감시 쓰레드가 실행중인지 여부.
|
||||
*/
|
||||
private boolean running = false;
|
||||
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
|
||||
private final Lock r = rwl.readLock();
|
||||
private final Lock w = rwl.writeLock();
|
||||
|
||||
public void setMapperLocations(Resource[] mapperLocations) {
|
||||
super.setMapperLocations(mapperLocations);
|
||||
this.mapperLocations = mapperLocations;
|
||||
}
|
||||
|
||||
public void setInterval(int interval) {
|
||||
this.interval = interval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public void refresh() throws Exception {
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("refreshing sqlMapClient.");
|
||||
}
|
||||
w.lock();
|
||||
try {
|
||||
super.afterPropertiesSet();
|
||||
} finally {
|
||||
w.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 싱글톤 멤버로 SqlMapClient 원본 대신 프록시로 설정하도록 오버라이드.
|
||||
*/
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
super.afterPropertiesSet();
|
||||
setRefreshable();
|
||||
}
|
||||
|
||||
private void setRefreshable() {
|
||||
proxy = (SqlSessionFactory) Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(), new Class[] { SqlSessionFactory.class }, new InvocationHandler() {
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
// log.debug("method.getName() : " + method.getName());
|
||||
return method.invoke(getParentObject(), args);
|
||||
}
|
||||
});
|
||||
task = new TimerTask() {
|
||||
private final Map<Resource, Long> map = new HashMap<>();
|
||||
|
||||
public void run() {
|
||||
if (isModified()) {
|
||||
try {
|
||||
refresh();
|
||||
} catch (Exception e) {
|
||||
log.error("caught exception", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isModified() {
|
||||
boolean retVal = false;
|
||||
if (mapperLocations != null) {
|
||||
for (int i = 0; i < mapperLocations.length; i++) {
|
||||
Resource mappingLocation = mapperLocations[i];
|
||||
retVal |= findModifiedResource(mappingLocation);
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private boolean findModifiedResource(Resource resource) {
|
||||
boolean retVal = false;
|
||||
List<String> modifiedResources = new ArrayList<String>();
|
||||
try {
|
||||
long modified = resource.lastModified();
|
||||
if (map.containsKey(resource)) {
|
||||
long lastModified = (Long) map.get(resource);
|
||||
if (lastModified != modified) {
|
||||
map.put(resource, modified);
|
||||
modifiedResources.add(resource.getDescription());
|
||||
retVal = true;
|
||||
}
|
||||
} else {
|
||||
map.put(resource, modified);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("caught exception", e);
|
||||
}
|
||||
if (retVal) {
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("modified files : " + modifiedResources);
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
};
|
||||
timer = new Timer(true);
|
||||
resetInterval();
|
||||
}
|
||||
|
||||
private Object getParentObject() throws Exception {
|
||||
r.lock();
|
||||
try {
|
||||
return super.getObject();
|
||||
} finally {
|
||||
r.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public SqlSessionFactory getObject() {
|
||||
return this.proxy;
|
||||
}
|
||||
|
||||
public Class<? extends SqlSessionFactory> getObjectType() {
|
||||
return (this.proxy != null ? this.proxy.getClass() : SqlSessionFactory.class);
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setCheckInterval(int ms) {
|
||||
interval = ms;
|
||||
if (timer != null) {
|
||||
resetInterval();
|
||||
}
|
||||
}
|
||||
|
||||
private void resetInterval() {
|
||||
if (running) {
|
||||
timer.cancel();
|
||||
running = false;
|
||||
}
|
||||
if (interval > 0) {
|
||||
timer.schedule(task, 0, interval);
|
||||
running = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() throws Exception {
|
||||
timer.cancel();
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis.paging;
|
||||
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
|
||||
public class CleanupMybatisPaginatorListener implements ServletContextListener {
|
||||
public void contextInitialized(ServletContextEvent servletContextEvent) {
|
||||
|
||||
}
|
||||
|
||||
public void contextDestroyed(ServletContextEvent servletContextEvent) {
|
||||
OffsetLimitInterceptor.Pool.shutdownNow();
|
||||
}
|
||||
}
|
@ -1,216 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis.paging;
|
||||
|
||||
import cokr.xit.fims.framework.support.LoggerHelper;
|
||||
import cokr.xit.fims.framework.support.mybatis.PagingConstants;
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.dialect.Dialect;
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.domain.PageBounds;
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.domain.Paginator;
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.support.PropertiesHelper;
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.support.SQLHelp;
|
||||
import cokr.xit.fims.framework.support.util.Checks;
|
||||
import org.apache.ibatis.cache.Cache;
|
||||
import org.apache.ibatis.cache.CacheKey;
|
||||
import org.apache.ibatis.executor.Executor;
|
||||
import org.apache.ibatis.mapping.BoundSql;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
import org.apache.ibatis.mapping.MappedStatement.Builder;
|
||||
import org.apache.ibatis.mapping.ParameterMapping;
|
||||
import org.apache.ibatis.mapping.SqlSource;
|
||||
import org.apache.ibatis.plugin.*;
|
||||
import org.apache.ibatis.session.ResultHandler;
|
||||
import org.apache.ibatis.session.RowBounds;
|
||||
import org.slf4j.Logger;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
/**
|
||||
* Paging 정보 - Paginator(pageNum, limit, totalSize)- 획득, 추가
|
||||
*/
|
||||
@Intercepts({ @Signature(type = Executor.class,
|
||||
method = "query",
|
||||
args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class }) })
|
||||
public class OffsetLimitInterceptor implements Interceptor {
|
||||
private final Logger log = LoggerHelper.getLogger();
|
||||
static int MAPPED_STATEMENT_INDEX = 0;
|
||||
static int PARAMETER_INDEX = 1;
|
||||
static int ROWBOUNDS_INDEX = 2;
|
||||
//static int RESULT_HANDLER_INDEX = 3;
|
||||
static ExecutorService Pool;
|
||||
String dialectClass;
|
||||
boolean asyncTotalCount = false;
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public Object intercept(final Invocation invocation) throws Throwable {
|
||||
final Executor executor = (Executor) invocation.getTarget();
|
||||
final Object[] queryArgs = invocation.getArgs();
|
||||
final MappedStatement ms = (MappedStatement) queryArgs[MAPPED_STATEMENT_INDEX];
|
||||
final Object parameter = queryArgs[PARAMETER_INDEX];
|
||||
final RowBounds rowBounds = (RowBounds) queryArgs[ROWBOUNDS_INDEX];
|
||||
final PageBounds pageBounds = new PageBounds(rowBounds);
|
||||
if (pageBounds.getOffset() == RowBounds.NO_ROW_OFFSET && pageBounds.getLimit() == RowBounds.NO_ROW_LIMIT && pageBounds.getOrders().isEmpty()) {
|
||||
return invocation.proceed();
|
||||
}
|
||||
|
||||
final Dialect dialect;
|
||||
try {
|
||||
Class clazz = Class.forName(dialectClass);
|
||||
Constructor constructor = clazz.getConstructor(MappedStatement.class, Object.class, PageBounds.class);
|
||||
dialect = (Dialect) constructor.newInstance(new Object[] { ms, parameter, pageBounds });
|
||||
} catch (Exception e) {
|
||||
throw new ClassNotFoundException("Cannot create dialect instance: " + dialectClass, e);
|
||||
}
|
||||
|
||||
final BoundSql boundSql = ms.getBoundSql(parameter);
|
||||
|
||||
queryArgs[MAPPED_STATEMENT_INDEX] = copyFromNewSql(ms, boundSql, dialect.getPageSQL(), dialect.getParameterMappings(), dialect.getParameterObject());
|
||||
queryArgs[PARAMETER_INDEX] = dialect.getParameterObject();
|
||||
queryArgs[ROWBOUNDS_INDEX] = new RowBounds(RowBounds.NO_ROW_OFFSET, RowBounds.NO_ROW_LIMIT);
|
||||
|
||||
boolean async = pageBounds.getAsyncTotalCount() == null ? asyncTotalCount : pageBounds.getAsyncTotalCount();
|
||||
Future<List> listFuture = call((Callable<List>) () -> (List) invocation.proceed(), async);
|
||||
|
||||
if (pageBounds.isContainsTotalCount()) {
|
||||
Callable<Paginator> countTask = (Callable) () -> {
|
||||
Paginator paginator;
|
||||
Integer count;
|
||||
Cache cache = ms.getCache();
|
||||
if (cache != null && ms.isUseCache() && ms.getConfiguration().isCacheEnabled()) {
|
||||
CacheKey cacheKey = executor.createCacheKey(
|
||||
ms,
|
||||
parameter,
|
||||
new PageBounds(),
|
||||
copyFromBoundSql(ms, boundSql, dialect.getCountSQL(), boundSql.getParameterMappings(), boundSql.getParameterObject()));
|
||||
count = (Integer) cache.getObject(cacheKey);
|
||||
if (count == null) {
|
||||
count = SQLHelp.getCount(ms, parameter, boundSql, dialect);
|
||||
cache.putObject(cacheKey, count);
|
||||
}
|
||||
} else {
|
||||
count = SQLHelp.getCount(ms, parameter, boundSql, dialect);
|
||||
}
|
||||
paginator = new Paginator(pageBounds.getPageNum(), pageBounds.getLimit(), count);
|
||||
return paginator;
|
||||
};
|
||||
Future<Paginator> countFutrue = call(countTask, async);
|
||||
// PageList pageList = new PageList(listFuture.get(), countFutrue.get());
|
||||
|
||||
// log.debug("###################################################################################");
|
||||
// log.debug("OffsetLimitInterceptor Page information ThreadLocal save::{} - {}", FEnum.Session.PAGE_INFO.getValue(), countFutrue.get());
|
||||
// log.debug("###################################################################################");
|
||||
RequestContextHolder.currentRequestAttributes().setAttribute(PagingConstants.Session.PAGE_INFO.getCode(), countFutrue.get(), RequestAttributes.SCOPE_REQUEST);
|
||||
// ContextThreadLocalHolder.setPageListThreadLocal(pageList);
|
||||
// return pageList; return new PageList(listFuture.get(), countFutrue.get());
|
||||
}
|
||||
return listFuture.get();
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private <T> Future<T> call(Callable callable, boolean async) {
|
||||
if (async) {
|
||||
return Pool.submit(callable);
|
||||
} else {
|
||||
FutureTask<T> future = new FutureTask(callable);
|
||||
future.run();
|
||||
return future;
|
||||
}
|
||||
}
|
||||
|
||||
private MappedStatement copyFromNewSql(MappedStatement ms, BoundSql boundSql, String sql, List<ParameterMapping> parameterMappings, Object parameter) {
|
||||
BoundSql newBoundSql = copyFromBoundSql(ms, boundSql, sql, parameterMappings, parameter);
|
||||
return copyFromMappedStatement(ms, new BoundSqlSqlSource(newBoundSql));
|
||||
}
|
||||
|
||||
private BoundSql copyFromBoundSql(MappedStatement ms, BoundSql boundSql, String sql, List<ParameterMapping> parameterMappings, Object parameter) {
|
||||
BoundSql newBoundSql = new BoundSql(ms.getConfiguration(), sql, parameterMappings, parameter);
|
||||
for (ParameterMapping mapping : boundSql.getParameterMappings()) {
|
||||
String prop = mapping.getProperty();
|
||||
if (boundSql.hasAdditionalParameter(prop)) {
|
||||
newBoundSql.setAdditionalParameter(prop, boundSql.getAdditionalParameter(prop));
|
||||
}
|
||||
}
|
||||
return newBoundSql;
|
||||
}
|
||||
|
||||
// see: MapperBuilderAssistant
|
||||
private MappedStatement copyFromMappedStatement(MappedStatement ms, SqlSource newSqlSource) {
|
||||
Builder builder = new Builder(ms.getConfiguration(), ms.getId(), newSqlSource, ms.getSqlCommandType());
|
||||
builder.resource(ms.getResource());
|
||||
builder.fetchSize(ms.getFetchSize());
|
||||
builder.statementType(ms.getStatementType());
|
||||
builder.keyGenerator(ms.getKeyGenerator());
|
||||
if (Checks.isNotEmpty(ms.getKeyProperties())) {
|
||||
StringBuilder keyProperties = new StringBuilder();
|
||||
for (String keyProperty : ms.getKeyProperties()) {
|
||||
keyProperties.append(keyProperty).append(",");
|
||||
}
|
||||
keyProperties.delete(keyProperties.length() - 1, keyProperties.length());
|
||||
builder.keyProperty(keyProperties.toString());
|
||||
}
|
||||
|
||||
// setStatementTimeout()
|
||||
builder.timeout(ms.getTimeout());
|
||||
|
||||
// setStatementResultMap()
|
||||
builder.parameterMap(ms.getParameterMap());
|
||||
|
||||
// setStatementResultMap()
|
||||
builder.resultMaps(ms.getResultMaps());
|
||||
builder.resultSetType(ms.getResultSetType());
|
||||
|
||||
// setStatementCache()
|
||||
builder.cache(ms.getCache());
|
||||
builder.flushCacheRequired(ms.isFlushCacheRequired());
|
||||
builder.useCache(ms.isUseCache());
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public Object plugin(Object target) {
|
||||
return Plugin.wrap(target, this);
|
||||
}
|
||||
|
||||
public void setProperties(Properties properties) {
|
||||
PropertiesHelper propertiesHelper = new PropertiesHelper(properties);
|
||||
String dialectClass = propertiesHelper.getRequiredString("dialectClass");
|
||||
setDialectClass(dialectClass);
|
||||
setAsyncTotalCount(propertiesHelper.getBoolean("asyncTotalCount", false));
|
||||
setPoolMaxSize(propertiesHelper.getInt("poolMaxSize", 0));
|
||||
}
|
||||
|
||||
public static class BoundSqlSqlSource implements SqlSource {
|
||||
BoundSql boundSql;
|
||||
|
||||
public BoundSqlSqlSource(BoundSql boundSql) {
|
||||
this.boundSql = boundSql;
|
||||
}
|
||||
|
||||
public BoundSql getBoundSql(Object parameterObject) {
|
||||
return boundSql;
|
||||
}
|
||||
}
|
||||
|
||||
public void setDialectClass(String dialectClass) {
|
||||
//logger.debug("dialectClass: {} ", dialectClass);
|
||||
this.dialectClass = dialectClass;
|
||||
}
|
||||
|
||||
public void setAsyncTotalCount(boolean asyncTotalCount) {
|
||||
//logger.debug("asyncTotalCount: {} ", asyncTotalCount);
|
||||
this.asyncTotalCount = asyncTotalCount;
|
||||
}
|
||||
|
||||
public void setPoolMaxSize(int poolMaxSize) {
|
||||
|
||||
if (poolMaxSize > 0) {
|
||||
log.debug("poolMaxSize: {} ", poolMaxSize);
|
||||
Pool = Executors.newFixedThreadPool(poolMaxSize);
|
||||
} else {
|
||||
Pool = Executors.newCachedThreadPool();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis.paging.dialect;
|
||||
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.domain.PageBounds;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
|
||||
public class DB2Dialect extends Dialect {
|
||||
|
||||
public DB2Dialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
|
||||
super(mappedStatement, parameterObject, pageBounds);
|
||||
}
|
||||
|
||||
private static String getRowNumber(String sql) {
|
||||
StringBuilder rownumber = new StringBuilder(50)
|
||||
.append("rownumber() over(");
|
||||
|
||||
int orderByIndex = sql.toLowerCase().indexOf("order by");
|
||||
|
||||
if (orderByIndex > 0 && !hasDistinct(sql)) {
|
||||
rownumber.append(sql.substring(orderByIndex));
|
||||
}
|
||||
|
||||
rownumber.append(") as rownumber_,");
|
||||
|
||||
return rownumber.toString();
|
||||
}
|
||||
|
||||
private static boolean hasDistinct(String sql) {
|
||||
return sql.toLowerCase().contains("select distinct");
|
||||
}
|
||||
|
||||
protected String getLimitString(String sql, String offsetName, int offset,
|
||||
String limitName, int limit) {
|
||||
int startOfSelect = sql.toLowerCase().indexOf("select");
|
||||
|
||||
StringBuilder pagingSelect = new StringBuilder(sql.length() + 100)
|
||||
.append(sql.substring(0, startOfSelect)) // add the comment
|
||||
.append("select * from ( select ") // nest the main query in an
|
||||
// outer select
|
||||
.append(getRowNumber(sql)); // add the rownnumber bit into the
|
||||
// outer query select list
|
||||
|
||||
if (hasDistinct(sql)) {
|
||||
pagingSelect.append(" row_.* from ( ") // add another (inner) nested
|
||||
// select
|
||||
.append(sql.substring(startOfSelect)) // add the main query
|
||||
.append(" ) as row_"); // close off the inner nested select
|
||||
} else {
|
||||
pagingSelect.append(sql.substring(startOfSelect + 6)); // add the
|
||||
// main
|
||||
// query
|
||||
}
|
||||
|
||||
pagingSelect.append(" ) as temp_ where rownumber_ ");
|
||||
|
||||
// add the restriction to the outer select
|
||||
if (offset > 0) {
|
||||
pagingSelect.append("between ?+1 and ?");
|
||||
setPageParameter(offsetName, offset, Integer.class);
|
||||
setPageParameter("__offsetEnd", offset + limit, Integer.class);
|
||||
} else {
|
||||
pagingSelect.append("<= ?");
|
||||
setPageParameter(limitName, limit, Integer.class);
|
||||
}
|
||||
|
||||
return pagingSelect.toString();
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis.paging.dialect;
|
||||
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.domain.PageBounds;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
|
||||
|
||||
public class DerbyDialect extends Dialect {
|
||||
|
||||
public DerbyDialect(MappedStatement mappedStatement,
|
||||
Object parameterObject, PageBounds pageBounds) {
|
||||
super(mappedStatement, parameterObject, pageBounds);
|
||||
}
|
||||
|
||||
public boolean supportsLimit() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean supportsLimitOffset() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getLimitString(String sql, int offset,
|
||||
String offsetPlaceholder, int limit, String limitPlaceholder) {
|
||||
|
||||
return sql +
|
||||
" offset " + offsetPlaceholder + " rows fetch next "
|
||||
+ limitPlaceholder + " rows only";
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,134 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis.paging.dialect;
|
||||
|
||||
import cokr.xit.fims.framework.support.LoggerHelper;
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.domain.Order;
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.domain.PageBounds;
|
||||
import org.apache.ibatis.mapping.BoundSql;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
import org.apache.ibatis.mapping.ParameterMapping;
|
||||
import org.apache.ibatis.session.RowBounds;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Dialect {
|
||||
@SuppressWarnings("unused")
|
||||
private static final Logger log = LoggerHelper.getLogger();
|
||||
|
||||
protected MappedStatement mappedStatement;
|
||||
protected PageBounds pageBounds;
|
||||
protected Object parameterObject;
|
||||
protected BoundSql boundSql;
|
||||
protected List<ParameterMapping> parameterMappings;
|
||||
protected Map<String, Object> pageParameters = new HashMap<String, Object>();
|
||||
|
||||
private String pageSQL;
|
||||
private String countSQL;
|
||||
|
||||
public Dialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
|
||||
this.mappedStatement = mappedStatement;
|
||||
this.parameterObject = parameterObject;
|
||||
this.pageBounds = pageBounds;
|
||||
init();
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
protected void init() {
|
||||
boundSql = mappedStatement.getBoundSql(parameterObject);
|
||||
parameterMappings = new ArrayList(boundSql.getParameterMappings());
|
||||
if (parameterObject instanceof Map) {
|
||||
pageParameters.putAll((Map) parameterObject);
|
||||
} else {
|
||||
for (ParameterMapping parameterMapping : parameterMappings) {
|
||||
pageParameters.put(parameterMapping.getProperty(), parameterObject);
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder bufferSql = new StringBuilder(boundSql.getSql().trim());
|
||||
if (bufferSql.lastIndexOf(";") == bufferSql.length() - 1) {
|
||||
bufferSql.deleteCharAt(bufferSql.length() - 1);
|
||||
}
|
||||
String sql = bufferSql.toString();
|
||||
pageSQL = sql;
|
||||
if (pageBounds.getOrders() != null && !pageBounds.getOrders().isEmpty()) {
|
||||
pageSQL = getSortString(sql, pageBounds.getOrders());
|
||||
}
|
||||
//log.debug("$$$$$$$$$$$$$$$ page::{}, offset::{}", pageBounds.getPage(), pageBounds.getOffset());
|
||||
if (pageBounds.getOffset() != RowBounds.NO_ROW_OFFSET || pageBounds.getLimit() != RowBounds.NO_ROW_LIMIT) {
|
||||
pageSQL = getLimitString(pageSQL, "__offset", pageBounds.getOffset(), "__limit", pageBounds.getLimit());
|
||||
}
|
||||
countSQL = getCountString(sql);
|
||||
}
|
||||
|
||||
public List<ParameterMapping> getParameterMappings() {
|
||||
return parameterMappings;
|
||||
}
|
||||
|
||||
public Object getParameterObject() {
|
||||
return pageParameters;
|
||||
}
|
||||
|
||||
public String getPageSQL() {
|
||||
return pageSQL;
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
protected void setPageParameter(String name, Object value, Class type) {
|
||||
ParameterMapping parameterMapping = new ParameterMapping.Builder(mappedStatement.getConfiguration(), name, type).build();
|
||||
parameterMappings.add(parameterMapping);
|
||||
pageParameters.put(name, value);
|
||||
}
|
||||
|
||||
public String getCountSQL() {
|
||||
return countSQL;
|
||||
}
|
||||
|
||||
/**
|
||||
* page query make
|
||||
*
|
||||
* @param sql sql
|
||||
* @param offsetName offsetName
|
||||
* @param offset offset
|
||||
* @param limitName limitName
|
||||
* @param limit limit
|
||||
* @return String query
|
||||
*/
|
||||
protected String getLimitString(String sql, String offsetName, int offset, String limitName, int limit) {
|
||||
throw new UnsupportedOperationException("paged queries not supported");
|
||||
}
|
||||
|
||||
/**
|
||||
* get total count SQL
|
||||
*
|
||||
* @param sql SQL
|
||||
* @return String count sql
|
||||
*/
|
||||
protected String getCountString(String sql) {
|
||||
return "select count(1) from (\n" + sql + "\n) tmp_count";
|
||||
}
|
||||
|
||||
/**
|
||||
* ordered sql
|
||||
*
|
||||
* @param sql SQL
|
||||
* @param orders ordered field List
|
||||
* @return 정렬구문까지 포함된 sql
|
||||
*/
|
||||
protected String getSortString(String sql, List<Order> orders) {
|
||||
if (orders == null || orders.isEmpty()) {
|
||||
return sql;
|
||||
}
|
||||
|
||||
StringBuilder buffer = new StringBuilder("select * from (\n").append(sql).append("\n) temp_order order by ");
|
||||
for (Order order : orders) {
|
||||
if (order != null) {
|
||||
buffer.append(order.toString()).append(", ");
|
||||
}
|
||||
}
|
||||
buffer.delete(buffer.length() - 2, buffer.length());
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis.paging.dialect;
|
||||
|
||||
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.domain.PageBounds;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
|
||||
public class H2Dialect extends Dialect {
|
||||
|
||||
public H2Dialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
|
||||
super(mappedStatement, parameterObject, pageBounds);
|
||||
}
|
||||
|
||||
protected String getLimitString(String sql, String offsetName,int offset, String limitName, int limit) {
|
||||
return sql +
|
||||
((offset > 0) ? " limit " + String.valueOf(limit) + " offset " + String.valueOf(offset) : " limit " + String.valueOf(limit));
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis.paging.dialect;
|
||||
|
||||
import cokr.xit.fims.framework.support.LoggerHelper;
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.domain.PageBounds;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public class HSQLDialect extends Dialect {
|
||||
@SuppressWarnings("unused")
|
||||
private static final Logger log = LoggerHelper.getLogger();
|
||||
|
||||
public HSQLDialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
|
||||
super(mappedStatement, parameterObject, pageBounds);
|
||||
}
|
||||
|
||||
protected String getLimitString(String sql, String offsetName, int offset, String limitName, int limit) {
|
||||
// log.debug("$$$$$$$$$$$$$$$ offset::{}, limit::{}", offset, limit);
|
||||
boolean hasOffset = offset > 0;
|
||||
return new StringBuffer(sql.length() + 10)
|
||||
.append(sql)
|
||||
.insert(sql.toLowerCase().indexOf("select") + 6,
|
||||
hasOffset ? " limit " + String.valueOf(offset) + " " + String.valueOf(limit) : " top " + String.valueOf(limit)).toString();
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis.paging.dialect;
|
||||
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.domain.PageBounds;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
|
||||
public class MySQLDialect extends Dialect {
|
||||
|
||||
public MySQLDialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
|
||||
super(mappedStatement, parameterObject, pageBounds);
|
||||
}
|
||||
|
||||
protected String getLimitString(String sql, String offsetName, int offset, String limitName, int limit) {
|
||||
StringBuilder buffer = new StringBuilder(sql.length() + 20).append(sql);
|
||||
if (offset > 0) {
|
||||
buffer.append("\n limit ?, ?");
|
||||
setPageParameter(offsetName, offset, Integer.class);
|
||||
setPageParameter(limitName, limit, Integer.class);
|
||||
} else {
|
||||
buffer.append("\n limit ?");
|
||||
setPageParameter(limitName, limit, Integer.class);
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis.paging.dialect;
|
||||
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.domain.PageBounds;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
|
||||
public class OracleDialect extends Dialect {
|
||||
|
||||
public OracleDialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
|
||||
super(mappedStatement, parameterObject, pageBounds);
|
||||
}
|
||||
|
||||
protected String getLimitString(String sql, String offsetName, int offset, String limitName, int limit) {
|
||||
sql = sql.trim();
|
||||
boolean isForUpdate = false;
|
||||
if (sql.toLowerCase().endsWith(" for update")) {
|
||||
sql = sql.substring(0, sql.length() - 11);
|
||||
isForUpdate = true;
|
||||
}
|
||||
|
||||
StringBuilder pagingSelect = new StringBuilder(sql.length() + 100);
|
||||
if (offset > 0) {
|
||||
pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");
|
||||
} else {
|
||||
pagingSelect.append("select * from ( ");
|
||||
}
|
||||
pagingSelect.append(sql);
|
||||
if (offset > 0) {
|
||||
pagingSelect.append(" ) row_ ) where rownum_ <= ? and rownum_ > ?");
|
||||
setPageParameter("__offsetEnd", offset + limit, Integer.class);
|
||||
setPageParameter(offsetName, offset, Integer.class);
|
||||
} else {
|
||||
pagingSelect.append(" ) where rownum <= ?");
|
||||
setPageParameter(limitName, limit, Integer.class);
|
||||
}
|
||||
|
||||
if (isForUpdate) {
|
||||
pagingSelect.append(" for update");
|
||||
}
|
||||
|
||||
return pagingSelect.toString();
|
||||
}
|
||||
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis.paging.dialect;
|
||||
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.domain.PageBounds;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
|
||||
/**
|
||||
* @author badqiu
|
||||
* @author miemiedev
|
||||
*/
|
||||
public class PostgreSQLDialect extends Dialect{
|
||||
|
||||
public PostgreSQLDialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
|
||||
super(mappedStatement, parameterObject, pageBounds);
|
||||
}
|
||||
|
||||
protected String getLimitString(String sql, String offsetName,int offset, String limitName, int limit) {
|
||||
StringBuilder buffer = new StringBuilder( sql.length()+20 ).append(sql);
|
||||
if(offset > 0){
|
||||
buffer.append(" limit ? offset ?");
|
||||
setPageParameter(limitName, limit, Integer.class);
|
||||
setPageParameter(offsetName, offset, Integer.class);
|
||||
|
||||
}else{
|
||||
buffer.append(" limit ?");
|
||||
setPageParameter(limitName, limit, Integer.class);
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis.paging.dialect;
|
||||
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.domain.PageBounds;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
|
||||
// Hibernate BUG: http://opensource.atlassian.com/projects/hibernate/browse/HHH-2655
|
||||
// SQLServer2005Dialect
|
||||
public class SQLServer2005Dialect extends Dialect{
|
||||
|
||||
public SQLServer2005Dialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
|
||||
super(mappedStatement, parameterObject, pageBounds);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a LIMIT clause to the given SQL SELECT
|
||||
* The LIMIT SQL will look like:
|
||||
* WITH query AS (SELECT TOP 100 percent ROW_NUMBER() OVER (ORDER BY CURRENT_TIMESTAMP) as __row_number__, * from table_name)
|
||||
* SELECT * FROM query WHERE __row_number__ BETWEEN :offset and :lastRows ORDER BY __row_number__
|
||||
*
|
||||
* @param sql The SQL statement to base the limit query off of.
|
||||
* @param offset Offset of the first row to be returned by the query (zero-based)
|
||||
* @param limit Maximum number of rows to be returned by the query
|
||||
* @return A new SQL statement with the LIMIT clause applied.
|
||||
*/
|
||||
protected String getLimitString(String sql, String offsetName,int offset, String limitName, int limit) {
|
||||
StringBuilder pagingBuilder = new StringBuilder();
|
||||
String orderby = getOrderByPart(sql);
|
||||
String distinctStr = "";
|
||||
|
||||
String loweredString = sql.toLowerCase();
|
||||
String sqlPartString = sql;
|
||||
if (loweredString.trim().startsWith("select")) {
|
||||
int index = 6;
|
||||
if (loweredString.startsWith("select distinct")) {
|
||||
distinctStr = "DISTINCT ";
|
||||
index = 15;
|
||||
}
|
||||
sqlPartString = sqlPartString.substring(index);
|
||||
}
|
||||
pagingBuilder.append(sqlPartString);
|
||||
|
||||
// if no ORDER BY is specified use fake ORDER BY field to avoid errors
|
||||
if (orderby == null || orderby.length() == 0) {
|
||||
orderby = "ORDER BY CURRENT_TIMESTAMP";
|
||||
}
|
||||
|
||||
StringBuilder result = new StringBuilder();
|
||||
result.append("WITH query AS (SELECT ")
|
||||
.append(distinctStr)
|
||||
.append("TOP 100 PERCENT ")
|
||||
.append(" ROW_NUMBER() OVER (")
|
||||
.append(orderby)
|
||||
.append(") as __row_number__, ")
|
||||
.append(pagingBuilder)
|
||||
.append(") SELECT * FROM query WHERE __row_number__ > ? AND __row_number__ <= ?")
|
||||
.append(" ORDER BY __row_number__");
|
||||
setPageParameter(offsetName,offset,Integer.class);
|
||||
setPageParameter("__offsetEnd",offset+limit,Integer.class);
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
static String getOrderByPart(String sql) {
|
||||
String loweredString = sql.toLowerCase();
|
||||
int orderByIndex = loweredString.indexOf("order by");
|
||||
if (orderByIndex != -1) {
|
||||
// if we find a new "order by" then we need to ignore
|
||||
// the previous one since it was probably used for a subquery
|
||||
return sql.substring(orderByIndex);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis.paging.dialect;
|
||||
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.domain.PageBounds;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
|
||||
public class SQLServerDialect extends Dialect{
|
||||
|
||||
public SQLServerDialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
|
||||
super(mappedStatement, parameterObject, pageBounds);
|
||||
}
|
||||
|
||||
|
||||
static int getAfterSelectInsertPoint(String sql) {
|
||||
int selectIndex = sql.toLowerCase().indexOf( "select" );
|
||||
final int selectDistinctIndex = sql.toLowerCase().indexOf( "select distinct" );
|
||||
return selectIndex + ( selectDistinctIndex == selectIndex ? 15 : 6 );
|
||||
}
|
||||
|
||||
|
||||
protected String getLimitString(String sql, String offsetName,int offset, String limitName, int limit) {
|
||||
if ( offset > 0 ) {
|
||||
throw new UnsupportedOperationException( "sql server has no offset" );
|
||||
}
|
||||
setPageParameter(limitName, limit, Integer.class);
|
||||
return new StringBuffer( sql.length() + 8 ).append( sql ).insert( getAfterSelectInsertPoint( sql ), " top " + limit ).toString();
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis.paging.dialect;
|
||||
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.domain.PageBounds;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
|
||||
public class SybaseDialect extends Dialect{
|
||||
|
||||
public SybaseDialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
|
||||
super(mappedStatement, parameterObject, pageBounds);
|
||||
}
|
||||
|
||||
|
||||
protected String getLimitString(String sql, String offsetName,int offset, String limitName, int limit) {
|
||||
throw new UnsupportedOperationException( "paged queries not supported" );
|
||||
}
|
||||
|
||||
}
|
@ -1,152 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis.paging.domain;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Order implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Direction direction;
|
||||
private String property;
|
||||
private String orderExpr;
|
||||
|
||||
public Order(String property, Direction direction, String orderExpr) {
|
||||
this.direction = direction;
|
||||
this.property = property;
|
||||
this.orderExpr = orderExpr;
|
||||
}
|
||||
|
||||
public Direction getDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
public String getProperty() {
|
||||
return property;
|
||||
}
|
||||
|
||||
public String getOrderExpr() {
|
||||
return orderExpr;
|
||||
}
|
||||
|
||||
public void setDirection(Direction direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
public void setProperty(String property) {
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
public void setOrderExpr(String orderExpr) {
|
||||
this.orderExpr = orderExpr;
|
||||
}
|
||||
|
||||
public static boolean isSQLInjection(String str) {
|
||||
String INJECTION_REGEX = "[A-Za-z0-9\\_\\-\\+\\.]+";
|
||||
return !Pattern.matches(INJECTION_REGEX, str);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (isSQLInjection(property)) {
|
||||
throw new IllegalArgumentException("SQLInjection property: " + property);
|
||||
}
|
||||
if (orderExpr != null && orderExpr.contains("?")) {
|
||||
String[] exprs = orderExpr.split("\\?");
|
||||
if (exprs.length == 2) {
|
||||
return String.format(orderExpr.replaceAll("\\?", "%s"), property) + (direction == null ? "" : " " + direction.name());
|
||||
}
|
||||
return String.format(orderExpr.replaceAll("\\?", "%s"), property, direction == null ? "" : " " + direction.name());
|
||||
}
|
||||
return property + (direction == null ? "" : " " + direction.name());
|
||||
}
|
||||
|
||||
public static List<Order> formString(String orderSegment) {
|
||||
return formString(orderSegment, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param orderSegment String
|
||||
* ex: "id.asc,code.desc" or "code.desc"
|
||||
* @param orderExpr String
|
||||
* @return List<Order> List
|
||||
*/
|
||||
public static List<Order> formString(String orderSegment, String orderExpr) {
|
||||
if (Objects.isNull(orderSegment) || Objects.equals(StringUtils.EMPTY, orderSegment.trim())) {
|
||||
return new ArrayList<Order>(0);
|
||||
}
|
||||
|
||||
List<Order> results = new ArrayList<Order>();
|
||||
String[] orderSegments = orderSegment.trim().split(",");
|
||||
for (int i = 0; i < orderSegments.length; i++) {
|
||||
String sortSegment = orderSegments[i];
|
||||
Order order = _formString(sortSegment, orderExpr);
|
||||
if (order != null) {
|
||||
results.add(order);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private static Order _formString(String orderSegment, String orderExpr) {
|
||||
|
||||
if (Objects.isNull(orderSegment) || Objects.equals(StringUtils.EMPTY, orderSegment.trim())
|
||||
|| orderSegment.startsWith("null.")
|
||||
|| orderSegment.startsWith(".")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String[] array = orderSegment.trim().split("\\.");
|
||||
if (array.length != 1 && array.length != 2) {
|
||||
throw new IllegalArgumentException(
|
||||
"orderSegment pattern must be {property}.{direction}, input is: " + orderSegment);
|
||||
}
|
||||
|
||||
return create(array[0], array.length == 2 ? array[1] : "asc", orderExpr);
|
||||
}
|
||||
|
||||
public static Order create(String property, String direction) {
|
||||
return create(property, direction, null);
|
||||
}
|
||||
|
||||
/**
|
||||
*<pre>
|
||||
* @param property property
|
||||
* @param direction direction
|
||||
* @param orderExpr
|
||||
* Oracle query에 특정 column의 대소문자 구분없이 정렬 방법 (case-insensitive sort)
|
||||
* placeholder is "?", in oracle like:
|
||||
* "nlssort( ? ,'NLS_SORT=SCHINESE_PINYIN_M')". Warning: you must
|
||||
* prevent orderExpr SQL injection.
|
||||
* Oracle session level에서 "nls_sort"의 값을 다음과 같이 설정함으로서 "nlssort"함수를 번번히 사용할 필요는 없습니다.
|
||||
* SQL: alter session set nls_sort=generic_m_ai;
|
||||
* Session altered.
|
||||
* @return Order Order
|
||||
* </pre>
|
||||
*/
|
||||
public static Order create(String property, String direction, String orderExpr) {
|
||||
return new Order(property, Direction.fromString(direction), orderExpr);
|
||||
}
|
||||
|
||||
/**
|
||||
* PropertyPath implements the pairing of an {@link Direction} and a
|
||||
* property. It is used to provide input for
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public static enum Direction {
|
||||
ASC, DESC;
|
||||
public static Direction fromString(String value) {
|
||||
try {
|
||||
return Direction.valueOf(value.toUpperCase(Locale.US));
|
||||
} catch (Exception e) {
|
||||
return ASC;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,159 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis.paging.domain;
|
||||
|
||||
import org.apache.ibatis.session.RowBounds;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* <pre>
|
||||
* TODO 프로젝트에 맞춰 페이지 정보 내용 define
|
||||
* new PageBounds(limit)
|
||||
* new PageBounds(page, limit)
|
||||
* new PageBounds("field, field")
|
||||
* new PageBounds(page, limit, "field, field.desc")
|
||||
* new PageBounds(page, limit, "field.asc, filed.desc")
|
||||
* @author minuk
|
||||
* </pre>
|
||||
*
|
||||
*/
|
||||
public class PageBounds extends RowBounds implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public final static int NO_PAGE = 1;
|
||||
protected int pageNum = NO_PAGE;
|
||||
protected int limit = NO_ROW_LIMIT;
|
||||
protected List<Order> orders = new ArrayList<Order>();
|
||||
protected boolean containsTotalCount;
|
||||
protected Boolean asyncTotalCount;
|
||||
|
||||
public PageBounds() {
|
||||
containsTotalCount = false;
|
||||
}
|
||||
|
||||
public PageBounds(RowBounds rowBounds) {
|
||||
if (rowBounds instanceof PageBounds) {
|
||||
PageBounds pageBounds = (PageBounds) rowBounds;
|
||||
this.pageNum = pageBounds.pageNum;
|
||||
this.limit = pageBounds.limit;
|
||||
this.orders = pageBounds.orders;
|
||||
this.containsTotalCount = pageBounds.containsTotalCount;
|
||||
this.asyncTotalCount = pageBounds.asyncTotalCount;
|
||||
} else {
|
||||
this.pageNum = (rowBounds.getOffset() / rowBounds.getLimit()) + 1;
|
||||
this.limit = rowBounds.getLimit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Query TOP N, default containsTotalCount = false
|
||||
* @param limit limit
|
||||
*/
|
||||
public PageBounds(int limit) {
|
||||
this.limit = limit;
|
||||
this.containsTotalCount = false;
|
||||
}
|
||||
|
||||
public PageBounds(int page, int limit) {
|
||||
this(page, limit, new ArrayList<Order>(), true);
|
||||
}
|
||||
|
||||
public PageBounds(int page, int limit, boolean containsTotalCount) {
|
||||
this(page, limit, new ArrayList<Order>(), containsTotalCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Just sorting, default containsTotalCount = false
|
||||
* @param orders orders
|
||||
*/
|
||||
public PageBounds(List<Order> orders) {
|
||||
this(NO_PAGE, NO_ROW_LIMIT, orders, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Just sorting, default containsTotalCount = false
|
||||
* @param order order
|
||||
*/
|
||||
public PageBounds(Order... order) {
|
||||
this(NO_PAGE, NO_ROW_LIMIT, order);
|
||||
this.containsTotalCount = false;
|
||||
}
|
||||
|
||||
public PageBounds(int page, int limit, Order... order) {
|
||||
this(page, limit, Arrays.asList(order), true);
|
||||
}
|
||||
|
||||
public PageBounds(int pageNum, int limit, List<Order> orders) {
|
||||
this(pageNum, limit, orders, true);
|
||||
}
|
||||
|
||||
public PageBounds(int pageNum, int limit, List<Order> orders,
|
||||
boolean containsTotalCount) {
|
||||
this.pageNum = pageNum;
|
||||
this.limit = limit;
|
||||
this.orders = orders;
|
||||
this.containsTotalCount = containsTotalCount;
|
||||
}
|
||||
|
||||
public int getPageNum() {
|
||||
return pageNum;
|
||||
}
|
||||
|
||||
public void setPageNum(int pageNum) {
|
||||
this.pageNum = pageNum;
|
||||
}
|
||||
|
||||
public int getLimit() {
|
||||
return limit;
|
||||
}
|
||||
|
||||
public void setLimit(int limit) {
|
||||
this.limit = limit;
|
||||
}
|
||||
|
||||
public boolean isContainsTotalCount() {
|
||||
return containsTotalCount;
|
||||
}
|
||||
|
||||
public void setContainsTotalCount(boolean containsTotalCount) {
|
||||
this.containsTotalCount = containsTotalCount;
|
||||
}
|
||||
|
||||
public List<Order> getOrders() {
|
||||
return orders;
|
||||
}
|
||||
|
||||
public void setOrders(List<Order> orders) {
|
||||
this.orders = orders;
|
||||
}
|
||||
|
||||
public Boolean getAsyncTotalCount() {
|
||||
return asyncTotalCount;
|
||||
}
|
||||
|
||||
public void setAsyncTotalCount(Boolean asyncTotalCount) {
|
||||
this.asyncTotalCount = asyncTotalCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOffset() {
|
||||
if (pageNum >= 1) {
|
||||
return (pageNum - 1) * limit;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PageBounds{" + "pageNum=" + pageNum +
|
||||
", limit=" + limit +
|
||||
", orders=" + orders +
|
||||
", containsTotalCount=" + containsTotalCount +
|
||||
", asyncTotalCount=" + asyncTotalCount +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis.paging.domain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
public class PageList<E> extends ArrayList<E> {
|
||||
private static final long serialVersionUID = 1412759446332294208L;
|
||||
|
||||
private Paginator paginator;
|
||||
|
||||
public PageList() {
|
||||
}
|
||||
|
||||
public PageList(Collection<? extends E> c) {
|
||||
super(c);
|
||||
}
|
||||
|
||||
public PageList(Collection<? extends E> c, Paginator p) {
|
||||
super(c);
|
||||
this.paginator = p;
|
||||
}
|
||||
|
||||
public PageList(Paginator p) {
|
||||
this.paginator = p;
|
||||
}
|
||||
|
||||
public Paginator getPaginator() {
|
||||
return paginator;
|
||||
}
|
||||
|
||||
}
|
@ -1,142 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis.paging.domain;
|
||||
|
||||
import cokr.xit.fims.framework.support.mybatis.PagingConstants;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class Paginator implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final int limit;
|
||||
private int pageNum = 1;
|
||||
private final int totalSize;
|
||||
|
||||
public Paginator(int pageNum, int limit, int totalSize) {
|
||||
super();
|
||||
this.limit = limit;
|
||||
this.totalSize = totalSize;
|
||||
this.pageNum = computePageNo(pageNum);
|
||||
}
|
||||
|
||||
public void setSessionPagination(Paginator paginator){
|
||||
RequestContextHolder.currentRequestAttributes().setAttribute(PagingConstants.Session.PAGE_INFO.getCode(), paginator, RequestAttributes.SCOPE_REQUEST);
|
||||
}
|
||||
|
||||
public int getPageNum() {
|
||||
return pageNum;
|
||||
}
|
||||
|
||||
public void setPageNum(int pageNum) {
|
||||
this.pageNum = pageNum;
|
||||
}
|
||||
|
||||
public int getLimit() {
|
||||
return limit;
|
||||
}
|
||||
|
||||
public int getTotalSize() {
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
public boolean isFirstPage() {
|
||||
return pageNum <= 1;
|
||||
}
|
||||
|
||||
public boolean isLastPage() {
|
||||
return pageNum >= getTotalPages();
|
||||
}
|
||||
|
||||
public int getPrePage() {
|
||||
if (isHasPrePage()) {
|
||||
return pageNum - 1;
|
||||
} else {
|
||||
return pageNum;
|
||||
}
|
||||
}
|
||||
|
||||
public int getNextPage() {
|
||||
if (isHasNextPage()) {
|
||||
return pageNum + 1;
|
||||
} else {
|
||||
return pageNum;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDisabledPage(int pageNum) {
|
||||
return ((pageNum < 1) || (pageNum > getTotalPages()) || (pageNum == this.pageNum));
|
||||
}
|
||||
|
||||
public boolean isHasPrePage() {
|
||||
return (pageNum - 1 >= 1);
|
||||
}
|
||||
|
||||
public boolean isHasNextPage() {
|
||||
return (pageNum + 1 <= getTotalPages());
|
||||
}
|
||||
|
||||
public int getStartRow() {
|
||||
if (getLimit() <= 0 || totalSize <= 0)
|
||||
return 0;
|
||||
return pageNum > 0 ? (pageNum - 1) * getLimit() + 1 : 0;
|
||||
}
|
||||
|
||||
public int getEndRow() {
|
||||
return pageNum > 0 ? Math.min(limit * pageNum, getTotalSize()) : 0;
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return pageNum > 0 ? (pageNum - 1) * getLimit() : 0;
|
||||
}
|
||||
|
||||
public int getTotalPages() {
|
||||
if (totalSize <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (limit <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int count = totalSize / limit;
|
||||
if (totalSize % limit > 0) {
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
protected int computePageNo(int pageNum) {
|
||||
return computePageNumber(pageNum, limit, totalSize);
|
||||
}
|
||||
|
||||
private static int computeLastPageNumber(int totalItems, int pageSize) {
|
||||
if (pageSize <= 0)
|
||||
return 1;
|
||||
int result = (int) (totalItems % pageSize == 0 ? totalItems / pageSize
|
||||
: totalItems / pageSize + 1);
|
||||
if (result <= 1)
|
||||
result = 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int computePageNumber(int pageNum, int pageSize, int totalItems) {
|
||||
if (pageNum <= 1) {
|
||||
return 1;
|
||||
}
|
||||
if (Integer.MAX_VALUE == pageNum
|
||||
|| pageNum > computeLastPageNumber(totalItems, pageSize)) { // last
|
||||
// page
|
||||
return computeLastPageNumber(totalItems, pageSize);
|
||||
}
|
||||
return pageNum;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Paginator" +
|
||||
"{pageNum=" + pageNum +
|
||||
", limit=" + limit +
|
||||
", totalSize=" + totalSize +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis.paging.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.core.Version;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.domain.PageList;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Converter의 ObjectMapper 확장
|
||||
* ResponseBody 사용시 호출
|
||||
* Converter 실행시 Paging 정보 추가 return
|
||||
* page, limit(row/page), totalCount, offset(쿼리조회시작row), startRow, prePage, nextPage, endRow, totalPages
|
||||
* boolean 값 : firstPage, lastPage, hasPrePage, hasNextPage
|
||||
* </pre>
|
||||
* @author minuk
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class PageListJsonMapper extends ObjectMapper{
|
||||
|
||||
public PageListJsonMapper() {
|
||||
//JSON data pretty 정렬
|
||||
enable(SerializationFeature.INDENT_OUTPUT);
|
||||
SimpleModule module = new SimpleModule("PageListJSONModule", new Version(1, 0, 0, null, null, null));
|
||||
//module.addSerializer(PageList.class, new PageListJsonSerializer(this));
|
||||
module.addSerializer(PageList.class, new PageListJsonSerializer());
|
||||
registerModule(module);
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis.paging.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import cokr.xit.fims.framework.support.LoggerHelper;
|
||||
import cokr.xit.fims.framework.support.mybatis.PagingConstants;
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.domain.PageList;
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.domain.Paginator;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
//TODO PageListJsonSerializer - Converting시 data attribute name 정의 - property에서 읽어 온다
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class PageListJsonSerializer extends JsonSerializer<PageList>{
|
||||
private final Logger log = LoggerHelper.getLogger();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void serialize(PageList value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
|
||||
Paginator paginator = value.getPaginator();
|
||||
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("totalSize", paginator.getTotalSize());
|
||||
map.put("totalPages", paginator.getTotalPages());
|
||||
map.put("pageNum", paginator.getPageNum());
|
||||
map.put("limit", paginator.getLimit());
|
||||
// Query Data
|
||||
map.put(PagingConstants.RSLT_ATTR_NAME, new ArrayList(value));
|
||||
// map.put(DEFAULT_RESPONSE_BODY_DATA_NAME, new ArrayList(value));
|
||||
map.put("startRow", paginator.getStartRow());
|
||||
map.put("endRow", paginator.getEndRow());
|
||||
map.put("offset", paginator.getOffset());
|
||||
// map.put("slider", paginator.getSlider());
|
||||
map.put("prePage", paginator.getPrePage());
|
||||
map.put("nextPage", paginator.getNextPage());
|
||||
map.put("firstPage", paginator.isFirstPage());
|
||||
map.put("hasNextPage", paginator.isHasNextPage());
|
||||
map.put("hasPrePage", paginator.isHasPrePage());
|
||||
map.put("lastPage", paginator.isLastPage());
|
||||
|
||||
// mapper.writeValue(jgen, map);
|
||||
jgen.writeObject(map);
|
||||
log.debug("#########################################Paging infomation##########################################################");
|
||||
log.debug("{}", map);
|
||||
log.debug("###################################################################################################");
|
||||
|
||||
}
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis.paging.springmvc;
|
||||
|
||||
import cokr.xit.fims.framework.support.LoggerHelper;
|
||||
import cokr.xit.fims.framework.support.mybatis.PagingConstants.Session;
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.domain.Paginator;
|
||||
import org.slf4j.Logger;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* name+Paginator
|
||||
* ex) ModelAndView.addObject("data", Object) ==> dataPaginator
|
||||
* ResponseBody 형태의 call이 아닌경우 Paging 정보를 추가하여 return
|
||||
* TODO PageListAttrHandlerInterceptor - @ResponseBody 형태의 call인 경우는 정보 추가 불가 - 필요시 이 부분 처리 필요
|
||||
* TODO PageListAttrHandlerInterceptor - 페이지 정보 setting name 정의 - - property에서 읽어 온다
|
||||
*/
|
||||
public class PageListAttrHandlerInterceptor extends HandlerInterceptorAdapter {
|
||||
@SuppressWarnings("unused")
|
||||
private final Logger log = LoggerHelper.getLogger();
|
||||
// @Value(("#{conf['page.info']}"))
|
||||
// private String DEFAULT_PAGE_INFO_NAME;
|
||||
|
||||
public boolean preHandle(HttpServletRequest request,
|
||||
HttpServletResponse httpServletResponse, Object o) throws Exception {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse httpServletResponse, Object handler, ModelAndView mav) throws Exception {
|
||||
|
||||
Object pageObject = RequestContextHolder.getRequestAttributes().getAttribute(Session.PAGE_INFO.getCode(), RequestAttributes.SCOPE_REQUEST);
|
||||
|
||||
if(pageObject != null){
|
||||
Paginator paginator = (Paginator)pageObject;
|
||||
|
||||
if(mav == null) {
|
||||
request.setAttribute(Session.PAGE_INFO.getCode(), getPageInfoMap(paginator));
|
||||
return;
|
||||
|
||||
}else{
|
||||
mav.addObject(Session.PAGE_INFO.getCode(), getPageInfoMap(paginator));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse httpServletResponse, Object o, Exception e)
|
||||
throws Exception {
|
||||
}
|
||||
|
||||
private Map<String,Object> getPageInfoMap(Paginator paginator){
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
|
||||
map.put("totalSize", paginator.getTotalSize());
|
||||
map.put("totalPages", paginator.getTotalPages());
|
||||
map.put("pageNum", paginator.getPageNum());
|
||||
map.put("limit", paginator.getLimit());
|
||||
// Query Data : Paging 정보만 set 하면 되므로 필요 없다
|
||||
//map.put(FwConstants.DEFAULT_RESPONSE_BODY_DATA_NAME, new ArrayList<PageList>(pageList));
|
||||
map.put("startRow", paginator.getStartRow());
|
||||
map.put("endRow", paginator.getEndRow());
|
||||
map.put("offset", paginator.getOffset());
|
||||
//map.put("slider", paginator.getSlider());
|
||||
map.put("prePage", paginator.getPrePage());
|
||||
map.put("nextPage", paginator.getNextPage());
|
||||
map.put("firstPage", paginator.isFirstPage());
|
||||
map.put("hasNextPage", paginator.isHasNextPage());
|
||||
map.put("hasPrePage", paginator.isHasPrePage());
|
||||
map.put("lastPage", paginator.isLastPage());
|
||||
return map;
|
||||
}
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009-2012 The MyBatis Team
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cokr.xit.fims.framework.support.mybatis.paging.support;
|
||||
|
||||
import org.apache.ibatis.executor.ErrorContext;
|
||||
import org.apache.ibatis.executor.ExecutorException;
|
||||
import org.apache.ibatis.executor.parameter.ParameterHandler;
|
||||
import org.apache.ibatis.mapping.BoundSql;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
import org.apache.ibatis.mapping.ParameterMapping;
|
||||
import org.apache.ibatis.mapping.ParameterMode;
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
import org.apache.ibatis.session.Configuration;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import org.apache.ibatis.type.TypeHandler;
|
||||
import org.apache.ibatis.type.TypeHandlerRegistry;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
public class DefaultParameterHandler implements ParameterHandler {
|
||||
|
||||
private final TypeHandlerRegistry typeHandlerRegistry;
|
||||
|
||||
private final MappedStatement mappedStatement;
|
||||
private final Object parameterObject;
|
||||
private BoundSql boundSql;
|
||||
private Configuration configuration;
|
||||
|
||||
public DefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
|
||||
this.mappedStatement = mappedStatement;
|
||||
this.configuration = mappedStatement.getConfiguration();
|
||||
this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry();
|
||||
this.parameterObject = parameterObject;
|
||||
this.boundSql = boundSql;
|
||||
}
|
||||
|
||||
public Object getParameterObject() {
|
||||
return parameterObject;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public void setParameters(PreparedStatement ps) throws SQLException {
|
||||
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
|
||||
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
|
||||
if (parameterMappings != null) {
|
||||
MetaObject metaObject = parameterObject == null ? null : configuration.newMetaObject(parameterObject);
|
||||
for (int i = 0; i < parameterMappings.size(); i++) {
|
||||
ParameterMapping parameterMapping = parameterMappings.get(i);
|
||||
if (parameterMapping.getMode() != ParameterMode.OUT) {
|
||||
Object value;
|
||||
String propertyName = parameterMapping.getProperty();
|
||||
if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
|
||||
value = boundSql.getAdditionalParameter(propertyName);
|
||||
} else if (parameterObject == null) {
|
||||
value = null;
|
||||
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
|
||||
value = parameterObject;
|
||||
} else {
|
||||
value = metaObject == null ? null : metaObject.getValue(propertyName);
|
||||
}
|
||||
TypeHandler typeHandler = parameterMapping.getTypeHandler();
|
||||
if (typeHandler == null) {
|
||||
throw new ExecutorException(
|
||||
"There was no TypeHandler found for parameter "
|
||||
+ propertyName + " of statement "
|
||||
+ mappedStatement.getId());
|
||||
}
|
||||
JdbcType jdbcType = parameterMapping.getJdbcType();
|
||||
if (value == null && jdbcType == null)
|
||||
jdbcType = configuration.getJdbcTypeForNull();
|
||||
typeHandler.setParameter(ps, i + 1, value, jdbcType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,409 +0,0 @@
|
||||
package cokr.xit.fims.framework.support.mybatis.paging.support;
|
||||
|
||||
import cokr.xit.fims.framework.support.util.Checks;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* used :
|
||||
* public class ConnectionUtils {
|
||||
* static Properties properties = new Properties();
|
||||
* // ... do load properties
|
||||
*
|
||||
* // delegate to properties
|
||||
* static PropertiesHelper props = new PropertiesHelper(properties);
|
||||
* public static Connection getConnection() {
|
||||
* // use getRequiredProperty()
|
||||
* DriverManager.getConnection(props.getRequiredString("jdbc.url"));
|
||||
* }
|
||||
* }
|
||||
* new PropertiesHelper(properties,PropertiesHelper.SYSTEM_PROPERTIES_MODE_OVERRIDE)
|
||||
* </pre>
|
||||
*/
|
||||
public class PropertiesHelper {
|
||||
/** Never check system properties. */
|
||||
public static final int SYSTEM_PROPERTIES_MODE_NEVER = 0;
|
||||
|
||||
/**
|
||||
* Check system properties if not resolvable in the specified properties.
|
||||
* This is the default.
|
||||
*/
|
||||
public static final int SYSTEM_PROPERTIES_MODE_FALLBACK = 1;
|
||||
|
||||
/**
|
||||
* Check system properties first, before trying the specified properties.
|
||||
* This allows system properties to override any other property source.
|
||||
*/
|
||||
public static final int SYSTEM_PROPERTIES_MODE_OVERRIDE = 2;
|
||||
|
||||
private int systemPropertiesMode = SYSTEM_PROPERTIES_MODE_NEVER;
|
||||
private Properties p;
|
||||
|
||||
public PropertiesHelper(Properties p) {
|
||||
setProperties(p);
|
||||
}
|
||||
|
||||
public PropertiesHelper(Properties p, int systemPropertiesMode) {
|
||||
setProperties(p);
|
||||
if(systemPropertiesMode != SYSTEM_PROPERTIES_MODE_NEVER && systemPropertiesMode != SYSTEM_PROPERTIES_MODE_FALLBACK && systemPropertiesMode != SYSTEM_PROPERTIES_MODE_OVERRIDE) {
|
||||
throw new IllegalArgumentException("error systemPropertiesMode mode:"+systemPropertiesMode);
|
||||
}
|
||||
this.systemPropertiesMode = systemPropertiesMode;
|
||||
}
|
||||
|
||||
public Properties getProperties() {
|
||||
return p;
|
||||
}
|
||||
|
||||
public void setProperties(Properties props) {
|
||||
if(props == null) throw new IllegalArgumentException("properties must be not null");
|
||||
this.p = props;
|
||||
}
|
||||
|
||||
public String getRequiredString(String key) {
|
||||
String value = getProperty(key);
|
||||
if(isBlankString(value)) {
|
||||
throw new IllegalStateException("required property is blank by key="+key);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getNullIfBlank(String key) {
|
||||
String value = getProperty(key);
|
||||
if(isBlankString(value)) {
|
||||
return null;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getNullIfEmpty(String key) {
|
||||
String value = getProperty(key);
|
||||
if(Checks.isEmpty(value)) {
|
||||
return null;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* System.getProperty(key) System.getenv(key)
|
||||
* @param key key
|
||||
* @return String
|
||||
*/
|
||||
public String getAndTryFromSystem(String key) {
|
||||
String value = getProperty(key);
|
||||
if(isBlankString(value)) {
|
||||
value = getSystemProperty(key);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private String getSystemProperty(String key) {
|
||||
String value;
|
||||
value = System.getProperty(key);
|
||||
if(isBlankString(value)) {
|
||||
value = System.getenv(key);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public Integer getInteger(String key) {
|
||||
String v = getProperty(key);
|
||||
if(v == null){
|
||||
return null;
|
||||
}
|
||||
return Integer.parseInt(v);
|
||||
}
|
||||
|
||||
public int getInt(String key,int defaultValue) {
|
||||
if(getProperty(key) == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return Integer.parseInt(getRequiredString(key));
|
||||
}
|
||||
|
||||
public int getRequiredInt(String key) {
|
||||
return Integer.parseInt(getRequiredString(key));
|
||||
}
|
||||
|
||||
public Long getLong(String key) {
|
||||
if(getProperty(key) == null) {
|
||||
return null;
|
||||
}
|
||||
return Long.parseLong(getRequiredString(key));
|
||||
}
|
||||
|
||||
public long getLong(String key,long defaultValue) {
|
||||
if(getProperty(key) == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return Long.parseLong(getRequiredString(key));
|
||||
}
|
||||
|
||||
public Long getRequiredLong(String key) {
|
||||
return Long.parseLong(getRequiredString(key));
|
||||
}
|
||||
|
||||
public Boolean getBoolean(String key) {
|
||||
if(getProperty(key) == null) {
|
||||
return null;
|
||||
}
|
||||
return Boolean.parseBoolean(getRequiredString(key));
|
||||
}
|
||||
|
||||
public boolean getBoolean(String key,boolean defaultValue) {
|
||||
if(getProperty(key) == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return Boolean.parseBoolean(getRequiredString(key));
|
||||
}
|
||||
|
||||
public boolean getRequiredBoolean(String key) {
|
||||
return Boolean.parseBoolean(getRequiredString(key));
|
||||
}
|
||||
|
||||
public Float getFloat(String key) {
|
||||
if(getProperty(key) == null) {
|
||||
return null;
|
||||
}
|
||||
return Float.parseFloat(getRequiredString(key));
|
||||
}
|
||||
|
||||
public float getFloat(String key,float defaultValue) {
|
||||
if(getProperty(key) == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return Float.parseFloat(getRequiredString(key));
|
||||
}
|
||||
|
||||
public Float getRequiredFloat(String key) {
|
||||
return Float.parseFloat(getRequiredString(key));
|
||||
}
|
||||
|
||||
public Double getDouble(String key) {
|
||||
if(getProperty(key) == null) {
|
||||
return null;
|
||||
}
|
||||
return Double.parseDouble(getRequiredString(key));
|
||||
}
|
||||
|
||||
public double getDouble(String key,double defaultValue) {
|
||||
if(getProperty(key) == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return Double.parseDouble(getRequiredString(key));
|
||||
}
|
||||
|
||||
public Double getRequiredDouble(String key) {
|
||||
return Double.parseDouble(getRequiredString(key));
|
||||
}
|
||||
|
||||
//---------- setProperty(String key,int value) ... start ---------------//
|
||||
public Object setProperty(String key,int value) {
|
||||
return setProperty(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
public Object setProperty(String key,long value) {
|
||||
return setProperty(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
public Object setProperty(String key,float value) {
|
||||
return setProperty(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
public Object setProperty(String key,double value) {
|
||||
return setProperty(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
public Object setProperty(String key,boolean value) {
|
||||
return setProperty(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
public String[] getStringArray(String key) {
|
||||
String v = getProperty(key);
|
||||
if(v == null) {
|
||||
return new String[0];
|
||||
}else {
|
||||
return tokenizeToStringArray(v, ", \t\n\r\f");
|
||||
}
|
||||
}
|
||||
|
||||
public int[] getIntArray(String key) {
|
||||
return toIntArray(getStringArray(key));
|
||||
}
|
||||
|
||||
public Properties getStartsWithProperties(String prefix) {
|
||||
if(prefix == null) throw new IllegalArgumentException("'prefix' must be not null");
|
||||
|
||||
Properties props = getProperties();
|
||||
Properties result = new Properties();
|
||||
for(Entry<Object, Object> entry : props.entrySet()) {
|
||||
String key = (String)entry.getKey();
|
||||
if(key != null && key.startsWith(prefix)) {
|
||||
result.put(key.substring(prefix.length()), entry.getValue());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//--------- delegate method start ---//
|
||||
public String getProperty(String key, String defaultValue) {
|
||||
String value = getProperty(key);
|
||||
if(isBlankString(value)) {
|
||||
return defaultValue;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getProperty(String key) {
|
||||
String propVal = null;
|
||||
if (systemPropertiesMode == SYSTEM_PROPERTIES_MODE_OVERRIDE) {
|
||||
propVal = getSystemProperty(key);
|
||||
}
|
||||
if (propVal == null) {
|
||||
propVal = p.getProperty(key);
|
||||
}
|
||||
if (propVal == null && systemPropertiesMode == SYSTEM_PROPERTIES_MODE_FALLBACK) {
|
||||
propVal = getSystemProperty(key);
|
||||
}
|
||||
return propVal;
|
||||
}
|
||||
|
||||
public Object setProperty(String key,String value) {
|
||||
return p.setProperty(key, value);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
p.clear();
|
||||
}
|
||||
|
||||
public Set<Entry<Object, Object>> entrySet() {
|
||||
return p.entrySet();
|
||||
}
|
||||
|
||||
public Enumeration<?> propertyNames() {
|
||||
return p.propertyNames();
|
||||
}
|
||||
|
||||
public boolean contains(Object value) {
|
||||
return p.contains(value);
|
||||
}
|
||||
|
||||
public boolean containsKey(Object key) {
|
||||
return p.containsKey(key);
|
||||
}
|
||||
|
||||
public boolean containsValue(Object value) {
|
||||
return p.containsValue(value);
|
||||
}
|
||||
|
||||
public Enumeration<Object> elements() {
|
||||
return p.elements();
|
||||
}
|
||||
|
||||
public Object get(Object key) {
|
||||
return p.get(key);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return p.isEmpty();
|
||||
}
|
||||
|
||||
public Enumeration<Object> keys() {
|
||||
return p.keys();
|
||||
}
|
||||
|
||||
public Set<Object> keySet() {
|
||||
return p.keySet();
|
||||
}
|
||||
|
||||
public void list(PrintStream out) {
|
||||
p.list(out);
|
||||
}
|
||||
|
||||
public void list(PrintWriter out) {
|
||||
p.list(out);
|
||||
}
|
||||
|
||||
public void load(InputStream inStream) throws IOException {
|
||||
p.load(inStream);
|
||||
}
|
||||
|
||||
public void loadFromXML(InputStream in) throws IOException,
|
||||
InvalidPropertiesFormatException {
|
||||
p.loadFromXML(in);
|
||||
}
|
||||
|
||||
public Object put(Object key, Object value) {
|
||||
return p.put(key, value);
|
||||
}
|
||||
|
||||
public void putAll(Map<? extends Object, ? extends Object> t) {
|
||||
p.putAll(t);
|
||||
}
|
||||
|
||||
public Object remove(Object key) {
|
||||
return p.remove(key);
|
||||
}
|
||||
|
||||
/**@deprecated
|
||||
* @param out out
|
||||
* @param comments comments
|
||||
*/
|
||||
@Deprecated
|
||||
public void save(OutputStream out, String comments) {
|
||||
p.save(out, comments);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return p.size();
|
||||
}
|
||||
|
||||
public void store(OutputStream out, String comments) throws IOException {
|
||||
p.store(out, comments);
|
||||
}
|
||||
|
||||
public void storeToXML(OutputStream os, String comment, String encoding)
|
||||
throws IOException {
|
||||
p.storeToXML(os, comment, encoding);
|
||||
}
|
||||
|
||||
public void storeToXML(OutputStream os, String comment) throws IOException {
|
||||
p.storeToXML(os, comment);
|
||||
}
|
||||
|
||||
public Collection<Object> values() {
|
||||
return p.values();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return p.toString();
|
||||
}
|
||||
|
||||
private static boolean isBlankString(String value) {
|
||||
return Objects.isNull(value) || Objects.equals(StringUtils.EMPTY, value.trim());
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private static String[] tokenizeToStringArray(String str, String sep) {
|
||||
StringTokenizer st = new StringTokenizer(str, sep);
|
||||
List result = new ArrayList();
|
||||
|
||||
while(st.hasMoreElements()) {
|
||||
Object o = st.nextElement();
|
||||
result.add(o);
|
||||
}
|
||||
return (String[])result.toArray(new String[result.size()]);
|
||||
}
|
||||
|
||||
private static int[] toIntArray(String[] array) {
|
||||
int[] result = new int[array.length];
|
||||
for(int i = 0; i < array.length; i++) {
|
||||
result[i] = Integer.parseInt(array[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2013, Poplar Yfyang 杨友峰 (poplar1123@gmail.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cokr.xit.fims.framework.support.mybatis.paging.support;
|
||||
|
||||
import cokr.xit.fims.framework.support.LoggerHelper;
|
||||
import cokr.xit.fims.framework.support.mybatis.paging.dialect.Dialect;
|
||||
import org.apache.ibatis.mapping.BoundSql;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class SQLHelp {
|
||||
private static final Logger log = LoggerHelper.getLogger();
|
||||
|
||||
/**
|
||||
* query record total count
|
||||
*
|
||||
* @param mappedStatement mapped
|
||||
* @param parameterObject parameter
|
||||
* @param boundSql boundSql
|
||||
* @param dialect database dialect
|
||||
* @return int
|
||||
* @throws SQLException SQLException
|
||||
*/
|
||||
public static int getCount(final MappedStatement mappedStatement, final Object parameterObject, final BoundSql boundSql, Dialect dialect) throws SQLException {
|
||||
final String count_sql = dialect.getCountSQL();
|
||||
|
||||
Connection connection = null;
|
||||
PreparedStatement countStmt = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
connection = mappedStatement.getConfiguration().getEnvironment().getDataSource().getConnection();
|
||||
countStmt = connection.prepareStatement(count_sql);
|
||||
DefaultParameterHandler handler = new DefaultParameterHandler(mappedStatement, parameterObject, boundSql);
|
||||
handler.setParameters(countStmt);
|
||||
rs = countStmt.executeQuery();
|
||||
int count = 0;
|
||||
|
||||
if (rs.next()) count = rs.getInt(1);
|
||||
// log.debug("Total count:{}, SQL:{}, parameters:{}", count, count_sql, parameterObject);
|
||||
return count;
|
||||
|
||||
} finally {
|
||||
try {
|
||||
if (rs != null) rs.close();
|
||||
} finally {
|
||||
try {
|
||||
if (countStmt != null) countStmt.close();
|
||||
} finally {
|
||||
if (connection != null && !connection.isClosed()) connection.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue