login 관리

Spring 2017. 11. 20. 21:59

Login구현시에는 cookie + session을 섞어서 쓰는게 일반적이다. REF


쿠키는  날짜를 지정가능

세션은  id/비번등 주요정보 저장 가능.  단 브라우저 종료시 사라짐. 


즉,

세션이 브라우저 종료시 사라지는 문제가 있으므로, 

쿠키를 이용해 이를 보완해야 한다.  쿠키에 날짜/시간이 지정 가능하므로 이를 이용해서 세션ID등을 저장해 보완하면된다.




Posted by yongary
,

Spring web Reactive

Spring 2017. 10. 30. 22:52

(spring에서 reactive 가능한 방식들)


1.  DeferredResult +  RxJava  + CompleteFuture   Ref


2. webFlux  using Mono or Flux 


===================================================

infoQ_lecture Ref1

  

  - WebFlux에서 사용하는 reactor프로젝트의 

    Mono는 backPressure도 지원한다.     (RxJava의 single은 지원하지 않음)


    Flux는 RxJava의 observable과 비슷.. 무한개의 데이타를 지원함..(메모리 안쓰니까..)



그리고, RxJava는 foundation Level이고

WebFlux는 Functional Level이라서 당연히 섞어서 쓸 수 있을 것 같다.(아직 미테스트)


spring-boot-start-webflux를 사용하면 웹서버가 tomcat이 아니고 netty네요. (async를 더 잘지원하기 때문)




utube-REF


(16:00)



(26:00)


                                                                                                                                   or Netty or UnderTow





Spring Web Flux - utubeRef




Posted by yongary
,


<AssertJ의 javadoc_REF 기초REF>


import static org.assertj.core.api.Assertions.assertThat


.isEqualTo

.contains

.startWith

.endsWith


등 기존 junit assertTrue보다 유연하게 사용가능.





JUnit JavaDoc


JavaDoc : Assert class




@Parameters - 음 javadoc에서 잘 안보이네요.

@Test
@Parameters({
"10000, 8, 32",
"100000, 12, 128",
})
public void realUsage(int numSerials, int numDigits, int hashKeySize)


@DataPoints + @Theory 

 @DataPoints
 public static String[] dataPoints = new String[] { ... };
 
 @DataPoints
 public static String[] generatedDataPoints() {
     return new String[] { ... };
 }
 
 @Theory
 public void theoryMethod(String param) {
     ...
 }


Posted by yongary
,

http://springmvc.egloos.com/535572 



@ModelAttribute

 - controller로 접근시 항상  해당항목은 자동으로 생성/세팅이 되는 자동세팅 필드이다. 


@SessionAttributes

 - 동일한 이름의 모델객체를 발견하면 자동으로 세션값으로 변환하여 가지고 있는다.  




@ExceptionHandler

  - Controller 내에 정의해 놓으면, 그 controller내에서 발생하는 해당 Exception을 다 잡아준다.

    따라서, 함수안에서 catch를 할 필요가 없어진다.


@ControllerAdvice 

  - 위의 ExceptionHandler같은 것들을, 해당 controller뿐 아니라, 전체 어플리케이션에서 동작하도록 해준다.
    (@RequestMapping을 보고 찾음)


  여기에 영향받는 어노테이션은 

   @ExceptionHandler

   @InitBinder

   @ModelAttribute

  이다. 


Posted by yongary
,

@Bean 사용법

Spring 2017. 5. 8. 14:19

@Autowired 를 사용할 경우에는 classpath내에 존재해야 하는데,

그게 여의치 않거나 새로운 생성자가 필요한 경우에는


생성자를 직접 정의하면서 @Bean을 사용할 수 있다. 


1.정의시:


@Configuration

public class OkHttpClientConfig {

@Bean(name = CHAT_BILLING_HTTP_CLIENT)

OkHttpClient chatBillingHttpClient() {

OkHttpClient client = new OkHttpClient();

client.setTimeOut(blabla)


return client;

}



2.사용시:


@Qualifier(OkHttpClientConfig.CHAT_BILLING_HTTP_CLIENT)

@Autowired

OkHttpClient chatBillingHttpClient;




Posted by yongary
,

RestTemplte.getForEntity 등 각종 함수에서 RestClientException (RUNTIME Exception)을 throw한다.


하지만 이 에러는 code를 표시하지 않기 때문에,


HttpClientErrorException을 catch하는게 좋다.




Class HttpClientErrorException

이렇게 HttpClientErrorException은 RestClientException을 상속받으며, 우리가 http를 주로사용하기 때문에

대부분이 여기에 해당된다.


사용법은 REF 첫번째 answer과 같이... 사용하면 된다.


try {
        ResponseEntity<StoreDto> r = restTemplate.getForEntity(url, StoreDto.class, m);
    }
    catch (final HttpClientErrorException e) {
        System.out.println(e.getStatusCode());
        System.out.println(e.getResponseBodyAsString());
    }


404에러 등이 잡힌다. 


Posted by yongary
,


spring에서 이전페이지로 복귀는 request의 referer를 이용해서 가능하다.


이전 페이지에 추가적인 데이타를 보내고 싶다면

addFlashAttribute로 가능하다. 


import javax.servlet.http.HttpServletRequest;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

String myFunction(HttpServletRequest request,
RedirectAttributes redirectAttributes,
) {

redirectAttributes.addFlashAttribute("okList", "AA BB CC");

String referer = request.getHeader("Referer");
return "redirect:"+ referer;
}


Posted by yongary
,

Jms + ActiveMQ

Spring 2017. 3. 13. 16:34

spring에서 msg를 전달하는 가장 흔한 방법은

JMS(+jmsTemplate)과 ActiveMQ(by apache)를 이용하는 방법이다. 물론 ASYNC 메시징이다.


ActiveMQ를 사용하고자 하면, ActiveMQConnectionFactory가 JMSConnectionFactory로써 제공된다.


 -디폴트 포트: 61616 



<Send>

ConnectionFactory cf = new ActiveMQConnectionFactory("tcp://localhost:61616";

Connection conn = cf.createConnection();


session = conn.createSession(..);


MessageProducer producer = session.createProducer(destination);


producer.send( session.createTextMessage('hello')..)




<Receive>

MessageConsumer consumer = session.createConsumer(destination);
Message message = consumer.receive();



<JmsTemplate을 사용하면 좀더 간단해진다>


jmsOperations.send( new MessageCreator() { ......blabla }

또는 컨버팅 필요시

 

jmsOperations.convertAndSend


Posted by yongary
,

몇몇 Annotation

Spring 2017. 3. 9. 18:48

 @ModelAttribute on a method argument -  indicates the argument will be retrieved from the model. If not present in the model, the argument will be instantiated first and then added to the model.


@Retryable (a.Exception, b.Exception 지정가능. 미지정시 상시.. )


@Recover (a.Exception) : a.Exception으로 실패시에에만 호출되어서.. 특별한 뒷처리 및 로그작업등 가능.



@Component( name부여가능 )


@Profile("profile_name")  - name에 해당하는 profile이 active일 때만, Bean이 생성됨. dev test등 주로 이용.


@Conditional - 조건부 Bean생성. 


@GatherJob    (USER_Defined)

  - 나중에 모으고 싶은 것들을 임의로 선언한다. (class는 있어야 죠 , 간단한 빈깡통 Interface면 됨.)

Set<Class<?>> gather = New Reflections(My.class.getPackage().getName())

.getTypesAnnotatedWith(GatherJob.class);


@Qualifier("my name") - 

Posted by yongary
,

REF


Mokito의 ArgumentCaptor를 사용해, insert/update같은 동작을 간단하게  hooking할 수 있다.


(예제)

final ArgumentCaptor<Ticket> logCaptor = ArgumentCaptor.forClass(Ticket.class);
verify(chatTicketRepository).update(logCaptor.capture());
Ticket ticket = logCaptor.getValue();

assertThat(ticket.getStatus(), is(TicketStatus.EXPIRED));



좀 더 복잡한 경우는, ArgumentMatcher를 이용해 복잡한 비교를 할 수 있다. 



파라미터를 hooking하는 다른방법: REF

when(mockObject.myMethod(any(parameterClass.class))).thenAnswer(
                invocation -> invocation.getArgumentAt(0, parameterClass.class));


Posted by yongary
,

MySql Row Lock

Spring 2017. 2. 19. 23:14

InnoDB Lock: REF



엔진확인 

   mysql> show engines;

   mysql> show variables;   (autocommit등의  Variables 확인) 



Spring 의 @Transactional과 함께 사용하면 autcommit이 일반적으로는 자동으로 풀렸다가 다시 설정 된다..  REF(Stack-overFlow)  REF



=======================================


Mysql에서 엔진이 innodb(요즘 보통다 이러함)일 경우, row level lock이 지원된다.REF


- start transaction   -> 작업 ->  commit 순으로 수행하면 된다.


start transaction;

select * from sales_item where id=99  lock in share mode;

commit; 



transaction도중에 다른 작업이 또 들어오면

  1. wait이 되거나 (위 REF 참조)

  2. 자동으로 에러가 나서 거절이 되는데..  

(1,2번 중 원하는 데로 선택을 어떻게 하는지 ... 연구 중)



 select for update도 있긴한데.. 한 문장 밖에 안되므로 좀 활용도가 떨어지지만
 spring의 @Transactional과 같이 사용하기에 유리하다.    REF


일단 설정 파일에서
init_connect = 'set autocommit=0'
으로 설정하여 오토커밋을 해제합니다. 기본적으로 mySQL 설치 시엔 오토커밋일 설정되어 있습니다



innodb_lock_wait_timeout 확인 방법.

show variables like '%wait_timeout%';

Posted by yongary
,

MockMvc결과가 문자열 json일 때 쉽게 체크하는 법은 jsonPath를 사용하는 방법. REF



그러나, 결과가 Attribute내에 Object 등으로 오는 경우가 많은데..

이럴 경우에는 org.hamcrest.Matchers 를 사용하면 좋다.



<Attribute가 단순 String일 경우>

.andExpect(model().attribute("ReserveResult", org.hamcrest.Matchers.containsString("rtncd=0000")));



<(result내의 Model)  AttributeJson Object일 경우> org.hamcrest.Matchers.CustomMatcher를 사용한다.

import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;

//Check if rtncd="0000"
Matcher< ResultClass > resultMatcher = new CustomMatcher< ResultClass >("") {
public boolean matches(Object object) {
return ((object instanceof ResultClass) && ((ResultClass) object).getRtncd().equals("00"));
}
};

mockMvc.perform(request)
.andDo(print())
.andExpect(status().is3xxRedirection())
.andExpect(model().attribute("reserveResult", resultMatcher));


Posted by yongary
,

<module-js> REF

Single Page Web Application에서 표준화를 해주는 라이브러리이다.

아래의 browserify와 함께 스면 좋다. 




<browserify> REF


  node코드들을 browser에서도 쓸 수 있게 해주는 library이다.


    간단히 설치:

    $npm install -g browserify 


  대표적으로   require('modules') 코드를 script 안에서 많이 쓴다.


Posted by yongary
,


========node와 연계해서 빌드도 가능===========REF

spring과 npm을 연계해서 빌드시에,


$npm run build:js  등으로 package.json을 이용해 직접 build명령을 내릴 수도 있다.



npm  REF

  - npm은 필요모듈 설치시, 글로벌설치/로컬설치 가능. 일반적으로는 로컬설치가 좋지만 선택이 어려울경우가 있다.

   

npm 환경설정 npm   


각종  npm 패키지 명령:  REF

   - npm list browserify

   - npm view browerify version ( 최신버전확인)

   - npm remove browserify

   - npm install (-g) browserify   (-g: global)




<빌드 LifeCycle>: REF

default 빌드 LifeCycle은 다음과 같다.

  • validate - validate the project is correct and all necessary information is available
  • compile - compile the source code of the project
  • test - test the compiled source code using a suitable unit testing framework. These tests should not require the code be packaged or deployed
  • package - take the compiled code and package it in its distributable format, such as a JAR.
  • verify - run any checks on results of integration tests to ensure quality criteria are met
  • install - install the package into the local repository, for use as a dependency in other projects locally
  • deploy - done in the build environment, copies the final package to the remote repository for sharing with other developers and projects.


아래와 같이 springBoot 실행도 가능.

$mvn springboot run  REF


------------------------------------------------------------------------------------------------------------


=====maven 확인========  REF

$mvn -version


없으면 mac의 경우에는 brew install maven



=======BUILD+package=============== REF

$mvn package


빌드 에러메시지를 상세히 보고 싶다면


$mvn -e -X package  




===기본설명===

spring 에서   pom.xmL을 이용해 maven 의존성 관리를 한다.


maven을 직접사용하는 방법도 있는데

maven 설치 후


mvn archetype:generate     해서 각종 값을 넣고 나면 (주로  package 명으로 넣으면된다)

pom.xml까지 자동 생성이 되며,


mvn compile exec:java -Dexec.mainClass=com.ky.App

 으로 바로 커맨드 상에서 실행한다.


매우 유용하다. 



=== MOJO ============


MOJO : Maven plain Old Java Object 이다.    REF

            - maven의 java-plugin을 만드는데 사용된다.


만들때는 @Mojo를 써서 간단히 만들 수 있다는데, 만들일 은 잘 없고.. 쓸 일은 많으니.. .. 쓸 때 위주로 보면.


groupIdThis is the group ID for the plugin, and should match the common prefix to the packages used by the mojos
artifactIdThis is the name of the plugin
versionThis is the version of the plugin
packagingThis should be set to "maven-plugin"
dependenciesA dependency must be declared to the Maven Plugin Tools API to resolve "AbstractMojo" and related classes


plugin내의  mojo를 실행시키려면  

  - "$mvn sample.plugin:hello-maven-plugin:1.0-SNAPSHOT:sayhi" 로도 가능하다.

       ($mvn groupId:artifactId:version:goal )


Posted by yongary
,

REF-spring  REF-etc     Validataion-Group



spring 에는 annotation으로 form 필드를 자동으로 체크할 수가 있다.


일반적으로는 

xxForm.java 파일을 하나 만들고 그 안에 Form과 일치하도록 모든 Field를 정의한 다음에...


각 필드별로 여러가지 constraint를 정의할 수 있다. 


@Pattern :  Regex패턴 체크.

@NotNull  @Null 

@Size(min=2, max=30) 

@Past (지난 날짜) @Future

@Max @Min @DecimalMax @DecimalMin 2Digits

@AssertFalse @AssertTrue


<기본사용>


예제)
public class MyForm {

@NotNull(message = "{error.not_input}")
@Length(max = 3, message = "{error.max_length}")
private String age;

@NotNull(message = "{error.not_input}")
@Length(max = 255, message = "{error.max_length}")
private String name;

@Pattern(regexp = MyConstant.MAIL_ADDRESS, message = "{error.mail_address_format_error}")

private String email;


}

 

컨트롤러에서 아래와 같은 형태로 값을 받는다.

public String checkPersonInfo(@Valid PersonForm personForm, BindingResult bindingResult)




==========1=====================

간단히 Override로 Custom Validator를 만들 수 있다.

@Data
@NoArgsConstructor
@CmsMemberMailValidator(newMailAddressField = "newMailAddress", mailConfirmField = "mailConfirm")
public class CmsMemberMailModifyForm {

private Long id;

private String displayName;

private String status;

private String organizationName;

private String mailAddress;

@NotNull(message = "{error.mail_address_null_error}")
@Pattern(regexp = WebConstantShared.MAIL_ADDRESS, message = "{error.mail_address_format_error}")
private String newMailAddress;

@NotNull(message = "{error.mail_address_null_error}")
private String mailConfirm;

public static CmsMemberMailModifyForm of(CmsMemberDetail cmsMemberDetail) {
CmsMemberMailModifyForm form = new CmsMemberMailModifyForm();
BeanUtils.copyProperties(cmsMemberDetail, form);
return form;
}
}

 


@Target({ TYPE }) @Documented
@Retention(RUNTIME)
@Constraint(validatedBy = Validator.class)
public @interface CmsMemberMailValidator {
String message() default "{error.mail_address_format_error}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String newMailAddressField();
String mailConfirmField();
class Validator implements ConstraintValidator<CmsMemberMailValidator, Object> {
private String message;
private String newMailAddressField;
private String mailConfirmField;
@Override
public void initialize(CmsMemberMailValidator constraintAnnotation) {
message = constraintAnnotation.message();
newMailAddressField = constraintAnnotation.newMailAddressField();
mailConfirmField = constraintAnnotation.mailConfirmField();
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
BeanWrapper beanWrapper = new BeanWrapperImpl(value);
String newMailAddressValue = (String) beanWrapper.getPropertyValue(newMailAddressField);
String mailConfirmValue = (String) beanWrapper.getPropertyValue(mailConfirmField);
//check only different case (null & blank Error_Message is processed on @NotNull annotation)
if (newMailAddressValue != null && StringUtils.isNotBlank(newMailAddressValue)
&& mailConfirmValue != null && StringUtils.isNotBlank(mailConfirmValue) && !mailConfirmValue
.equals(newMailAddressValue)) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(message)
.addPropertyNode(mailConfirmField)
.addConstraintViolation();
return false;
}
return true;
}
}
}


==========2===================

위보단 약간 복잡하지만 좀 더 많은 기능이 있는 @InitBinder를 이용해

Custom Validator를 만들 수 있다.


Custom Validator: spring-REF   Ref-InitBinder

Custom Validation Class를 만들 수도 있다.

.  



< Valid vs Validated >  REF1simple, REF2,


Validated는 spring 소속이고, Valid는 java소속인데

Validated가 Validataion-Group을 지정할 수 있다.



 에러메시지도 출력가능하다.   REF




Posted by yongary
,

Selenium 을 이용하면 여러 브라우저를 직접구동시켜 다양한 테스트를 수행하므로

고급 웹서비스에서는 이 방식을 사용하는 것이 좋다.


하지만 간단한 웹페이지라면 이런방식이 부담이 될 수 있는데,

간단한게  spring의  HtmlUnit을 이용하면 되지만(REF) 약간 부족한 부분을

Selenium의 WebDriver만 이용하는 방법이 있다.    이경우 Selenium서버는 필요없다. REF


<비교설명> REF  챕터2.

Posted by yongary
,

MockMvc

Spring 2017. 1. 6. 15:26

영문 spring test 환경 (MockMVC+Junit) 기본설명  : REF


영문Test Guide URL



Spring에서 지원하는 MockMvc로도 거의 모든 테스트가 가능하다.

(가끔 Mockito가 필요하면 둘을 섞어서 쓰면 되는 정도로 보인다)



이전엔 Mockito가 많이 필요했지만, 필요성이 조금 줄어든 것 같다.



아래는 MockMvc로 컨트롤러를 테스트 하는 예제이다. 

  - Controller Test annotation (spring-boot 1.4 부터 지원:)  REF




<MockMVC 기본>  REF

1. Request

-perform

-accept

-with

-param

-cookie

-sessionAttr


2. Response

-andExpect

-andDo

-andReturn



<andExpect> 에서 여러가지 확인이 가능한데.. 주로 많이 쓰는 것들은

.andExpect(status().isOk())
.andExpect(content().json(expected));
.andExpect(status().is3xxRedirection());

.andExpect(view().name("list"))
.andExpect(MockMvcResultMatchers.model().size(1));

등등이다.



ModelAndView: 데이타가 복잡할 경우에도 테스트가 가능한데....  

        View name = redirect:view

             View = null

        Attribute = MyTicketReserveResult

            value = MyTicketReserved(code=0009, msg=nulll)

           errors = []


와 같은 json을 확인하려면.. (아직 확인 중)


.andExpect(jsonPath("$[1].rtncd").value("0009"))


Posted by yongary
,


Spring 에서  web Test시에 user를 mock하는 방법으로 2가지를 현재 보고 있는데,

차이점이나 장단점에 대해서는 좀 더 공부를 할 예정이다.



1. import org.springframework

        .security.authentication.UsernamePasswordAuthenticationTokenREF


  

UserDetails user = this.userDetailsService.loadUserByUsername(username);

        UsernamePasswordAuthenticationToken authentication = 
                new UsernamePasswordAuthenticationToken(
                        user, 
                        user.getPassword(), 
                        user.getAuthorities());



2. import static org.springframework

         .security.test.web.servlet.request

         .SecurityMockMvcRequestPostProcessors.user;


  RequestBuilder request = get("/my_web_url")

  .with(user (myUser));



AuthenticationManager 참고: REF

Posted by yongary
,

Mockito 사용법

Spring 2016. 12. 28. 18:09

javadoc   한글개요   goodTutorial



Mockito에서   @Mock @InjectMocks @Spy 의 차이점:

(작성 중: 현재 정확하지 않음)


@InjectMocks를 우선 사용해서 서비스/Controller등을 만들고

컴포넌트를 @Mock를 이용해서 삽입한다.  REF


둘을 하나의 object에 동시에 사용하고 싶을 경우, 동시에 사용할 수 없기 때문에

@InjectMocks와 @Spy를 동시에 사용할 수 있는데

이경우  when()함수를 사용하면 실제 함수를 호출하기 때문에  doReturn함수를 사용한다.  Ref



<검사함수들>

when  :  mock객체는 기본값을 return하기 때문에 Stubbing을 통해 원하는 값을 리턴한다.      REF

 - when(mockedGenerator.getNextId()).thenAnswer(new Answer<Integer>(


assertTrue

  assertNotNull


doReturn  Ref   -override도 가능.

  doThrow  -  void type을 stub할때, when이 java문법에 맞지않아서  
                    doThrow(new Exception()).when(mock).method() 이렇게 사용.

  doNothing

           ex) doNothing().when(authenticationManager).authenticate(Matchers.any(Authentication.class)); 

  doAnswer 

           ex) 

doAnswer(new Answer<Authentication>(){

@Override
public Authentication answer(final InvocationOnMock invocation) throws Throwable {


//case token

ObjectPostProcessor<Object> objPostProc = (
new ObjectPostProcessor<Object> () {
public Object postProcess(Object bean) throws BeansException {
System.out.println("BeforeInitialization : " );
return bean; // you can return any other object as well
}
});

final PreAuthenticatedAuthenticationToken token = (PreAuthenticatedAuthenticationToken)(invocation.getArguments())[0];
Authentication authentication = (new AuthenticationManager(){
@Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
return (new AuthenticationManagerBuilder(objPostProc)).getOrBuild().authenticate(authentication);
}
}).authenticate(token);
return authentication;
}

}).when(authenticationManager).authenticate(Matchers.any(Authentication.class));



Verify 사용법 : test된 코드들의 횟수체크.. . REF

  - verify ( object,  atMost/never/times/atLeast/timeout ).함수명(  any(param) OR eq(param) ) 등.


InOrder  :  object간 순서 체크. 

verifyNoMoreInteractions : mock의 행동 다 검증했는지 확인.


Posted by yongary
,

Service-as-a-VM & Docker

Spring 2016. 12. 3. 03:34

서비스를 개발하다 보면, 여러개의 서브-서비스로 나누어지게 되고 개발도 따로 하게되는 문제가 있지만,

배포에서 큰 문제가 된다. java version이 다르다던가 하는 사소한 문제부터 복잡한 수많은 문제가 생기게 되면서

배보다 배꼽이 큰, 즉 개발보다 deploy가 더 어려워지는 경우도 발생이 되기 때문에,


이런문제를 해결하는 개념으로 Service-as-a-VM 이 등장하였다.

(넷플릭스에서는  AMI 패키지 방식으로 아마존EC2에 배포를 한다) AMI=아마존 머신 이미지.



 그러나, 

VM자체도 부하가 크고 배포도 상당히 어렵기 때문에,  

간단한 파일로 배포를 하고, 프로세스 형태로 동작하는 가벼운  Docker 가 훨씬 더 유리하게 되면서

spring-boot 에 Docker를 결합한 방법이 많이 사용되고 있다.  REF(source 포함)




<Docker>한글REF REF

 


Docker image는 read-only 파일시스템이다. 

   layer  구조라서 배포시에 없는 layer만 배포하면 되고, 이미지 생성도 필요한 것만 되므로 매우 빠르다


Docker container 는 1개 또는 몇개의 sandboxed process로 이루어진  running image이다.  즉 프로세스라고 보면 된다.

  container 단위로  포트 등이 격리가 된다.  



Posted by yongary
,

<동작구조>


Request --->  DispatcherServlet  ---------------------------> Haldlermapping

                                     ----------------------------> Controller

                                     <--Model & view name--

                                     ---------------------------->ViewResolver

                                     ----------------------------> View

      response <--------------------------------------------



<어노테이션>  annotation-Driven.   @Component로 하고,  component-scan으로 자동으로 Bean으로 등록. 

  @Controller

  @RequestMapping( { "/", "/homepage" } )   =>  controller에서 이 String array를 통해 여러 request 수용가능.

  public class myController {....


 

  -param 처리  /show?my_id=12345 URL처리하려면

   public String show( @RequestParam("my_id") long myId, Model model) {
   }

  - URL방식 param처리

   @RequestMapping(value="/{my_id}", method=RequestMethod.GET)
   public String show( @PathVariable("my_id") long myId, Model model) {

   }





<Spring's MockMVC>

  myRepository mockRepository =

     mock (myRepository.class);

   when (mockRepository.findData())

     .thenReturn(expectedData);


     .setSingleView  .build  .perform  .andExpect 등.   



<Web controller에>

 @Autowired 생성자. 가능.    #146 



  Model: View로 전달할 key,value Map.이며 아래와같이 사용함.

   <c:forEach  items="${modelName}" var="oneData">

<c:out value="${oneData.kv1}" />

   </c:forEach>

   => spring에서 만든 sf (spring form) tag library도 존재.
    sf:input 이런식으로 사용하며 Model과 연동이 잘된다. 

   => srping에서 만든 s tag library도 존재

    s:message   리소스 파일등에서 읽어서 메시지 출력.




<ViewResolver>

  InternalResourceViewResolver를 기본적으로 쓰는데, 그 외 UrlBasedViewResolver, XmlViewResolver, 

  TilesViewResolver (Apache Tiles를 이용해 Web페이지 구성, tiles는 t tagLib 사용.),

  ThymeleafViewRelolsver ( Tyhymeleaf = jsp 사용성 개선한 범용 template-th tag 사용하며 html처럼 막 편집가능
        즉, jsp안에 <> <c:> 이런거 섞어쓰면서 오는 <>개수 혼란 등을 피할 수 있음.)
  
  등 10개 이상의 용도에 따른 ViewResolver가 존재한다.

 

 

<기타 & Advanced>

WebApplicationInitializer

- DispatcherServlet 외에 추가적인 servlet나 filter를 등록해서 사용가능.

- onStartup & getServletFilters 메쏘드 override .   (#7.1)

 

multipart는 보통 StandardServletMultipartResolver 를 사용.

 

 

flash attribute: redirect시 Object전달 같은 일회성 data전달을 model을 이용해 지원.

-사용법: model.addFlashAttribute("spitter", spitter);

 


 Web Flow:  spring MVC확장 framework로 flow를 관리한다.

     - status, transitions, flow_Data 의 3개 요소로 구성됨.



Posted by yongary
,

spring에서 bean은

Spring 2016. 6. 29. 16:48

spring에서 bean은 아무 생각없이 만들면

spring container에서 singleton 으로 만들어 준다.

(즉, 전체 sping container에서 항상 동일한 하나의 global instance로 bean을 만들어 준다)

 

따라서 immutable이고 status도 없이 만드는 것이 좋음.

 

만약, 다른 용도로 만드려면

 

Prototype Bean - 매번 생성

Session Bean  - WEB 세션별로 생성

Request  Bean - WEB Request별로 생성

이 존재하며..

 

 

@Component

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)     과 같이 annotate 한다.

    - @Scope("prototype") 만 해도 되지만.. 위에 방식이 더 안전.

 

 

xml에서 할 경우에는
<baen id="note" class="my.Note" scope="prototype"> 으로 한다.




참고:  @Component는 autoscan이 되지만 @Bean의 경우에는 안되므로

@Bean을 직접 사용할 경우에는 method body에서 생성해서 return해야 한다.  REF


Posted by yongary
,

spring DM + OSGi

Spring 2015. 12. 30. 11:02

 

spring DM이란:

- spring framework의 Core를 이용해서 Dynamic Module을 지원하는 방식으로서 Server모듈이 개발되어 있다.

주로 OSGi를 이용하게 됨.  REF-SITE(영문)

 

OSGi:

- eclipse의 plug-in에서 주로 사용하던 java용 plug-in개발 framework.

 

 

OSGi를 이용한 spring DM 개발방식 :  REF-SITE(개념),    REF-SITE(실전) 

Posted by yongary
,

maven

Spring 2015. 12. 4. 11:29

spring 에서   pom.xmL을 이용하는 경우가 많은데

이것은 maven 의존성 관리툴에서 사용하는 파일이다.


maven을 직접사용하는 방법도 있는데

maven 설치 후


$ mvn archetype:generate     해서 각종 값을 넣고 나면 (주로  package 명으로 넣으면된다)

pom.xml까지 자동 생성이 되며,


mvn compile exec:java -Dexec.mainClass=com.ky.App

 으로 바로 커맨드 상에서 실행한다.


매우 유용하다. 

 




Posted by yongary
,

JPA방식

Spring 2015. 8. 19. 23:35

REF-SITE 

 

Entity 어노테이션이 RDB테이블이 된다.


@Entity
public class Forum {
    @Id private Long id;
    @Column private String name;
    @Column private String description;
    @Column private Date createdAt;
 
// Omit Getters/Setters....
}


Posted by yongary
,

EL과 JSTL

Spring 2015. 8. 7. 14:48

참고사이트:  http://egloos.zum.com/slog2/v/3581446   https://docs.oracle.com/javaee/6/tutorial/doc/bnahq.html 

 

 

EL (expression language) -> JSP2부터 기본 지원

JSTL (JavaServer Pages Standard Tag Library ) -> c tag를 가장 많이 사용.

 

앞부분에 taglib 디렉티브로 사용함을 표시한다.

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>  // c:tag사용.

 

<EL>

${param.name} => request.getParameter("name");
${member} => request.getAttribute("member");

 

${member.name} => Member m = (Member)request.getAttribute("member");
m.getName();
${list["0"]} => List list = (List)request.getAttribute("list");
list.get(0);

 <JSTL>

<c:forEach items="${list}" var="listItem" >

<td>${listItem.title}</td>

</c:forEach> 

 

Posted by yongary
,

Maven run

Spring 2015. 1. 15. 10:07


pom.xml을 이용해서 직접 run하는 command:



컴파일 + 실행:


    mvn compile exec:java -Dexec.mainClass=com.mongodb.SparkHomework




?아래는 jetty 실행.

mvn clean jetty:run


Posted by yongary
,

redis를 HA로 구성했을 경우, SDR(spring-data-redis 1.4) 와 jedis커넥션을 이용한 spring과 redis 연동.


RedisSentinelConfiguration 클래스를 이용하면, HA를 지원하는 redis의 이중화 상태에서도 spring을 이용한 redis연동이 가능하다.

java코드로 연동하는 방법은 여러곳에서 나와있으므로, 본 글 에서는

xml을 이용한 DI(Dependency Injection)방식으로   spring과 HA redis를 연동하는 방식을 설명한다.



1. pom.xml 수정   (SDR , jedis를 추가)

이전글과 동일하다. 단 common-pool 대신에 이를 상속받은 JedisPoolConfig을 써봄으로 인해 common-pool은 제거.


<dependency>

<groupId>org.springframework.data</groupId>

<artifactId>spring-data-redis</artifactId>

<version>1.4.0.RELEASE</version>

</dependency>


<dependency>

<groupId>redis.clients</groupId>

<artifactId>jedis</artifactId>

<version>2.5.1</version>

<type>jar</type>

<scope>compile</scope>

</dependency>




2. application-config.xml 수정


2.1 네임스페이스에  xmlns:p,c, util 추가.


2.2.1 mymaster와 setntinels을 xml로 구성


2.2.2 RedisSentinelContiguration을 이용해서 HA구성.

         => SDR에 미흡한 부분이 하나 존재하여, MySentinelConfiguration  를 별도로 생성해서 이용하도록 함.

             (이유는 아래 xml의 코멘트 참조)   


2.2.3 jedis를 이용한 Pool과 connection구성.


이렇게만 하면 이전 예제와 동일하게 그냥 redisTemplate만을 이용해서 개발하면 자동으로 HA구성을 지원하는 개발이 된다.




<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:context="http://www.springframework.org/schema/context"

xmlns:p="http://www.springframework.org/schema/p"

xmlns:c="http://www.springframework.org/schema/c"

xmlns:util="http://www.springframework.org/schema/util"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd

http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">


<!-- Uncomment and add your base-package here:-->

<context:component-scan base-package="my"/>


<!-- myster -->

<bean id="myMaster" class= "org.springframework.data.redis.connection.RedisNode" c:host="127.0.0.1" c:port="6379" p:name="mymaster"/>


<!-- Sentinels -->

<bean id="mySent1" class= "org.springframework.data.redis.connection.RedisNode" c:host="127.0.0.1" c:port="26379"/>

<bean id="mySent2" class= "org.springframework.data.redis.connection.RedisNode" c:host="127.0.0.1" c:port="26381"/>

<bean id="mySents" class= "java.util.HashSet">

 <constructor-arg>

  <list>

   <ref bean="mySent1" />

   <ref bean="mySent2" />

  </list>

 </constructor-arg>

</bean>


<!-- RedisSentinelConfiguration: org.springframework.data.redis.connection.RedisSentinelConfiguration" 

2.2.2 이 부분이 유일하게 아직 SDR에서 미흡한 부분이다.  이 부분은 ReidsSentinelConfiguration class 가 

getter와 setter 파라미터가 다른 오류가 발생하므로, 자체 class를 하나 만들어서 해결하였다.

-->

<bean id="redisSentinelConf" class="my.MySentinelConfiguration"

p:master-ref="myMaster"

p:mySentinels-ref="mySents"

/>

<!-- p:sentinels-ref="mySents" : ERROR 발생-->



<!--2.2.3 POOL & Connection-->

<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"/>

<bean id="jedisConnFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"

    p:use-pool="true"

    p:poolConfig-ref="jedisPoolConfig"

    c:sentinelConfig-ref="redisSentinelConf"

/>

<!--p:host-name="127.0.0.1" p:port="6379" -->



<bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>

<!-- redis template definition -->

<bean id="redisTemplate"

class="org.springframework.data.redis.core.RedisTemplate"

p:connection-factory-ref="jedisConnFactory"

p:keySerializer-ref="stringRedisSerializer"

p:hashKeySerializer-ref="stringRedisSerializer"

p:valueSerializer-ref="stringRedisSerializer"/>

</beans>





3. JAVA  코드 - 유일하게 추가한 MySentinelConfiguration코드이다.  추가만 해 놓으면 된다.


- 단지, SDR의 getter와 setter의 오류를 피하기 위한 클래스이다. 향후에는 SDR에서 개선이 될 것으로 기대된다.


public class MySentinelConfiguration extends RedisSentinelConfiguration {

MySentinelConfiguration(){

super();

}


public Set<RedisNode> getMySentinels(){

Set<RedisNode> sets=super.getSentinels();

return sets;

}


public void setMySentinels( Set<RedisNode> sentinels){

super.setSentinels(sentinels);

}


}


Posted by yongary
,

spring과 redis연동

Spring 2014. 9. 18. 09:26

SDR(spring-data-redis) 와 jedis커넥션을 이용한 spring을 이용한 redis 연동.


spring에서 redis를 연결하기 위한 기본적인 방법을 커넥션 위주로 설명.

실제로는 redis에 저장할 데이타 class를 별도로 만들어 serialize기능을 이용해 {key,class}형태로 저장하는 방식이 바람직하지만, 여기서는 이 부분은 생략하고 기본적인 연결과정만 설명한다. 


1. pom.xml 수정   (SDR , common-pool,  jedis를 추가)


<dependency>

<groupId>org.springframework.data</groupId>

<artifactId>spring-data-redis</artifactId>

<version>1.4.0.RELEASE</version>

</dependency>

<dependency>

<groupId>commons-pool</groupId>

<artifactId>commons-pool</artifactId>

<version>1.6</version>

</dependency>

<dependency>

<groupId>org.apache.commons</groupId>

<artifactId>commons-pool2</artifactId>

<version>2.0</version>

</dependency>

<dependency>

<groupId>redis.clients</groupId>

<artifactId>jedis</artifactId>

<version>2.5.1</version>

<type>jar</type>

<scope>compile</scope>

</dependency>






2. application-config.xml 수정


2.1 네임스페이스에  xmlns:p 추가.

2.2  jedisConnnection, Serializer, redisTemplate 추가.


<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:context="http://www.springframework.org/schema/context"

xmlns:p="http://www.springframework.org/schema/p"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">


    <!-- Uncomment and add your base-package here:-->

    <context:component-scan base-package="my"/>


<bean id="jedisConnFactory"

    class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"

    p:use-pool="true" p:host-name="127.0.0.1" p:port="6379" />


<bean id="stringRedisSerializer"

    class="org.springframework.data.redis.serializer.StringRedisSerializer"/>


<!-- redis template definition -->

<bean id="redisTemplate"

class="org.springframework.data.redis.core.RedisTemplate"

p:connection-factory-ref="jedisConnFactory"

p:keySerializer-ref="stringRedisSerializer"

p:hashKeySerializer-ref="stringRedisSerializer"

p:valueSerializer-ref="stringRedisSerializer"/>


</beans>



  이 중에서 serializer는 추가하지 않아도 동작은 잘 되지만, 

 기본 serializer로 동작하게 되면 redis에 데이타가 들어갈 때, 앞 부분에 xac xed x00 x05t x00 등의 character가 몇개 들어가게 된다.

(이런 이상한 캐릭터들은 standard serializer에서 사용하는 class정보이다.)




3. JAVA Service 코드


 @Service

public class RedisService implements IRedisService{


@Autowired

private RedisTemplate<String,String> redisTemplate;


public Set<String> keysAll() {


//값을 넣고 싶을 땐, 이렇게..

//redisTemplate.opsForValue().set("abcKey", "valueABC");


return redisTemplate.keys("*");

}



}     


Posted by yongary
,

spring을 이용해서 mongoDB를 연동할 경우 방법은 다음과 같다.


1. pom.xml 수정 : spring-data-mongodb 추가


         <dependency>

       <groupId>org.springframework.data</groupId>

       <artifactId>spring-data-mongodb</artifactId>

       <version>1.5.1.RELEASE</version>

</dependency>

        

      참고: http://projects.spring.io/spring-data-mongodb/

      




2. application-config.xml 수정.   ( 주로 resources/spring/ 밑에 위치)


    2.1 네임스페이스 수정   :  xmlns:mongo 한 줄 및  xsi:schemaLocation 2줄 추가.

    2.2 mongo:db-factory 추가 및  mongoTemplate 추가



   <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:context="http://www.springframework.org/schema/context"

xmlns:mongo="http://www.springframework.org/schema/data/mongo"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd

http://www.springframework.org/schema/data/mongo

        http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd">

    

<!-- Uncomment and add your base-package here:-->

    <context:annotation-config /> 

    <context:component-scan base-package="my"/> 

   

    <mongo:mongo host="localhost" port="27017"/>

    <mongo:db-factory   dbname="kcdb"/>   


    <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">

 <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>

    </bean>  

</beans>





3. Vo(value object) 와 유사한   java파일 작성. ( @Document와  @Id를 포함하도록 한다. )

       

    @Document    //mongoDB에서 persistent한 도메인으로 인식하게 되는 어노테이션. 즉 테이블로 인식.

     public class User{


@Id       // mongoDB의 테이블(category)에서 데이타별 고유id로 자동생성 되는 id에 매핑하기 위함) 

private String id;


private String username;


//setters & getters ... 

}




4. Service에서 mongoTemplate를 이용한 query작성.

 

  @Service

  public class MongoService implements IMongoService{


@Autowired

private MongoTemplate mongoTemplate;

     

  public User getUser(String userName) {


Query query = new Query( where("username").is(userName) );

User user=mongoTemplate.findOne(query, User.class);

return user;

}


   }

Posted by yongary
,