if (anno instanceof RequestMapping) { // 모든 요청 방식 매핑
RequestMapping mapping = (RequestMapping) anno;
mappings = mapping.value();
} else if (anno instanceof GetMapping && method.equals("GET")) { // GET 방식 매핑
GetMapping mapping = (GetMapping) anno;
mappings = mapping.value();
} else if (anno instanceof PostMapping && method.equals("POST")) {
PostMapping mapping = (PostMapping) anno;
mappings = mapping.value();
} else if (anno instanceof PutMapping && method.equals("PUT")) {
PutMapping mapping = (PutMapping) anno;
mappings = mapping.value();
} else if (anno instanceof PatchMapping && method.equals("PATCH")) {
PatchMapping mapping = (PatchMapping) anno;
mappings = mapping.value();
} else if (anno instanceof DeleteMapping && method.equals("DELETE")) {
DeleteMapping mapping = (DeleteMapping) anno;
mappings = mapping.value();
}
예를들어 요청이
if (anno instanceof RequestMapping) { // 모든 요청 방식 매핑
RequestMapping mapping = (RequestMapping) anno;
mappings = mapping.value();
}
에 해당되는 요청이 들어왔다면
//에노테이션
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapping {
String[] value();
}
해당 에노테이션 배열에
(MemberController)
@Controller
@RequestMapping("/member")
@RequiredArgsConstructor
public class MemberController {
private final JoinService joinService;
@GetMapping("/{mode}/test/{num}")
public String join(@PathVariable("mode") String mode, @RequestParam("seq") int seq, RequestJoin form, HttpServletResponse response, @PathVariable("num") int num) {
System.out.printf("mode=%s, seq=%d, num=%d%n", mode, seq, num);
System.out.println(form);
joinService.process();
return "member/join";
}
}
[/member] 이 담기게된다.
package org.choongang.global.router;
import jakarta.servlet.http.HttpServletRequest;
import org.choongang.global.config.annotations.*;
import org.choongang.global.config.containers.BeanContainer;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Service
public class HandlerMappingImpl implements HandlerMapping{
private String controllerUrl;
@Override
public List<Object> search(HttpServletRequest request) {
List<Object> items = getControllers();
for (Object item : items) { // item = req
/* Type 애노테이션에서 체크 S */
// @RequestMapping, @GetMapping, @PostMapping, @PatchMapping, @PutMapping, @DeleteMapping
if (isMatch(request,item.getClass().getDeclaredAnnotations(), false, null)) {
// 메서드 체크
for (Method m : item.getClass().getDeclaredMethods()) {
if (isMatch(request, m.getDeclaredAnnotations(), true, controllerUrl)) {
return List.of(item, m); // req객체와 매칭되는 컨트롤러에 정의되어 있는 요청 메서드를 리스트로 리턴
}
}
}
/* Type 애노테이션에서 체크 E */
/**
* Method 애노테이션에서 체크 S
* - Type 애노테이션 주소 매핑이 되지 않은 경우, 메서드에서 패턴 체크
*/
for (Method m : item.getClass().getDeclaredMethods()) {
if (isMatch(request, m.getDeclaredAnnotations(), true, null)) {
return List.of(item, m);
}
}
/* Method 애노테이션에서 체크 E */
}
return null;
}
/**
*
* @param request
* @param annotations : 적용 애노테이션 목록
* @param isMethod : 메서드의 에노테이션 체크인지
* @param prefixUrl : 컨트롤러 체크인 경우 타입 애노테이션에서 적용된 경우
* @return
*/
private boolean isMatch(HttpServletRequest request, Annotation[] annotations, boolean isMethod, String prefixUrl) {
//에노테이션과 요청이 일치하는지 확인하기 위함.
String uri = request.getRequestURI();
String method = request.getMethod().toUpperCase(); //요청 방식 가져옴 GET,POST 등등
String[] mappings = null;
for (Annotation anno : annotations) {
if (anno instanceof RequestMapping) { // 모든 요청 방식 매핑
RequestMapping mapping = (RequestMapping) anno;
mappings = mapping.value();
} else if (anno instanceof GetMapping && method.equals("GET")) { // GET 방식 매핑
GetMapping mapping = (GetMapping) anno;
mappings = mapping.value();
} else if (anno instanceof PostMapping && method.equals("POST")) {
PostMapping mapping = (PostMapping) anno;
mappings = mapping.value();
} else if (anno instanceof PutMapping && method.equals("PUT")) {
PutMapping mapping = (PutMapping) anno;
mappings = mapping.value();
} else if (anno instanceof PatchMapping && method.equals("PATCH")) {
PatchMapping mapping = (PatchMapping) anno;
mappings = mapping.value();
} else if (anno instanceof DeleteMapping && method.equals("DELETE")) {
DeleteMapping mapping = (DeleteMapping) anno;
mappings = mapping.value();
}
if (mappings != null && mappings.length > 0) {
String matchUrl = null;
if (isMethod) {
String addUrl = prefixUrl == null ? "" : prefixUrl;
// 메서드인 경우 *와 {경로변수} 고려하여 처리
for(String mapping : mappings) {
String pattern = mapping.replace("/*", "/\\w*")
.replaceAll("/\\{\\w+\\}", "/(\\\\w*)");
Pattern p = Pattern.compile("^" + request.getContextPath() + addUrl + pattern + "$");
Matcher matcher = p.matcher(uri);
return matcher.find();
}
} else {
List<String> matches = Arrays.stream(mappings)
.filter(s -> uri.startsWith(request.getContextPath() + s)).toList();
if (!matches.isEmpty()) {
matchUrl = matches.get(0);
controllerUrl = matchUrl;
}
}
return matchUrl != null && !matchUrl.isBlank();
}
}
return false;
}
/**
* 모든 컨트롤러 조회
*
* @return
*/
private List<Object> getControllers() {
return BeanContainer.getInstance().getBeans().entrySet()
.stream()
.map(s -> s.getValue())
.filter(b -> Arrays.stream(b.getClass().getDeclaredAnnotations()).anyMatch(a -> a instanceof Controller || a instanceof RestController))
.toList();
}
}