ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • spring boot 정리 (locale, messageSource, security, jpa, hibernate, Scheduler, config)
    IT/spring 2021. 2. 4. 15:43


    안녕하세요


    Spring boot  정리 해봅니다. 


    https://github.com/visualkhh/lib-spring/tree/master/boot/default_template


    visualkhh@gmail.com




    springboot로 만든 기본틀입니다.


    사용 : spring jpa, hibernate, scheduler, config, groovyTemplate


    //설명은 소스안 주석으로 설명하겠습니다.








    build.gradle

    group 'com.boot'
    version '1.0-SNAPSHOT'

    apply plugin: 'java'
    apply plugin: 'idea'
    apply plugin: 'spring-boot'
    apply plugin: 'war'
    apply plugin: 'groovy'
    version = '1.0'
    sourceCompatibility = 1.8
    targetCompatibility = 1.8
    [compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
    compileJava {
    options.fork = true
    options.forkOptions.executable = "${System.getenv().JAVA_HOME}/bin/javac" // assumes that javac is on PATH
    //options.compilerArgs << "-XDignore.symbol.file"// does not exist 오류나면..
    }

    buildscript {
    ext {
    springBootVersion = '1.4.1.RELEASE'
    }
    repositories {
    mavenLocal()
    mavenCentral()
    }

    dependencies {
    classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    // classpath("org.springframework:springloaded:1.2.5.RELEASE")
    }
    }

    repositories {
    maven { url "http://119.206.205.172:8081/nexus/content/repositories/releases/" }
    mavenCentral()
    // maven { url "http://www.egovframe.go.kr/maven/" }
    }


    dependencies {
    // egov 전자정부 프레임워크 감리통과하려면 아래 풀어 dependencies 걸어서 감리만 통과하여라
    // compile(group: 'egovframework.rte', name: 'egovframework.rte.ptl.mvc', version:'3.5.0') {
    // exclude(group: 'egovframework.rte')
    //// exclude(module: 'commons-logging')
    // }

    compile("org.springframework.boot:spring-boot-starter-web:${springBootVersion}")
    compile("org.springframework.boot:spring-boot-starter-data-jpa:${springBootVersion}")
    compile("org.springframework.boot:spring-boot-starter-security:${springBootVersion}")
    compile("org.springframework.boot:spring-boot-starter-integration:${springBootVersion}")
    //devtools
    compile("org.springframework.boot:spring-boot-devtools")
    //config를위하여
    compile("org.springframework.boot:spring-boot-configuration-processor")
    //optional ("org.springframework.boot:spring-boot-configuration-processor")

    //view template select one!
    compile("org.springframework.boot:spring-boot-starter-groovy-templates:${springBootVersion}")
    //compile("org.springframework.boot:spring-boot-starter-thymeleaf:${springBootVersion}")
    //compile("org.springframework.boot:spring-boot-starter-velocity:${springBootVersion}")
    /*jsp jstl viwe 쓰려면
    compile("javax.servlet:jstl");
    compile("org.apache.tomcat.embed:tomcat-embed-jasper")
    */

    compile("com.h2database:h2:1.4.192");

    compile('com.jayway.jsonpath:json-path:2.1.0')

    /* lombok*/
    compile group: 'org.projectlombok', name: 'lombok', version: '1.16.8'
    /* quartz */
    compile group: 'org.quartz-scheduler', name: 'quartz', version: '1.8.6'
    // https://mvnrepository.com/artifact/javax.transaction/jta
    compile group: 'javax.transaction', name: 'jta', version: '1.1'

    /* email */
    compile group: 'javax.mail', name: 'mail', version: '1.4.7'

    /* class scaner https://sites.google.com/site/javacornproject/corn-cps */
    compile group: 'net.sf.corn', name: 'corn-cps', version: '1.1.7'


    testCompile ("org.springframework.boot:spring-boot-starter-test:${springBootVersion}")


    compile group: 'com.omnicns', name: 'common-java', version: '0.0.1'
    compile group: 'com.omnicns', name: 'common-jsp', version: '0.0.1'
    compile group: 'com.omnicns', name: 'common-spring', version: '0.0.1'


    testCompile group: 'junit', name: 'junit', version: '4.11'
    }
    compileJava.dependsOn(processResources)
    idea {
    module {
    inheritOutputDirs = false
    outputDir = file("$buildDir/classes/main/")
    }
    }




    application.yml

    #http://docs.spring.io/spring-boot/docs/current/reference/html/howto-properties-and-configuration.html
    #http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
    application:
    version: 1.0
    title: Board Application

    spring:
    devtools:
    livereload:
    enabled: true
    freemarker:
    cache: false
    # templateLoaderPath:
    config:
    location:
    application:
    name: springboot
    main:
    banner-mode: off
    h2:
    console:
    enabled: true # Enable the console.
    path: /h2-console # Path at which the console will be available.
    settings:
    trace: false # Enable trace output.
    web-allow-others: false # Enable remote access.
    datasource:
    name: testdb
    initialize: true # Populate the database using 'data.sql'.
    #schema:
    #data:
    platform: all # Platform to use in the schema resource (schema-${platform}.sql).
    # url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
    driverClassName: org.h2.Driver
    username: sa
    password:
    continue-on-error: true
    # jpa:
    # database-platform: org.hibernate.dialect.H2Dialect
    # generate-ddl: true
    # show-sql: true
    # open-in-view: true
    # hibernate:
    # ddl-auto: create-drop
    # properties:
    # hibernate.current_session_context_class: thread
    # hibernate.jdbc.batch_size: 50
    # hibernate.format_sql: false
    # hibernate.validator.apply_to_ddl: false
    # hibernate.validator.autoregister_listeners: false
    # javax.persistence.validation.mode: none
    ## hibernate.current_session_context_class: org.springframework.orm.hibernate5.SpringSessionContext
    data:
    repositories:
    enabled: true
    http:
    multipart:
    enabled: true # Enable support of multi-part uploads.
    mvc:
    locale: ko_KR
    groovy:
    template:
    cache: false
    # INTERNATIONALIZATION (MessageSourceAutoConfiguration)
    messages:
    # always-use-message-format: false # Set whether to always apply the MessageFormat rules, parsing even messages without arguments.
    cache-seconds: -1 # Loaded resource bundle files cache expiration, in seconds. When set to -1, bundles are cached forever.
    basename: classpath:/messages/message # Comma-separated list of basenames, each following the ResourceBundle convention.
    encoding: UTF-8 # Message bundles encoding.
    # fallback-to-system-locale: true # Set whether to fall back to the system Locale if no files for a specific Locale have been found.



    # SECURITY (SecurityProperties)
    security:
    basic:
    authorize-mode: role # Security authorize mode to apply.
    enabled: true # Enable basic authentication.
    path: /** # Comma-separated list of paths to secure.
    realm: Spring # HTTP basic realm name.
    enable-csrf: true # Enable Cross Site Request Forgery support.
    filter-order: 0 # Security filter chain order.
    filter-dispatcher-types: ASYNC, FORWARD, INCLUDE, REQUEST # Security filter chain dispatcher types.
    headers:
    cache: true # Enable cache control HTTP headers.
    content-type: true # Enable "X-Content-Type-Options" header.
    frame: true # Enable "X-Frame-Options" header.
    #hsts= # HTTP Strict Transport Security (HSTS) mode (none, domain, all).
    xss: true # Enable cross site scripting (XSS) protection.
    #ignored= # Comma-separated list of paths to exclude from the default secured paths.
    require-ssl: false # Enable secure channel for all requests.
    sessions: stateless # Session creation policy (always, never, if_required, stateless).
    user:
    name: user # Default admin name.
    password: user # Password for the default admin name. A random password is logged on startup by default.
    role: USER # Granted roles for the default admin name.
    # view:
    # prefix:
    # suffix: :.vm

    logging:
    level:
    root: INFO
    org.springframework.web: INFO
    org.hibernate: INFO
    com.khh: INFO

    multipart:
    maxFileSize: 10Mb


    ######## CUSTOM PROPERTIES ##########
    hibernate:
    mapping-locations: classpath:hibernate/*.hbm.xml
    # packages-to-scan: com.khh.project
    # annotated-packages: com.khh.project
    properties:
    # hibernate.connection.url
    hibernate.dialect: org.hibernate.dialect.H2Dialect
    hibernate.show_sql: true
    hibernate.hbm2ddl.auto: update
    hibernate.current_session_context_class: thread

    project:
    properties:
    hello: hello22






    ---

    spring:
    profiles: development

    logging:
    level:
    root: INFO
    org.springframework.web: INFO
    org.hibernate: DEBUG
    com.khh: DEBUG

    ---

    spring:
    profiles: production

    logging:
    #file: logs/application.log
    level:
    root: INFO
    org.springframework.web: INFO
    org.hibernate: INFO
    com.khh: INFO







    WebMvcConfigurerAdapter

    1.다국어(locale)

    2.messageSource

    3.interceptor

     - springsecurity csrf

    package com.khh.project.config.web;

    import com.khh.project.web.error.ErrorController;
    import lombok.extern.slf4j.Slf4j;
    import org.hibernate.SessionFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
    import org.springframework.boot.web.servlet.ErrorPage;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.support.MessageSourceAccessor;
    import org.springframework.context.support.ReloadableResourceBundleMessageSource;
    import org.springframework.http.HttpStatus;
    import org.springframework.security.web.csrf.CsrfToken;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.LocaleResolver;
    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
    import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
    import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
    import org.springframework.web.servlet.i18n.SessionLocaleResolver;

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.util.Locale;


    @Configuration
    @EnableWebMvc
    @Slf4j
    public class WebMvcConfigurerAdapter extends org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter {


    @Value("${spring.mvc.locale}")
    Locale locale = null;

    @Value("${spring.messages.basename}")
    String messagesBasename = null;
    @Value("${spring.messages.encoding}")
    String messagesEncoding = null;
    @Value("${spring.messages.cache-seconds}")
    int messagesCacheSeconds;


    @Autowired
    SessionFactory sessionFactory = null;

    // preHandle boolean 1. 클라이언트의 요청을 컨트롤러에 전달 하기 전에 호출
    // false 인 경우 intercepter 또는 controller 를 실행 시키지 않고 요청 종료
    // postHandle void 1. 컨트롤러 로직 실행 된 후 호출됨2. 컨트롤러 실행 도중 error 발생의 경우 postHandle() 는 실행 되지 않음
    // request 로 넘어온 데이터 가공시 많이 쓰임
    // afterCompletion void 1. 컨트롤러 로직 실행 된 후 호출 됨 2. 컨트롤러 실행 도중이나 view 페이지 실행 도중 error 발생 해도 실행됨
    // 공통 Exception 처리 로직 작성시 많이 쓰임
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(csrfTokenAddingInterceptor()).addPathPatterns("/**"); //.includePathPatterns("/**") .excludePathPatterns("/**/*.ecxld");
    registry.addInterceptor(localeChangeInterceptor()).addPathPatterns("/**");
    registry.addInterceptor(sessionFactoryTransctionInterceptor()).addPathPatterns("/**");
    }

    @Bean
    public HandlerInterceptor sessionFactoryTransctionInterceptor() {
    return new HandlerInterceptorAdapter() {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    sessionFactory.getCurrentSession().beginTransaction();
    return true;
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    sessionFactory.getCurrentSession().getTransaction().commit();
    }
    };
    }
    @Bean
    public HandlerInterceptor csrfTokenAddingInterceptor() {
    return new HandlerInterceptorAdapter() {
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView view) {
    CsrfToken token = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
    if (token != null && null != view) {
    view.addObject(token.getParameterName(), token);
    }
    }
    };
    }



    //다국어 https://justinrodenbostel.com/2014/05/13/part-4-internationalization-in-spring-boot/
    @Bean
    public LocaleResolver localeResolver() {
    SessionLocaleResolver slr = new SessionLocaleResolver();
    slr.setDefaultLocale(locale);
    return slr;
    }
    @Bean
    public LocaleChangeInterceptor localeChangeInterceptor() {
    LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
    lci.setParamName("lang");
    return lci;
    }

    //message source
    @Bean
    public ReloadableResourceBundleMessageSource messageSource(){
    ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
    messageSource.setBasename(messagesBasename); //"classpath:/messages/message"
    messageSource.setDefaultEncoding(messagesEncoding);
    messageSource.setCacheSeconds(messagesCacheSeconds);
    return messageSource;
    }

    @Bean
    public MessageSourceAccessor getMessageSourceAccessor(){
    ReloadableResourceBundleMessageSource m = messageSource();
    return new MessageSourceAccessor(m);
    }


    //로그인페이지.
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController(WebSecurityConfigurerAdapter.LOGIN_PAGE).setViewName("security/login");
    }




    @Bean
    public EmbeddedServletContainerCustomizer containerCustomizer() {
    return container -> {
    container.addErrorPages(
    new ErrorPage(HttpStatus.UNAUTHORIZED, ErrorController.ERROR_401),
    new ErrorPage(HttpStatus.FORBIDDEN, ErrorController.ERROR_403),
    new ErrorPage(HttpStatus.NOT_FOUND, ErrorController.ERROR_404),
    new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, ErrorController.ERROR_500),
    new ErrorPage(Throwable.class, ErrorController.ERROR_DEFAULT)
    );
    };
    }



    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/resource/**") .addResourceLocations("/resource/");
    registry.addResourceHandler("/static/**") .addResourceLocations("/static/");
    registry.addResourceHandler("/static/**") .addResourceLocations("/static/");
    registry.addResourceHandler("/img/**") .addResourceLocations("/img/");
    registry.addResourceHandler("/image/**") .addResourceLocations("/image/");
    }


    }






    spring jpa와 함께 hibernate original 사용하기위해 설정

    package com.khh.project.config;

    import com.khh.Application;
    import com.khh.project.config.properties.HibernateProperties;
    import com.khh.project.config.properties.ProjectProperties;
    import lombok.extern.slf4j.Slf4j;
    import org.hibernate.SessionFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.devtools.classpath.ClassPathRestartStrategy;
    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.io.*;
    import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
    import org.springframework.core.io.support.ResourcePatternResolver;
    import org.springframework.orm.hibernate4.support.OpenSessionInViewFilter;
    import org.springframework.orm.hibernate4.HibernateTemplate;
    import org.springframework.orm.hibernate4.HibernateTransactionManager;
    import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
    import org.springframework.transaction.annotation.EnableTransactionManagement;

    import javax.sql.DataSource;
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.Properties;

    @Configuration
    @EnableTransactionManagement
    @Slf4j
    public class HibernateConfig {

    @Autowired
    DataSource dataSource;

    @Autowired
    HibernateProperties hibernateProperties;
    @Autowired
    ProjectProperties ProjectProperties;


    @Autowired
    private ResourceLoader resourceLoader;
    //https://github.com/netgloo/spring-boot-samples/blob/master/spring-boot-mysql-hibernate/src/main/java/netgloo/configs/DatabaseConfig.java
    @Bean
    public LocalSessionFactoryBean sessionFactory() throws IOException {
    LocalSessionFactoryBean factory = new LocalSessionFactoryBean();
    factory.setPackagesToScan();
    factory.setDataSource(dataSource);
    if (hibernateProperties.getMappingLocations() != null) {
    ClassLoader cl = this.getClass().getClassLoader();
    ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(cl);
    Resource[] resources = resolver.getResources(hibernateProperties.getMappingLocations()) ;
    for (Resource resource: resources){
    factory.setMappingLocations(resources);
    }
    }
    if (hibernateProperties.getPackagesToScan() != null) {
    factory.setPackagesToScan(hibernateProperties.getPackagesToScan());
    }else{
    factory.setPackagesToScan(Application.BASE_PACKAGES);
    }
    if (hibernateProperties.getAnnotatedPackages() != null) {
    factory.setAnnotatedPackages(hibernateProperties.getAnnotatedPackages());
    }else{
    factory.setAnnotatedPackages(Application.BASE_PACKAGES);
    }
    factory.setHibernateProperties(hibernateProperties.getProperties());
    Properties hibernateProperties = new Properties();
    SessionFactory sessionFactory = factory.getObject();
    return factory;
    }


    } // class DatabaseConfig






    SpringBootServletInitializer

    - Scheduler, characterEncoding, War

    package com.khh.project.config;

    import com.khh.Application;
    import org.springframework.boot.builder.SpringApplicationBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.converter.HttpMessageConverter;
    import org.springframework.http.converter.StringHttpMessageConverter;
    import org.springframework.scheduling.annotation.EnableScheduling;
    import org.springframework.scheduling.concurrent.ScheduledExecutorFactoryBean;
    import org.springframework.web.filter.CharacterEncodingFilter;

    import javax.servlet.Filter;
    import java.nio.charset.Charset;

    @Configuration
    @EnableScheduling
    public class SpringBootServletInitializer extends org.springframework.boot.web.support.SpringBootServletInitializer {
    //war를 처리하기위해 필요하다.
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
    return application.sources(Application.class);
    }


    @Bean
    public HttpMessageConverter<String> responseBodyConverter() {
    return new StringHttpMessageConverter(Charset.forName("UTF-8"));
    }

    @Bean
    public Filter characterEncodingFilter() {
    CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
    characterEncodingFilter.setEncoding("UTF-8");
    characterEncodingFilter.setForceEncoding(true);
    return characterEncodingFilter;
    }


    //////////////////////////scheduled 스케쥴 하기위하여//////////////////////
    //////////////@EnableScheduling 붙쳐줘야한다
    @Bean
    public ScheduledExecutorFactoryBean scheduledExecutorService() {
    ScheduledExecutorFactoryBean bean = new ScheduledExecutorFactoryBean();
    bean.setPoolSize(5);
    return bean;
    }


    }








    WebSecurityConfigurerAdapter

    - Security

    package com.khh.project.config.web;

    import com.khh.project.config.web.security.*;
    import com.khh.project.config.web.security.user.LoginUserDetailsService;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.access.AccessDecisionVoter;
    import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
    import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
    import org.springframework.security.access.vote.AffirmativeBased;
    import org.springframework.security.access.vote.RoleHierarchyVoter;
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.builders.WebSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.http.SessionCreationPolicy;
    import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
    import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
    import org.springframework.security.web.authentication.RememberMeServices;
    import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
    import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
    import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
    import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;
    import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

    import javax.sql.DataSource;
    import java.util.ArrayList;
    import java.util.List;

    import static org.hibernate.criterion.Restrictions.and;


    @Slf4j
    @Configuration
    @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
    @EnableWebSecurity
    public class WebSecurityConfigurerAdapter extends org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter {

    @Value("${spring.h2.console.enabled}")
    boolean h2ConsoleEnabled;
    @Value("${spring.h2.console.path}")
    String h2ConsolePath;

    public static final String ROOT_PATH = "/";
    public static final String SECURITY_PATH = "/security";
    public static final String ANON_PATH = "/anon";
    public static final String AUTH_PATH = "/auth";

    public static final String LOGIN_PAGE = SECURITY_PATH+"/login";
    public static final String LOGIN_PROCESSING_URL = SECURITY_PATH+"/sign_in";
    public static final String FAILURE_URL = SECURITY_PATH+"/fail";
    public static final String USERNAME_PARAMETER = "username";
    public static final String PASSWORD_PARAMETER = "password";
    public static final String DEFAULT_SUCCESS_URL = ROOT_PATH;
    public static final String LOGOUT_SUCCESS_URL = ROOT_PATH;
    public static final String SESSION_EXPIRED_URL = LOGIN_PAGE+"?expred";
    public static final String SESSION_INVALIDSESSION_URL = LOGIN_PAGE+"?invalid";
    public static final String LOGOUT_URL = SECURITY_PATH+"/sign_out";
    public static final String REMEMBER_ME_KEY = "REMEBMER_ME_KEY";
    public static final String REMEMBER_ME_COOKE_NAME = "REMEMBER_ME_COOKE";



    // @Autowired
    // private LoginUserDetailsService userDetailsService;
    @Autowired
    AuthenticationManager authenticationManager;
    // @Autowired
    // private DataSource dataSource;


    @Override
    public void configure(WebSecurity web) throws Exception {
    if(h2ConsoleEnabled) {
    web.ignoring().antMatchers(h2ConsolePath+"/**");
    }
    web.ignoring().antMatchers("/resource/**","/static/**","/img/**","/image/**");
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
    log.debug("-----security HttpSecurity-----"+http);
    http
    .anonymous()
    .and()
    .authorizeRequests()
    .antMatchers("/", ANON_PATH +"/**") .permitAll()
    .antMatchers(AUTH_PATH +"/**") .hasRole("AUTH")
    .antMatchers("/admin/**") .hasRole("ADMIN")
    .antMatchers("/board/**") .hasRole("USER")
    //.antMatchers("/board/**").hasAnyAuthority()
    .anyRequest().authenticated()
    .and()
    .sessionManagement() //http://niees.tistory.com/17
    .maximumSessions(1)
    .expiredUrl(SESSION_EXPIRED_URL) //중복 로그인이 일어났을 경우 이동 할 주소​
    .maxSessionsPreventsLogin(false) //만약 두번째 인증을 거부하게 하고 싶은 경우concurrency-control에​ error-if-maximum-exceeded="true"속성을 지정하면 된다.​
    .and()
    .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
    .invalidSessionUrl(SESSION_INVALIDSESSION_URL)
    .and()
    .formLogin()
    .loginPage(LOGIN_PAGE) //로그인 페이지
    .loginProcessingUrl(LOGIN_PROCESSING_URL) //login-processing-url 로그인 페이지 form action에 입력할 주소 지정
    .failureUrl(FAILURE_URL) //실패시 이동될 페이지
    .usernameParameter(USERNAME_PARAMETER)
    .passwordParameter(PASSWORD_PARAMETER)
    .defaultSuccessUrl(DEFAULT_SUCCESS_URL) //성공시 이동될 페이지
    .failureHandler(authenticationFailureHandler())
    .successHandler(authenticationSuccessHandler())
    .permitAll()
    .and()
    .rememberMe()
    .key(REMEMBER_ME_KEY)
    .rememberMeServices(tokenBasedRememberMeServices())
    .and()
    .logout()
    .deleteCookies(REMEMBER_ME_COOKE_NAME)
    .deleteCookies("JSESSIONID")
    .logoutUrl(LOGOUT_URL)
    .invalidateHttpSession(true)
    .logoutSuccessUrl(LOGOUT_SUCCESS_URL)
    // .logoutSuccessHandler(logoutSuccessHandler()) //커스텀으로 로그아웃된거에 대한 처리를 해주면 로그아웃성공URL로 가지 않으니 커스텀할떄 사용해여라
    .logoutRequestMatcher(new AntPathRequestMatcher(LOGOUT_URL))
    .permitAll()
    .and()
    .authenticationProvider(authenticationProvider()) //configure(AuthenticationManagerBuilder auth) 오버라이딩해서 추가할수도있다.
    .csrf();
    }



    ///////////////////////////AuthenticationProvider/////////////////////////////////////////////////
    /**/ //AuthenticationProvider Interface는 자동으로 클래스패스에 있는거 찾아서 쓴다
    /**/ //
    /**/ // //DaoAuthenticationProvider daoAuthenticationProvider() 대신 이거 아래 처럼 등록을해도된다
    /**/ // @Override
    /**/ // protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    /**/ // auth.authenticationProvider(authenticationProvider());
    /**/ // }
    /**/ // @Bean //스프링에서 제공하는 기본적인 아이디 idpassword관련 처리
    /**/ // public DaoAuthenticationProvider daoAuthenticationProvider() {
    /**/ // DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
    /**/ // daoAuthenticationProvider.setUserDetailsService(userDetailsService());
    /**/ // daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
    /**/ // daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
    /**/ // return daoAuthenticationProvider;
    /**/ // }
    /**/ @Bean
    /**/ public AuthenticationProvider authenticationProvider(){
    /**/ return new AuthenticationProvider();
    /**/ }
    /////////////////////////////////////////////////////////////////////////////////////////////////




    ///////////////////////////////////////////////////////////////////////////////////////////////////////
    /**/ //커스텀 시큐리티 인텁셉터 하려면 아래를 사용하면된다
    /**/ //사용전에 httpSecurity쪽에 추가해줘야된다 .addFilterBefore(filterSecurityInterceptor(), UsernamePasswordAuthenticationFilter.class)
    /**/ ////////http://aoruqjfu.fun25.co.kr/index.php/post/657
    /**/ @Bean
    /**/ public FilterSecurityInterceptor filterSecurityInterceptor() {
    /**/ FilterSecurityInterceptor filterSecurityInterceptor = new FilterSecurityInterceptor();
    /**/ filterSecurityInterceptor.setAuthenticationManager(authenticationManager);
    /**/ filterSecurityInterceptor.setSecurityMetadataSource(filterInvocationSecurityMetadataSource());
    /**/ filterSecurityInterceptor.setAccessDecisionManager(affirmativeBased());
    /**/ return filterSecurityInterceptor;
    /**/ }
    /**/ @Bean
    /**/ public AffirmativeBased affirmativeBased() {
    /**/ List<AccessDecisionVoter<? extends Object>> accessDecisionVoters = new ArrayList<>();
    /**/ accessDecisionVoters.add(roleVoter());
    /**/ AffirmativeBased affirmativeBased = new AffirmativeBased(accessDecisionVoters);
    /**/ return affirmativeBased;
    /**/ }
    /**/ @Bean
    /**/ public RoleHierarchyVoter roleVoter() {
    /**/ RoleHierarchyVoter roleHierarchyVoter = new RoleHierarchyVoter(roleHierarchy());
    /**/ roleHierarchyVoter.setRolePrefix("ROLE_");
    /**/ return roleHierarchyVoter;
    /**/ }
    /**/ //RoleHierarchy 설정
    /**/ @Bean
    /**/ public RoleHierarchy roleHierarchy() {
    /**/ RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
    /**/ roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER");
    /**/ return roleHierarchy;
    /**/ }
    /**/ //시큐리트쪽 부분에서 사용자가 화면 페이지 호출하면 매번 호출되는 클래스 중요함
    /**/ @Bean
    /**/ public FilterInvocationSecurityMetadataSource filterInvocationSecurityMetadataSource(){
    /**/ return new FilterInvocationSecurityMetadataSource();
    /**/ }
    ///////////////////////////////////////////////////////////////////////////////////////////////////






    @Bean
    public PasswordEncoder passwordEncoder() {
    return new PasswordEncoder();
    }
    @Bean
    public LoginUserDetailsService userDetailsService(){
    return new LoginUserDetailsService();
    }
    @Bean
    public RememberMeServices tokenBasedRememberMeServices() {
    TokenBasedRememberMeServices tokenBasedRememberMeServices = new TokenBasedRememberMeServices(REMEMBER_ME_KEY, userDetailsService());
    tokenBasedRememberMeServices.setAlwaysRemember(true);
    tokenBasedRememberMeServices.setTokenValiditySeconds(60 * 60 * 24 * 31);
    tokenBasedRememberMeServices.setCookieName(REMEMBER_ME_COOKE_NAME);
    return tokenBasedRememberMeServices;
    }


    //login,out 정상처리 및 실패에 대한 Bean
    @Bean
    public AuthenticationSuccessHandler authenticationSuccessHandler() {
    log.debug("#### login Success handler #####");
    return new AuthenticationSuccessHandler();
    }
    @Bean
    public AuthenticationFailureHandler authenticationFailureHandler() {
    log.debug("#### login Failurer handler #####");
    return new AuthenticationFailureHandler();
    }
    //로그아웃 성공시 핸들링
    @Bean
    public LogoutSuccessHandler logoutSuccessHandler(){
    return new LogoutSuccessHandler();
    }


    //

    //REMEMBER ME를 위한.
    // @Bean
    // public PersistentTokenRepository persistentTokenRepository() {
    // JdbcTokenRepositoryImpl tokenRepositoryImpl = new JdbcTokenRepositoryImpl();
    // tokenRepositoryImpl.setDataSource(dataSource);
    // return tokenRepositoryImpl;
    // }

    }




    security groovyTemplate에서 csrf넣기 (interceptor설정부분)

    login.tpl

    //http://www.w3ii.com/ko/groovy/groovy_template_engines.html
    layout 'layout.tpl', title: 'login',
    content: contents {
    div{
    form(action:"${WebSecurityConfigurerAdapter.LOGIN_PROCESSING_URL}", method:'POST'){
    input(type:'text', name:'username', value:'')
    input(type:'password', name:'password', value:'')
    input(type:'hidden', name:"${_csrf.parameterName}", value:"${_csrf.token}")
    input(type:'submit', value:'submit')
    }
    }
    }






    UserDetailsService


    package com.khh.project.config.web.security.user;

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.support.MessageSourceAccessor;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;


    //@Transactional //http://jdm.kr/blog/141
    public class LoginUserDetailsService implements org.springframework.security.core.userdetails.UserDetailsService{
    @Autowired
    MessageSourceAccessor messageSource;

    @Autowired
    LoginUserRepository userRepository;

    @Override
    public LoginUserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    LoginUserDetails userDetails = userRepository.findByUsername(username);
    if (null == userDetails) {
    throw new UsernameNotFoundException(messageSource.getMessage("error.login.fail"));
    }
    return userDetails;
    }
    }




    AuthenticationProvider

    - 로그인 처리


    import com.khh.project.config.web.security.user.LoginUserDetails;
    import com.khh.project.config.web.security.user.LoginUserDetailsService;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.support.MessageSourceAccessor;
    import org.springframework.security.authentication.BadCredentialsException;
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.security.web.authentication.WebAuthenticationDetails;
    import org.springframework.stereotype.Component;
    import org.springframework.transaction.annotation.Transactional;

    @Slf4j
    public class AuthenticationProvider implements org.springframework.security.authentication.AuthenticationProvider {

    @Autowired
    LoginUserDetailsService userDetailsService;
    @Autowired
    MessageSourceAccessor messageSource;

    @Autowired
    PasswordEncoder encoder;
    @Override
    // @Transactional //http://jdm.kr/blog/141
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {


    WebAuthenticationDetails detail = (WebAuthenticationDetails) authentication.getDetails();
    String remoteIP = detail.getRemoteAddress();
    String username = (String)authentication.getPrincipal();
    String password = (String)authentication.getCredentials();
    LoginUserDetails userDetails = userDetailsService.loadUserByUsername(username);
    log.info("Login try ip : -> "+remoteIP+" input id("+username+") info:"+userDetails);
    if(null == userDetails || userDetails.isAccountNonLocked()==false || userDetails.isAccountNonExpired() == false || userDetails.isEnabled() == false || userDetails.isCredentialsNonExpired() == false) {
    throw new UsernameNotFoundException(messageSource.getMessage("error.login.fail"));
    }


    if(!encoder.matches(encoder.encode(password),userDetails.getPassword())){ //실패
    throw new BadCredentialsException(messageSource.getMessage("error.login.fail"));
    }

    UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password, userDetails.getAuthorities());
    // token.setDetails(userDetails);
    return token;
    }

    @Override
    public boolean supports(Class<?> authentication) {
    return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
    }




    AuthenticationSuccessHandler

    - 로그인성공시

    package com.khh.project.config.web.security;

    import com.khh.project.config.web.WebSecurityConfigurerAdapter;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.web.DefaultRedirectStrategy;
    import org.springframework.security.web.RedirectStrategy;
    import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
    import org.springframework.security.web.savedrequest.RequestCache;
    import org.springframework.security.web.savedrequest.SavedRequest;

    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;



    //로그인 성공 핸들러
    @Slf4j
    public class AuthenticationSuccessHandler implements org.springframework.security.web.authentication.AuthenticationSuccessHandler {

    @Autowired
    protected AuthenticationManager authenticationManager;
    private RequestCache requestCache = null;
    private RedirectStrategy redirectStrategy = null;

    public AuthenticationSuccessHandler(){
    requestCache = new HttpSessionRequestCache();
    redirectStrategy = new DefaultRedirectStrategy();
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
    sendRedirectDefaultUrl(request,response);
    }

    private void sendRedirectSessionUrl(HttpServletRequest request,HttpServletResponse response) throws IOException {
    SavedRequest savedRequest = requestCache.getRequest(request, response);
    String targetUrl = savedRequest.getRedirectUrl();
    redirectStrategy.sendRedirect(request, response, targetUrl);
    }

    private void sendRedirectRefererUrl(HttpServletRequest request, HttpServletResponse response) throws IOException {
    String targetUrl = request.getHeader("REFERER");
    redirectStrategy.sendRedirect(request, response, targetUrl);
    }

    private void sendRedirectDefaultUrl(HttpServletRequest request, HttpServletResponse response) throws IOException {
    redirectStrategy.sendRedirect(request, response, WebSecurityConfigurerAdapter.DEFAULT_SUCCESS_URL);
    }
    }






    LoginUserDetails

    package com.khh.project.config.web.security.user;

    import lombok.Data;

    import javax.persistence.*;
    import java.io.Serializable;
    import java.util.Collection;

    @Entity
    @Table(name = "USER")
    @Data
    public class LoginUserDetails implements org.springframework.security.core.userdetails.UserDetails, Serializable {

    @Id
    @Column(name = "USERNAME", unique = true, nullable = false)
    private String username;

    @Column(name = "PASSWORD", nullable = false)
    private String password;

    @Column(name = "ACCOUNTNONEXPIRED")
    private boolean accountNonExpired;

    @Column(name = "ACCOUNTNONLOCKED")
    private boolean accountNonLocked;

    @Column(name = "CREDENTIALSNONEXPIRED")
    private boolean credentialsNonExpired;

    @Column(name = "ENABLED")
    private boolean enabled;


    @OneToMany(fetch = FetchType.EAGER)
    // @OneToMany
    @JoinColumn(name="USERNAME")
    private Collection<LoginUserGrantedAuthority> authorities;

    }






    LoginUserGrantedAuthority

    package com.khh.project.config.web.security.user;

    import lombok.Data;

    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.Table;

    @Entity
    @Table(name = "AUTHORITY")
    @Data
    public class LoginUserGrantedAuthority implements org.springframework.security.core.GrantedAuthority {
    @Id
    @Column(name = "USERNAME")
    private String username;

    @Id
    @Column(name = "AUTHORITY")
    private String authority = null;

    public LoginUserGrantedAuthority() {
    }

    public LoginUserGrantedAuthority(String authority) {
    this.authority = authority;
    }

    }






    SecurityController

    package com.khh.project.web.security;

    import com.khh.project.config.web.WebSecurityConfigurerAdapter;
    import groovy.util.logging.Slf4j;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.context.SecurityContextHolder;
    import org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler;
    import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    @Slf4j
    @Controller
    @RequestMapping(WebSecurityConfigurerAdapter.SECURITY_PATH)
    public class SecurityController {


    @RequestMapping({"","/"})
    String index(HttpServletRequest request, HttpServletResponse response, Model model) {
    return "security/login";
    }



    //수동로그아웃시킬때 사용하세요
    public void logout(HttpServletRequest request, HttpServletResponse response){
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    if (auth != null){
    CookieClearingLogoutHandler cookieClearingLogoutHandler = new CookieClearingLogoutHandler(new String[]{"remember-me","JSESSIONID",WebSecurityConfigurerAdapter.REMEMBER_ME_COOKE_NAME});
    SecurityContextLogoutHandler securityContextLogoutHandler = new SecurityContextLogoutHandler();
    cookieClearingLogoutHandler.logout(request, response, (Authentication)null);
    securityContextLogoutHandler.logout(request, response, (Authentication)null);
    request.getSession().invalidate();
    }
    }


    }










    @ControllerAdvice

     - error Controller


    @org.springframework.web.bind.annotation.ControllerAdvice(Application.BASE_PACKAGES)
    @Slf4j
    public class ControllerAdvice {


    @ExceptionHandler(EntityNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ResponseBody
    ModelAndView handleException(HttpServletRequest request, HttpServletResponse response, EntityNotFoundException exception){
    log(request,response,exception);
    //log.trace(exception.getMessage(),exception);
    ModelAndView mav = new ModelAndView();
    response.setHeader("x-status", "Exception");
    mav.addObject("throwable", exception);
    mav.setViewName("error/default");
    return mav;
    }


    @ExceptionHandler({UsernameNotFoundException.class})
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    @ResponseBody
    ModelAndView handleException(HttpServletRequest request, HttpServletResponse response, UsernameNotFoundException exception){
    log(request,response,exception);
    //log.trace(exception.getMessage(),exception);
    ModelAndView mav = new ModelAndView();
    response.setHeader("x-status", "Exception");
    mav.addObject("throwable", exception);
    mav.setViewName("error/default");
    return mav;
    }



    @ExceptionHandler(Throwable.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    ModelAndView handleException(HttpServletRequest request, HttpServletResponse response, Throwable exception){
    log(request,response,exception);
    //log.trace(exception.getMessage(),exception);
    ModelAndView mav = new ModelAndView();
    response.setHeader("x-status", "Exception");
    mav.addObject("throwable", exception);
    mav.setViewName("error/default");
    return mav;
    }

    private void log(HttpServletRequest request, HttpServletResponse response, Throwable ex) {
    Throwable tex = StackTraceUtil.getLastCause(ex);
    StackTraceElement[] stacks = tex.getStackTrace();

    StringBuffer logInfo = new StringBuffer();
    logInfo.append(ex.getClass().getName());
    logInfo.append("|").append(request.getRequestURI());//API CODE(URL)
    logInfo.append("|").append(RequestUtil.getRemoteAddr(request)); // 접속IP
    logInfo.append("|").append(null==ex.getMessage()?"":ex.getMessage().replace("\n","").replace("\r", "")); // 처리 담당자 ID
    logInfo.append("|").append(Stream.of(stacks).map(at->at.toString()).collect(Collectors.joining("<<")));
    log.error(logInfo.toString().replace("\n", "").replace("\r",""));
    }
    }




    schduler

    @Component
    @Slf4j
    public class Scheduler {

    // 매일 5시 30분 0초에 실행한다.
    @Scheduled(cron = "0 30 5 * * *")
    public void aJob() {
    // 실행될 로직
    }

    // 매월 1일 0시 0분 0초에 실행한다.
    @Scheduled(cron = "0 0 0 1 * *")
    public void anotherJob() {
    // 실행될 로직
    }

    @Scheduled(cron = "0/10 * * * * ?")
    public void anotherJob2() {
    log.debug(new Date().toString());
    }
    }






    ErrorController



    @Controller
    @Slf4j
    public class ErrorController implements org.springframework.boot.autoconfigure.web.ErrorController {

    public static final String ERROR_PATH = "/error";
    public static final String ERROR_DEFAULT = ERROR_PATH + "/default";
    public static final String ERROR_401 = ERROR_PATH + "/401";
    public static final String ERROR_403 = ERROR_PATH + "/403";
    public static final String ERROR_404 = ERROR_PATH + "/404";
    public static final String ERROR_500 = ERROR_PATH + "/500";



    @RequestMapping(value = ERROR_DEFAULT, method = GET)
    public String defaultError() {
    return "error/default";
    }

    @RequestMapping(value = ERROR_401, method = GET)
    public String error401() {
    return "error/401";
    }

    @RequestMapping(value = ERROR_403, method = GET)
    public String error403() {
    return "error/403";
    }

    @RequestMapping(value = ERROR_404, method = GET)
    public String error404() {
    return "error/404";
    }

    @RequestMapping(value = ERROR_500, method = GET)
    public String error500() {
    return "error/500";
    }

    @Override
    public String getErrorPath() {
    return ERROR_DEFAULT;
    }
    }






    hibernate, springJPA

    package com.khh.project.web.admin;

    import com.khh.project.web.admin.domain.Authority;
    import com.khh.project.web.admin.domain.User;
    import com.khh.project.web.admin.repository.UserRepository;
    import com.omnicns.java.db.hibernate.Hibernater;
    import lombok.extern.slf4j.Slf4j;
    import org.hibernate.Criteria;
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
    import org.springframework.stereotype.Controller;
    import org.springframework.transaction.annotation.Transactional;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;

    import java.util.ArrayList;
    import java.util.List;

    @Controller
    @RequestMapping("/admin")
    @Transactional
    @javax.transaction.Transactional(rollbackOn = { Exception.class })
    @Slf4j
    public class AdminController {


    @Autowired
    public SessionFactory sessionFactory;

    @Autowired
    public UserRepository userRepository;


    @RequestMapping({"","/"})
    @ResponseBody
    String home() {
    return "admin main";
    }



    @RequestMapping("/save")
    @ResponseBody
    String save() {
    Session currentSession = sessionFactory.getCurrentSession();
    currentSession.beginTransaction();
    User u = new User();
    u.setUsername("zzz");
    u.setPassword("zzz");

    Authority a = new Authority();
    a.setUsername("zzz");
    a.setAuthority("vvv");
    List l= new ArrayList<>();
    l.add(a);
    u.setAuthorities(l);

    currentSession.save(u);

    currentSession.flush();
    currentSession.clear();
    currentSession.getTransaction().commit();

    return "ok";
    }



    @RequestMapping("/list")
    @ResponseBody
    List<User> list() {
    Session currentSession = sessionFactory.getCurrentSession();

    // currentSession.beginTransaction();
    Criteria crit = currentSession.createCriteria(User.class);
    // crit.setFetchMode("authorities", FetchMode.JOIN); //강제로 지연로딩 사용안함
    //lazy로되어있다면 아래처럼 DISTINCT_ROOT_ENTITY를하던가 트랜젝션을 닫지말고 그냥 흘려보네 그냥 지연로딩을 사용해도된다. 지연로딩 사용하면 각각 쿼리날라간다
    ////crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);//조인 쿼리가 날라간다
    //위처럼할수도 있지만 엔티티에도 넣어도된다 @Fetch(FetchMode.SELECT) 이것도 각각 날라간다
    List<User> list = crit.list();
    // currentSession.flush();
    // currentSession.clear();
    // currentSession.getTransaction().commit();

    // List<User> list = (List<User>) crit.uniqueResult();
    // currentSession.getTransaction().commit();
    // currentSession.close();
    return list;
    }

    @RequestMapping("/list2")
    @ResponseBody
    List<User> list2() {
    List<User> list = userRepository.findAll();
    return list;
    }
    @RequestMapping("/list3")
    @ResponseBody
    User list3() {
    User list = userRepository.findByUsername("khh");
    return list;
    }





    }












    Application

    package com.khh;

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.scheduling.annotation.EnableScheduling;
    import org.springframework.transaction.annotation.EnableTransactionManagement;

    @EnableAutoConfiguration
    @SpringBootApplication(scanBasePackages = {Application.BASE_PACKAGES})
    @EnableTransactionManagement
    public class Application {
    public static final String BASE_PACKAGES = "com.khh.project";

    public static void main(String[] args) throws Exception {
    SpringApplication.run(Application.class, args);
    }

    }












    spring boot로 프로젝트 시작하기전에 참고하셔서 사용하셨으면 좋겠습니다.


    먼저 삽질한거 공유합니다. 배워서 남주자~


    ps: libqa 참고 하였습니다.  퀵형~ 고마워욤~


    libqa github : https://github.com/visualkhh/libqa


    springboot template github : https://github.com/visualkhh/lib-spring/tree/master/boot/default_template




    visualkhh@gmail.com  감사합니다.




    댓글

Designed by Tistory.