public interface Oracle {
    String defineMeaningOfLife();
}
public class BookwormOracle implements Oracle{
    private Encyclopedias encyclopedias;

    public void setEncyclopedias(Encyclopedias encyclopedias) {
        this.encyclopedias = encyclopedias;
    }

    @Override
    public String defineMeaningOfLife() {
        return "Encyclopedias are a waste of money - go see the world instead";
    }
}

BookwormOracle.javainterface Oracle 을 구현했을 뿐만 아니라 의존성 주입을 위한 수정자도 정의했다.
구현 클래스 각각이 자신의 의존성을 각자 정의하고, 비즈니스 인터페이스에서는 비즈니스 메서드만 유지해야한다.

만약 인터페이스에 setEncyclopedias 같은 의존성 주입 메서드를 정의한다면, 해당 인터페이스의 모든 구현체가 encyclopedias 의존성을 사용하거나 최소한 인지하도록 강제하는 것. 유연성이 떨어진다.

'JAVA > SPRING' 카테고리의 다른 글

HTTP2로 요청을 보내보자  (0) 2020.01.29
ResourceLoader  (2) 2020.01.22
@PathVariable  (0) 2019.10.20
@RequestMapping의 value 패턴.  (0) 2019.10.19
[SPRING SECURITY] ignoring() - 필터에서 벗어나보자  (0) 2019.10.18

1020-스프링MVC-핸들러메소드-URI패턴

@GetMapping("/events/{id}")
public String getEvent(@PathVariable int id) {
...  
}
  • @GetMapping("/events/{id}")가 URI패턴이다.

핸들러

@GetMapping("/events/{id}")
    @ResponseBody
    public Event getEvent(@PathVariable Integer id) {
        Event event = new Event();
        event.setId(id);
        return event;
    }

클라이언트 역할하는 테스트코드.

    @Test
    public void getEvent() throws Exception {
        mockMvc.perform(get("/events/1"))
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(jsonPath("id").value(1));
    }
  • /events/1로 요청을 보내고있다. 당연히 문자열이다. 하지만 스프링에서는 자동 형변환해준다. (핸들러 메소드의 아규먼트를 볼 것.)
  • id값이 안들어오면 BadRequest 뜬다. 방지하려면 아규먼트타입에 required = false 집어넣어줄 것.
    • ex ) @PathVariable(required=false) Integer id
  • @RequestMapping("/hello")
    • hello 주소 요청만 매핑된다.
  • @RequestMapping("/hello?")
    • hello 뒤 한글자만 붙어야 매핑된다.
  • @RequestMapping("/hello/*")
    • hello 뒤 / 이후 하나의 뎁스만 매핑된다.
  • @RequestMapping("/hello/**")
    • hello 뒤 / 이후 여러개의 뎁스가 매핑된다.
  • @RequestMapping("/hello/[a-z]+")
    • hello 뒤 / 이후 정규표현식이 매핑된다.

SampleController.java


@Controller
@RequestMapping
public class SampleController {

    @RequestMapping(value = {"/hello", "/hi"})
    @ResponseBody
    public String hello() {
        return "hello";
    }

    @RequestMapping("/hello?")
    @ResponseBody
    public String helloMustBeBehindOneChar() {
        return "hello one char";
    }

    @RequestMapping("/hello/*")
    @ResponseBody
    public String helloMustBeBehindOneDepth() {
        return "hello one depth";
    }

    @RequestMapping("/hello/**")
    @ResponseBody
    public String helloMustBeBehindOverOneDepth() {
        return "hello over one depth";
    }

    @RequestMapping("/hello/{name:[a-z]+}")
    @ResponseBody
    public String helloPathVariableRegx(@PathVariable String name) {
        return "hello regx " + name;
    }
}

SampleControllerTest.java


@RunWith(SpringRunner.class)
@WebMvcTest
public class SampleControllerTest {

    @Autowired
    private MockMvc mockMvc;

    /**
     *
     * 리퀘스트 매핑의 주소는 @RequestMapping(value = {"/hello", "/hi"}) 다.
     */
    @Test
    public void helloTest() throws Exception {
        mockMvc.perform(get("/hello"))
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(content().string("hello"))
                .andExpect(handler().method(SampleController.class.getMethod("hello")));
    }

    /**
     *
     * 리퀘스트매핑의 주소는 @RequestMapping("/hello?") 다.
     */
    @Test
    public void helloMustBeBehindOneCharTest() throws Exception {
        mockMvc.perform(get("/helloa"))
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(content().string("hello one char"))
                .andExpect(handler().method(SampleController.class.getMethod("helloMustBeBehindOneChar")));
    }

    /**
     *
     * 컨트롤러의 @RequestMapping("/hello?") 는 hello 뒤 한 글자만 매핑된다.
     */
    @Test
    public void helloMustBeBehindOneCharTest_두글자이상_expect_not_found() throws Exception {
        mockMvc.perform(get("/helloaa"))
                .andDo(print())
                .andExpect(status().isNotFound());
    }


    /**
     *리퀘스트매핑의 주소는 @RequestMapping("/hello/*") 다.
     *
     */
    @Test
    public void helloMustBeBehindOneDepth() throws Exception {
        mockMvc.perform((get("/hello/1")))
                .andDo(print())
                .andExpect(handler().methodName("helloMustBeBehindOneDepth"));
    }

    /**
     *
     * 리퀘스트매핑의 주소는 @RequestMapping("/hello/**")다.
     */
    @Test
    public void helloMustBeBehindOverOneDepth() throws Exception {
        mockMvc.perform((get("/hello/1/2")))
                .andDo(print())
                .andExpect(handler().methodName("helloMustBeBehindOverOneDepth"));
    }

    /**
     *
     * 리퀘스트매핑의 주소는 @RequestMapping("/hello/{name:[a-z]+}") 다.
     * 정규표현식 사용한다.
     */
    @Test
    public void helloRegx() throws Exception {
        mockMvc.perform((get("/hello/eunmo")))
                .andDo(print())
                .andExpect(handler().methodName("helloPathVariableRegx"))
                .andExpect(content().string("hello regx eunmo"));
    }

}

1018 spring security

ignoring()

예를 들어 favicon 같은 스태틱한 리소스인 경우는 시큐리티 필터를 타게할 필요가 없다.

favicon을 보여주는데 무슨 인증이 필요하겠나?

하지만 별도의 설정이 없다면 favicon 요청마저 시큐리티 필터들을 타게되고, 그만큼의 자원이 낭비된다.

이런 경우 시큐리티필터를 안타게하려면 어떻게 해야할까?

SecurityConfig.java

@Override
public void configure(WebSecurity web) throws Exception {
  web.ignoring().mvcMatchers("/favicon.ico")
}

부트 쓸 경우

SecurityConfig.java

@Override
public void configure(WebSecurity web) throws Exception {
  web.ignoring().requestMatchers(PathRequest.toStaticResource().atCommonLocations());
}

이외에도 다양한 메소드들이 있으니 살펴볼 것.

ignoring() 적용 전


파비콘이 필터를 타는 것을 볼 수 있다.

ignoring() 적용 후


파비콘이 필터를 타지 않는 것을 볼 수 있다.

'JAVA > SPRING' 카테고리의 다른 글

@PathVariable  (0) 2019.10.20
@RequestMapping의 value 패턴.  (0) 2019.10.19
[SPRING MVC] Formatter  (2) 2019.10.14
[SPRING SECURITY] 1012 공부(아키텍쳐 마지막 정리.)  (2) 2019.10.12
[SPRING SECURITY] 1011 공부(SecurityContextHolder)  (0) 2019.10.12

+ Recent posts