spring boot jsp mybatis mariadb basic gradle with intellij ultimate lombok

반응형

 

 

spring boot jsp mybatis mariadb basic gradle with intellij ultimate

 

 

https://start.spring.io/   이곳에서 제공하는 스프링 부트 2.0.4, gradle, java, 웹, 시큐리티 등이 적용된 프로젝트 생성.

IntelliJ 나 eclipse 에서 New > Project 시에 Spring Initializr 를 통해 생성할 수 있다.

 

 

 

controller / domain / repository / service 의 패키지 명을 사용한다.

 

controller 는 웹요청을 처리하는 컨트롤러 이다.

domain 은 스프링 자바 프로그램 안에서 사용될 모델을 정의한 클래스 이다.

repository 는 mapper 의 mybatis 매퍼 xml 파일들의 sql 수행 후의 리턴 또는 sql 실행 을 코드로 정의한 인터페이스 들의 패키지 이다.

service 는 컨트롤러의 주요 기능인 웹요청 이외의 복잡하거나 공통적인 비즈니스 로직을 다른 레이어를 두어 구현해 놓은 곳 이다.

 

 

jsp 적용은 아래 application.properties 의 설정을 참조하고 webapp/WEB-INF/views 디렉토리에 jsp 파일들을 넣어준다.

 

 

현재 시점에서 좀 더 학습을 해야할 부분은 rest json 응답 적용 및 TDD 적용 이다.

 

 

아래의 대략적인 코드 구조를 통해 이해에 도움을 주고자 한다. 구체적인 코드는 비트버킷 참조.

 

 

build.gradle

dependencies {
    compile('org.springframework.boot:spring-boot-starter-web')
    compile('org.apache.tomcat.embed:tomcat-embed-jasper')
    compile('javax.servlet:jstl')
    compile('org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.2') // MyBatis 라이브러리
    compile('org.mariadb.jdbc:mariadb-java-client')// DB 연결 JDBC Library
    compile('org.springframework.boot:spring-boot-starter-security')
    compile('org.springframework.security.oauth:spring-security-oauth2:2.3.3.RELEASE')
    compile('org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:2.0.1.RELEASE')
    compile('org.webjars:jquery:2.1.1')
    compile('org.webjars:bootstrap:3.2.0')
    compile('org.webjars:webjars-locator-core')
    compile('org.webjars:js-cookie:2.2.0')
    compile('org.springframework.boot:spring-boot-devtools')
    compile('org.springframework.boot:spring-boot-starter-actuator')
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

 

 

application.properties

#server.servlet.context-path=/
server.port=8035
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.url=jdbc:mariadb://localhost:3306/bws
spring.datasource.username=root
spring.datasource.password=
mybatis.config-location=classpath:mybatis-config.xml
#logging.level.root=WARN
logging.level.root=INFO
logging.level.org.springframework.security=DEBUG
logging.level.com.thewavelet.buyworksellserver.repository=TRACE


# @EnableOAuth2Sso
#security.oauth2.client.client-id=219143695436190
#security.oauth2.client.client-secret=ff10c6c3560e89fb12291522b02665b7
#security.oauth2.client.access-token-uri=https://graph.facebook.com/oauth/access_token
#security.oauth2.client.user-authorization-uri=https://www.facebook.com/dialog/oauth
#security.oauth2.client.token-name=oauth_token
#security.oauth2.client.authentication-scheme=query
#security.oauth2.client.client-authentication-scheme=form
#security.oauth2.resource.user-info-uri=https://graph.facebook.com/me


facebook.client.client-id=219143695436190
facebook.client.client-secret=yoursecret
facebook.client.access-token-uri=https://graph.facebook.com/oauth/access_token
facebook.client.user-authorization-uri=https://www.facebook.com/dialog/oauth
facebook.client.token-name=oauth_token
facebook.client.authentication-scheme=query
facebook.client.client-authentication-scheme=form
facebook.resource.user-info-uri=https://graph.facebook.com/me


github.client.client-id=f6dec18f9e752415363c
github.client.client-secret=yoursecret
github.client.access-token-uri=https://github.com/login/oauth/access_token
github.client.user-authorization-uri=https://github.com/login/oauth/authorize
github.client.client-authentication-scheme=form
github.resource.user-info-uri=https://api.github.com/user

# @EnableAuthorizationServer
security.oauth2.client.client-id=acme
security.oauth2.client.client-secret=acmesecret
security.oauth2.client.scope=read,write
security.oauth2.client.auto-approve-scopes='.*'

 

 

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <package name="com.thewavelet.buyworksellserver.domain"/>
    </typeAliases>
    <mappers>
        <mapper resource="mapper/CityMapper.xml"/>
        <mapper resource="mapper/HotelMapper.xml"/>
    </mappers>
</configuration>

 

 

Application.java (스프링 부트 메인 클래스.main 함수 가진 클래스)

@SpringBootApplication
//@EnableOAuth2Sso
@EnableOAuth2Client
@EnableAuthorizationServer
@Order(200)
@MapperScan("mapper")
public class BuyworksellServerApplication extends WebSecurityConfigurerAdapter {

 

 

com.xxx.xxx.repository.CityRepository.java

@Mapper
@Repository
public interface CityRepository {

    @Select("select * from city where state = #")
    City findByState(@Param("state") String state);

    City selectCityById(int id);

}

 

 

resources/mapper/CityMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.thewavelet.buyworksellserver.repository.CityRepository">
    <select id="selectCityById" resultType="City">
        select * from city where id = #
    </select>
</mapper>

 

 

import.sql

drop table if exists city;
drop table if exists hotel;

create table city (id int primary key auto_increment, name varchar(45), state varchar(45), country varchar(45));
create table hotel (city int, name varchar(45), address varchar(45), zip varchar(45));

insert into city (name, state, country) values ('San Francisco', 'CA', 'US');
insert into hotel(city, name, address, zip) values (1, 'Conrad Treasury Place', 'William & George Streets', '4001');

 

 

 

 

 

 

 

스프링프레임워크 간략 설명

  • org.springframework:spring-core (IoC 컨테이너) : Inversion of Control 제어의 역전, Dependency Injection 의존성 주입의 기능을 수행. 프레임워크라 함은 기본적으로 DI 기능을 제공하는 것을 일컫는다. 자바빈을 조립하듯이 재컴파일 없이 교체할 수 있다. spring-beans, spring-context, spring-context-support, spring-expression(SpEL) 들이 스프링 프레임워크의 핵심 Core 를 담당한다.
  • spring-aop (Aspect Oriented Programming)
  • spring-messaging
  • spring-jdbc, spring-tx, spring-orm, spring-oxm, spring-jms (Data Access/Integration)
  • spring-web, spring-webmvc, spring-websocket, spring-webmvc-portlet
  • spring-test

스프링프레임워크 시작점

  • 자바 진영의 웹 애플리케이션 기술의 가장 기초에서 부터 시작한다.
    • 웹 컨테이너 (서블릿, JSP 처리를 위해 J2EE 스펙을 구현한 프로그램) : Tomcat, JBoss, Zetty, WebLogic, ...
    • 웹 컨테이너의 Deployment Descriptor (Tomcat 의 경우 web.xml) 에 서블릿을 등록하여 웹 요청을 처리한다.
    • 서블릿 3.0 이상부터는 web.xml 없이도 서블릿 컨텍스트 초기화 작업이 가능하도록 ServletContainerInitializer API 를 제공한다.
    • 서블릿 컨텍스트 초기화 란 web.xml 에서 했던 서블릿 등록/매핑, 리스너 등록, 필터 등록 과 같은 작업들을 말한다.
    • 자바 프로그램인 웹 컨테이너가 구동이 되며 해당 웹 컨테이너가 요청에 해당하는 서블릿 객체 생성 및 쓰레드 생성하여 처리한다.
    • 이러한 서블릿과 JSP 를 사용하기 위해서 servlet-api.jar, jsp-api.jar 라이브러리가 필요하다.
    • 서블릿(HttpServlet 클래스 상속)이란 웹 요청을 처리할 수 있는 클래스. HttpServletRequest, HttpServletResponse 파라미터를 가지는 doGet, doPost 등의 메소드를 가진다.
    • 리스너는 ServletContextListener, HttpSessionListener, ServletRequestListener, ServletContextAttributeListener, HttpSessionAttributeListener, ServletRequestAttributeListener 등이 있다. 서블릿의 Listener 는 웹어플리케이션의 주요 변화를 감지. 예를 들면 ServletContextListener 는 Context 의 라이프사이클을 감시하는 기능을 제공함. 웹어플리케이션의 시작과 종료시에 contextInitialized, contextDestroyed 메소드가 자동 호출됨.
    • 필터(javax.servlet.Filter 인터페이스 구현)는 서블릿/JSP 의 웹요청 실행 전/후 의 처리에 사용됨.
  • web.xml 에 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
    • 웹 어플리케이션이 시작되는 시점에 ApplicationContext 를 로딩하며, 로딩된 빈 정보는 모든 WebApplicationContext 들이 참조할 수 있다. contextConfigLocation 파라미터에 xml 경로를 지정. (리스너). 
    • WebApplicationContext 는 DispatcherServlet 을 의미. contextConfigLocation 파라미터에 xml 경로를 지정. (서블릿). <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  • public class EgovWebApplicationInitializer implements WebApplicationInitializer
    • 사용자 인증 권한처리를 분리(session, spring security) 하기 위해서 web.xml의 기능을 Servlet3.x WebApplicationInitializer 기능으로 처리할 수 있다. javax.servlet.ServletContainerInitializer 인터페이스를 구현하는 클래스를 만들고, 이 클래스의 이름을 /META-INF/services/javax.servlet.ServletContainerInitializer 라는 텍스트 파일에 적어주면 web.xml 없이도 3.0 이상에서 서블릿 컨텍스트 초기화가 가능하다. 이 구현 클래스에 @HandlesTypes 어노테이션으로 클래스를 지정해주면 WAS 가 시작될 때 지정된 클래스를 찾아서 onStartup 메소드의 인자로 서블릿 컨텍스트 객체와 지정된 클래스를 넣어준다. 스프링에서는 이것이 이미 적용되어 있어 WebApplicationInitializer 라는 인터페이스를 구현한 클래스를 구현하면 된다.
    • 어플리케이션 컨텍스트, 웹 어플리케이션 컨텍스트, 필터 등을 프로그램적으로 등록, 설정할 수 있다. web.xml 은 xml 에 리스너, 필터, 서블릿을 고정적으로 등록하여 사용하지만 WebApplicationInitializer 를 사용하면 조건에 따라 프로그램적으로 이를 구현할 수 있다. 따라서 globals.properties 에 Globals.Auth=session 이나 Globals.Auth=security 와 같은 설정을 통해 시큐리티 방식을 변경할 수 있게 구현할 수 있다.

스프링프레임워크 인증/인가

  • Filter 는 스프링의 어플리케이션 컨텍스트와 같은 레벨에서 동작한다고 볼 수 있다. 어플리케이션 컨텍스트는 리스너로 등록되고 웹 어플리케이션 컨텍스트 (DispatcherServlet)은 서블릿으로 등록되기 때문에 Filter 는 DispatcherServlet 내에서 후킹되는 Interceptor 보다 더 전역적인 부분에서 동작한다. 스프링 시큐리티는 기본적으로 Filter 들의 체인으로 구성되어 있다.
  • 기본적으로 스프링 시큐리티의 인증 방식은 세션 쿠키 방식을 사용한다. JWT, OAuth Token 등과 같은 방식으로 사용하려면 설정을 추가하여야 한다. 전자정부프레임웍의 Globals.Auth=session/security 에서 session/security 모두 기본적으로 세션 방식을 사용하는 것이다. 단지 security 설정 값의 경우 spring security tablibs 를 통해 적용하는 것이며 session 설정 값의 경우는 LoginPolicyFilter 를 통해서 적용하는 것이다.
  • Interceptor 는 DispatcherServlet 에서 Controller 로 요청이 가기 전과 Controller 처리 후 DispatcherServlet 후 View 로 가기 전에 수행된다. 기본적으로 스프링 시큐리티가 적용되어 로그인 페이지 등의 설정 값을 셋팅하고 interceptor 에서는 SecurityContextHolder.getContext().getAuthentication() 와 같이 authentication 등을 가져와서 authority 라던가 기타 필요한 값들을 request 애 넣어주거나(preHandle) 또는 DispatcherServlet (Controller 처리 후) View 로 가기 전인 (postHandle) 부분에 필요한 값들을 modelAndView 에 셋팅하여 View 로 넘겨주는 식으로 사용한다. 즉, 스프링 시큐리티는 필터 기반으로 설정을 통해 적용되고 인터셉터 부분에서는 시큐리티 적용이라기 보다 관련 객체를 가져와서 요청에 필요한 정보를 셋팅하는 지점으로 사용하는 것이 보편적이다.
  • 세션쿠키: 일반적인 세션 인증에서 로그인 되었다는 것을 세션을 통해서 구현하게 되는데 이 세션이라는 것은 서버 측의 작은 저장소일 뿐이고 서버 측의 기술이다. 실질적으로 클라이언트와의 통신은 쿠키라는 것을 통하게 된다. 세션이라는 것은 HTTP 통신과 관련 없는 서버측의 자그마한 인증을 위한 정보 저장 공간을 다루는 기술일 뿐이다. Cookie 와 Set-Cookie 헤더를 통한 서버의 세션키 값을 브라우저에 내려주고 브라우저가 모두 닫히면 로그아웃 되도록 하려면 쿠키의 만료를 적지 않으면 되고 keep signed 하려면 쿠키의 만료일을 지정해주면 된다. 이 쿠키의 세션키 정보가 삭제되면 로그아웃 되는 것이다. 쿠키는 항상 서버측에 Cookie 라는 헤더로 전송되고 서버는 항상 Set-Cookie 라는 헤더로 응답한다. 이 때 보통 사용되는 쿠키는 세션 쿠키라고 불리며 세션 쿠키란 저장 기간이 해당 브라우저가 종료되기 전까지인 쿠키를 의미한다. 따라서 일반적인 브라우저의 경우 쿠키 허용이 기본 옵션이고 이러한 옵션은 크로스 도메인까지 허용을 의미하지만 사파리의 경우 방문한 웹 사이트 허용 이라는 옵션이 기본이고 이것은 자신이 방문한 페이지의 도메인과 일치하는 곳과의 쿠키만을 허용한다는 의미이다. 이러한 이유로 SPA 로 만든 클라이언트 스크립트만을 다운받아 도메인이 다른 API 서버로 인증을 위한 API 를 호출할 경우 쿠키가 적용되지 않아 로그인이 안된다. 클라이언트 쪽에서 세션쿠키를 없앨 수는 없나? 서버에서 로그아웃 하는 것은 클라이언트 쪽에서 할 수 없다고 한다. 브라우저의 세션 쿠키를 강제로 지워버리면 더이상 로그인 상태가 아닌거 아닌가? 라고 생각할 수 있는데 보안 상 세션쿠키 부분을 직접 컨트롤 할 수 없게 되어 있는 듯 하다. 세션쿠키 또한 일반적인 쿠키이지만 httpOnly 파라미터가 붙은 것은 읽고, 쓰고, 삭제하는 것을 HTTP 요청을 통한 방식을 제외하고는 불가하다. 예를 들어 자바스크립트로 쿠키를 변경하는 것이 불가하다.

어노테이션

  • 스테레오 타입으로 빈을 등록, @Autowired 나 @Resource를 사용하여 가져와서 사용
  • @Component, @Repository (DAO), @Service, @Controller : 스테레오타입 
    • <context:component-scan base-package="org.example" /> 이거 해주면 mvc:annotation-driven, context:annotation-config 모두 적용한 것을 포함한다. @Autowired, @Qualifier 를 인식할 수 있다. @Component 보다 @Repository, @Service, @Controller 를 사용하는 것이 좋다.
  • @Autowired (springframework), @Resource(JSR-250), (@Qualifier, @Required) : 빈 참조를 위해 사용
    • @Resource 가 프레임워크 비종속적이라 더 좋다. @Resource(name="") 와 같이 name 참조가 우선. @Autowired 는 타입 참조를 우선 시도.
  • @Controller, @RequestMapping, @RequestParam, @ModelAttribute, @SessionAttributes, @CommandMap : MVC
  • @Mapper (Mybatis)

 

Lombok

  • Lombok
  • @Data, @Getter/Setter, @ToString, @EqualsAndHashCode, @Value, @Builder 등 어노테이션을 통해 단순화
  • Maven 추가
    • <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> <scope>provided</scope> </dependency>
  • Intellij: 
    • Preferences > Plugins > Lombok (롬복 플러그인 설치)
    • Restart Intellij
    • Build, Execution, Deployment > Compiler > Annotation Processings (보통은 이미 체크 되어 있음)
  • Eclipse:
    • java -jar lombok.jar > 이클립스 체크 > Install/Update
반응형

댓글

Designed by JB FACTORY