๋
ธ์
๋งํฌ
๊นํ๋ธ ํ์ตํ
์คํธ
Annotation
) ์ด๋?์ฝ๋ ์ฌ์ด์ ์ฃผ์์ฒ๋ผ ์ฐ์ด๋ฉฐ ํน๋ณํ ์๋ฏธ, ๊ธฐ๋ฅ์ ์ํํ๋๋ก ํ๋ ๊ธฐ์ ์ด๋ค.
meta data
๋ผ๊ณ ๋ณผ ์ ์๋ค.meta data
ย : ๋ฐ์ดํฐ๋ฅผ ์ํ ๋ฐ์ดํฐ์ด๋
ธํ
์ด์
์ฌ์ฉ ์์์ด๋
ธํ
์ด์
์ ์
@Target({ElementType.[์ ์ฉ๋์-ํจํค์ง, ์์ฑ์, ๋ฉ์๋, ํ๋...]})
// ElementType.TYPE ์ ํด๋์ค,์ธํฐํ์ด์ค,์ด๊ฑฐํ์
์ ์ด๋
ธํ
์ด์
์ ๋ถ์ผ ์ ์๋ค๋ ์๋ฏธ
@Retention(RetentionPolicy.[์ ๋ณด ์ ์ง๋๋ ๋์-์์ค, ๋ฐํ์(๋ณดํต ๋ฐํ์)...])
public @interface [์ด๋
ธํ
์ด์
๋ช
]{
public ํ์
elementName() [default ๊ฐ]
...
}
ํด๋์ค
์ ์ด๋
ธํ
์ด์
์ ๋ฐฐ์น
์ฝ๋๊ฐ ์คํ๋๋ ์ค์ Reflection
์ ์ด์ฉํ์ฌ ์ถ๊ฐ์ ๋ณด๋ฅผ ํ๋ํ์ฌ ๊ธฐ๋ฅ ์ค์
@Controller
, @RestController
@Controller
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
@AliasFor(annotation = Component.class)
String value() default "";
}
@Component
ํด๋์ค์ ํน์ํ@Component
)๋ฅผ ์๋ ๊ฐ์ง(auto-detection)@RequestMapping
์ ํจ๊ป ์@RestController
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody // ์ด๊ฑฐ ํ๋ ๋นผ๊ณค Controller์ ๋์ผ
public @interface RestController {
@AliasFor(annotation = Controller.class)
String value() default "";
}
@Controller
+ @ResponseBody
๊ฒฐํฉ@ResponseBody
annotation
์ ์ธ ํ์๊ฐ ์์ด์ง!@RequestMapping
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
String name() default "";
@AliasFor("path")//๋ณ์นญ ์ ์ธ
String[] value() default {}
@AliasFor("value")
String[] path() default {};
RequestMethod[] method() default {};
String[] params() default {};
String[] headers() default {};
String[] consumes() default {};
String[] produces() default {};
}
//...
@RestController
@RequestMapping(value = "/api", headers = "Accept=application/json", method = GET)
// == @GetMapping(value = "/api", headers = "Accept=application/json")
public class PathController {...}
@PostMapping(value = "/users", consumes = APPLICATION_JSON_VALUE)
@GetMapping
: ํด๋ผ์ด์ธํธ๊ฐ ์๋ฒ์ ๋ฆฌ์์ค๋ฅผ ์์ฒญํ ๋ ์ฌ์ฉ@PostMapping
: ํด๋ผ์ด์ธํธ๊ฐ ์๋ฒ์ ๋ฆฌ์์ค๋ฅผ ์์ ๋๋ ์์ฑํ ๋ ์ฌ์ฉvalue
: ํจ์ค ์ฃผ์path
: ํจ์ค ์ฃผ์ (@GetMapping(path = "/api")
== @GetMapping("/api")
)params
, headers
:ย ๋งคํํ ํ๋ผ๋ฏธํฐ/ ํค๋ ์์ฑ ์ง์ consumes
: ์์ฒญ ๋ฐ์ดํฐ ํ์! HTTP ์์ฒญ์ Content-Type
ํค๋์ ๋์produces
: ์๋ต ๋ฐ์ดํฐ ํ์! HTTP ์์ฒญ์ Accept
ํค๋์ ๋์@ModelAttribute
, @RequestBody
,@RequestParam
, @PathVariable
@ModelAttribute
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ModelAttribute {
@AliasFor("name")
String value() default "";
@AliasFor("value")
String name() default "";
boolean binding() default true;
}
//...
//์์ฒญ : http://localhost:8080/api/1
@GetMapping
public ResponseEntity<PathResponse> showPaths(@ModelAttribute PathsRequest pathsRequest) {
return ResponseEntity
.ok(pathService.showPaths(pathsRequest));
}
ํ๋ผ๋ฏธํฐ
๋ฅผ JAVA ๊ฐ์ฒด๋ก ๋ฐ์ธ๋ฉ์ฟผ๋ฆฌ(์คํธ๋ง)/ํผ(ํ๋ผ๋ฏธํฐ)
โ DTO
@RequestBody
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestBody {
boolean required() default true;
}
//...
// ์์ฒญ : ๋ฐ๋๊ฐ
@PostMapping
public ResponseEntity<LineResponse> createLine(@RequestBody LineRequest lineRequest) {
return ResponseEntity
.created(URI.create("/lines"))
.body(lineService.create(lineRequest));
}
JSON
ํํ์ body
๋ฅผ JAVA ๊ฐ์ฒด๋ก ๋งคํjson ๋ฐ๋
โ DTO
/์ด์ธ ๊ฐ์ฒด(Stringโฆ)GetMapping
๋ถ๊ฐ(๋ฐ๋ ์์)๊ธฐ๋ณธ ์์ฑ์
ํ์ : ์ง๋ ฌํgetter
๋ setter
์ค 1๊ฐ์ง๋ ์ ์ : ๋ฐ์ดํฐ๋ฐ์ธ๋ฉ ์ฉ ํ๋๋ช
์ ์์๋ด๊ธฐ ์ํดGET ๋งคํ
: DTO
์ setter
๊ฐ ํ์POST ๋งคํ
: DTO
์ ์์ฑ์
ํ์ (setter
๋ ํ์ X)@RequestParam
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
@AliasFor("name")
String value() default "";
@AliasFor("value")
String name() default "";
boolean required() default true;
String defaultValue() default ValueConstants.DEFAULT_NONE;
}
//...
// ์์ฒญ : http://localhost:8080/api?stationId=1
@DeleteMapping("/sections")
public void deleteSection(@RequestParam long stationId) {
lineService.deleteSection(lineId, stationId);
}
ํ๋ผ๋ฏธํฐ
๊ฐ์ ๊ทธ๋๋ก ๊ฐ์ ธ์ดController
์ ํ๋ผ๋ฏธํฐ๋ฅผ 1:1 ๋งคํrequired
: ๋ฐ๋์ ํ์ํ ๋ณ์์ธ์ง ์ฌ๋ถdefaultValue
: ํด๋น ํ๋ผ๋ฏธํฐ๊ฐ ์์ ์ ๋ํดํธ ๊ฐ@PathVariable
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PathVariable
@AliasFor("name")
String value() default "";
@AliasFor("value")
String name() default "";
boolean required() default true;
//...
@DeleteMapping("/{id}")
public void deleteLineById(@PathVariable long id) {
lineService.removeLineById(id);
}
required
: ๋ฐ๋์ ํ์ํ ๋ณ์์ธ์ง ์ฌ๋ถResponseEntity
@ResponseBody
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResponseBody {}
//...
@ResponseBody
@ResponseStatus(HttpStatus.OK)
public MoveResponseDto move(@RequestBody MoveDto moveDto) {
return moveResponseDto;
}
Annotation
@RestController
๊ฐ ๋ถ์ผ๋ฉดย `@ResponseBody` ์๋ตResponseEntity
public class ResponseEntity extends HttpEntity {
private final Object status;
}
//...
@GetMapping
public ResponseEntity<PathResponse> showPaths(...) {
return ResponseEntity.ok()
.headers(...)
.body(...);
}
๊ฐ์ฒด
๋ก ๋ง๋ค์ด์ ๋ฐํStatus
,ย Header
,ย Body
๋ฅผ ์ง์ Builder
ํจํด์ ํ์ฉ@ResponseStatus
@ResponseStatus(HttpStatus.BAD_REQUEST, reason = "Some parameters are invalid")
HttpStatus
์ reason
์ค์ 404 NOT FOUND
, 200 OK
โฆ@ExceptionHandler
, @ControllerAdvice
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExceptionHandler {
Class<? extends Throwable>[] value() default {};
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
@AliasFor("basePackages")
String[] value() default {};
}
//...
@ControllerAdvice
public class SubwayAdvice
@ExceptionHandler(BadRequestException.class)
public ResponseEntity<ErrorResponse> badRequestExceptionHandler(BadRequestException e) {
return ResponseEntity.badRequest()
.body(e.getMessage());
}
}
@ExceptionHandler
๋ฉ์๋
๋จ์ ๋ถ์IllegalArgumentException.class
๋ฑ)๋ฅผ ์บ์นํ์ฌ ์ฒ๋ฆฌํ๋ค.@ControllerAdvice
ํด๋์ค
๋จ์ ๋ถ์Advice
ํด๋์ค์์ ์บ์นAdvice
ํด๋์ค ์ ๋ฉ์๋ ์๋จ์ @ExceptionHandler(์์ธํด๋์ค๋ช
.class)
๋ฅผ ๋ถ์ฌ์ ๊ธฐ์ @ExceptionHandler
@ControllerAdvice
์ @ExceptionHandler
๋ฉ์๋
๋ถํฐ ์์๋๋ก ์คํ@Repository
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Repository {
@AliasFor(annotation = Component.class)
String value() default "";
}
@Component
ํด๋์ค์ ํน์ํNamedParameterJdbcTemplate
JdbcTemplate
โ ๊ฐ๋
์ฑ ๋ฎ์NamedParameterJdbcTemplate
: ?
๋์ :๋ณ์๋ช
์ ์ด์ฉํ์ฌ ์ฒ๋ฆฌ โ ์์ ์๊ด์์ด์งqueryForObject()
public Long findIdByUserName(final String username) {
final String sql = "SELECT id FROM customer WHERE username = :username";
return namedParameterJdbcTemplate.queryForObject(sql, Map.of("username", username), Long.class);
}
queryForObject(SQL์ฟผ๋ฆฌ, ๋งคํ๋ ํ๋ผ๋ฏธํฐ, ๋ฆฌํด๋ ํด๋์ค(๋ก์ฐ๋งคํผ))
๋งคํ๋ ํ๋ผ๋ฏธํฐ
: Map<String, Object>
ํํquery()
public List<Long> findIdsByCountry(final String country) {
final String sql = "SELECT id FROM customer WHERE country = :country";
return namedParameterJdbcTemplate.query(sql, Map.of("country", country), Long.class);
}
query(SQL์ฟผ๋ฆฌ, ๋งคํ๋ ํ๋ผ๋ฏธํฐ, ๋ฆฌํด๋ ํด๋์ค(๋ก์ฐ๋งคํผ))
๋งคํ๋ ํ๋ผ๋ฏธํฐ
: Map<String, Object>
ํํupdate()
public void updatePassword(final Long id, final String oldPassword, final String newPassword) {
String query = "update customer set password = :newPassword"
+ " where id = :id and password = :oldPassword";
namedParameterJdbcTemplate.update(query,
Map.of("id", id, "newPassword", newPassword, "oldPassword", oldPassword)
);
}
update(SQL์ฟผ๋ฆฌ, ๋งคํ๋ ํ๋ผ๋ฏธํฐ)
batchUpdate()
public int[] deleteByIds(final List<Long> ids) {
final String query = "DELETE FROM cart_item WHERE id = :id";
List<Map<String, Long>> updateMaps = ids.stream()
.map(id -> Map.of("id", id))
.collect(Collectors.toList());
SqlParameterSource[] batchArgs = SqlParameterSourceUtils.createBatch(updateMaps);
return jdbcTemplate.batchUpdate(query, batchArgs);
}
batchUpdate(SQL์ฟผ๋ฆฌ, ๋งคํ๋ ํ๋ผ๋ฏธํฐ ๋ฆฌ์คํธ)
๋งคํ๋ ํ๋ผ๋ฏธํฐ
๋ฆฌ์คํธ : SqlParameterSource[]
ํํSqlParameterSourceUtils.createBatch()
๋ฅผ ํตํด ์์ฑGeneratedKeyHolder
public Long create(final Long customerId, final Long productId) {
final String query = "INSERT INTO cart_item(customer_id, product_id, quantity) VALUES (:customer_id, :product_id, :quantity)";
Map<String, Object> params = new HashMap<>();
params.put("customer_id", customerId);
params.put("product_id", productId);
params.put("quantity", 1);
SqlParameterSource source = new MapSqlParameterSource(params);
final KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(query, source, keyHolder);
return keyHolder.getKey().longValue();
}
auto increment
์ ์ํด ์์ฑ๋ id
๋ฅผ ๋ฐํํ ์ ์๋๋ก ํจROW_MAPPER
RowMapper<User> ROW_MAPPER = (resultSet, rowNum) -> new User(
resultSet.getString("name"),
resultSet.getString("description")
));
RowMapper<GuestBook> rowMapper = BeanPropertyMapper.newInstance(GuestBook.class);
//๊ฒ์ํ์ ๊ฒ์๊ธ์ ์ญ์ ํ๋ ๋ฉ์๋
@Transactional
public void removeBoard(Long id) throws Exception {
replyDAO.removeAll(id); //์ญ์ ํ ๊ฒ์๊ธ์ ๋ต๊ธ ์ญ์
boardDAO.deleteBoard(id); //๊ฒ์๊ธ ์ญ์
}
DB
ํธ๋์ญ์
์ ์ค์ ํ๊ณ ์ถ์ ํด๋์ค
๋ ๋ฉ์๋
์ ์ ์ฉ@Transactional
์ ์ธ์ด ์ฐ์ ์ ์ฉ!method
๋ด๋ถ์์ ์ผ์ด๋๋ DB ๋ก์ง์ดย ์ ๋ถ ์ฑ๊ณตํ๊ฑฐ๋, DB ์ ๊ทผ์ค ํ๋๋ผ๋ ์คํจํ๋ฉด ์ ์ฒด ๋กค๋ฐฑDB
๋ฐ์ดํฐ๋ฅผ ๋ฑ๋ก/์์ /์ญ์ ํ๋ Service
๋ฉ์๋๋ @Transactional
๋ฅผ ํ์์ ์ผ๋ก ๊ฐ์ ธ๊ฐ๋ค.@Transaction(readOnly=true, rollbackFor=Exception.class)
readOnly
: ์ฝ๊ธฐ ์ ์ฉrollbackFor
: ํด๋น Exception
์ด ์๊ธฐ๋ฉด ๋กค๋ฐฑ์ด๋
ธํ
์ด์
๋ถ์ฌ๋ ๋กค๋ฐฑ ์๋จ!WebEnvironment
์ย RANDOM_PORT
,ย DEFINED_PORT
DB
์ id
(Auto Increment
ย ์ต์
์ฌ์ฉ ์)@Transaction
์ ์ฉ๋จ!@JdbcTest
[10๋ถ ํ ์ฝํก] ์ค์ฐ, ์ผํธ์ DI์ IoC
@Service
public class LineService {
private final LineRepository repository;
//์๋์ผ๋ก DI(์์ฑ์ ์ฃผ์
)๋จ!!
public LineService(LineRepository repository) {
this.repository = repository;
}
}
IoC
์์น์ด๋?DIP
(Dependency Inversion Principle, ์์กด์ฑ ์ญ์ ์์น) ์์น๊ณผ ํจ๊ป ์ฌ์ฉ๋๊ธธ ๊ถ์ฅ๋จDI
๋?(Dependency Injection)DI
์ ์ธ ๊ฐ์ง ๋ฐฉ์์์ฑ์
์ฃผ์
DI Container
์ ๋ ์์กดfinal
๋ก ์ ์ธโ ๋ถ๋ณ ๊ฐ์ฒดsetter
์ฃผ์
ํ๋
์ฃผ์
(@Autowired
)@Bean
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component //@Configuration์ @Component์ ํฌํจํ๋ค!!!
public @interface Configuration {...}
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {...}
๋ฉ์๋
๋ฆฌํด ๊ฐ์ฒด์ Bean
์ผ๋ก ๋ฑ๋ก@Configuration
์ ํด๋์ค
์ ๋ถ์ธ ํ ์ฌ์ฉ!Bean
์ผ๋ก ๋ง๋ค๋ คํ ๋ ์ฌ์ฉObjectMapper Class
์ @Component
๋ฅผ ์ ์ธํ ์๋ ์์ผ๋ObjectMapper
์ ์ธ์คํด์ค
๋ฅผ ์์ฑํ๋ ๋ฉ์๋
๋ฅผ ๋ง๋ค๊ณ ๋ฉ์๋
์ @Bean
์ ์ ์ธํ์ฌ Bean
์ผ๋ก ๋ฑ๋กํ๋ค.@Component
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {...}
ํด๋์ค
๊ฐ์ฒด๋ฅผ Bean
์ผ๋ก ๋ฑ๋ก@ComponentScan
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {...}
@Component, @Service, @Repository, @Controller, @Configuration
์ด ๋ถ์ ๋น๋ค์ ์ฐพ์์ Context
์ ๋ฑ๋ก@Bean
๋์ @Controller
, @Service
, @Repository
๋ฑ์ ์ฌ์ฉํ๋ ์ด์ @Repository
์์๋ unchecked exception
๋ค์ ์คํ๋ง์ DataAccessException
์ผ๋ก ์ฒ๋ฆฌโฆ์ฝ๋
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
//------์ค์------
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)
})
//---------------
public @interface SpringBootApplication {
...
}
[10แแ
ฎแซ ํ
์ฝํก] ๐ฆแ
แ
ฅแแ
ฅแแ
ฅแจแแ
ด Springboot autoConfiguration : ๋งํฌ
@SpringBootApplication
ย ์ 3๊ฐ์ง ์ด๋
ธํ
์ด์
@SpringBootConfiguration
@Configuration
๊ณผ ๊ฐ์ ๊ธฐ๋ฅ. bean
์ ๋ง๋ค์ด์ค
@EnableAutoConfiguration
์์ ์ฌ์ง
์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ spring.factories
ย ์ Configuration
๋ค(๋ฆฌ์์ค ์์ ์ฐ๋ฆฌ๊ฐ ๋ฑ๋กํด๋ ๋น๋ค ํฌํจ)์ ์๋ ๋ฑ๋ก
AutoConfiguration
์ ๋ฑ๋ก ์กฐ๊ฑด์ ๋ง์กฑํ๋ ๊ฒฝ์ฐ์๋ง ๋ฑ๋ก!-debug
ย ์ต์
์ผ๋ก jar
ํ์ผ์ ์คํ : ์กฐ๊ฑด ๋ง์กฑ ์ฌ๋ถ, Bean
๋ฑ๋ก๋ฆฌ์คํธ ํ์ธ
IntelliJ
์์๋ ๋ณ๋์ ์ค์ ์์ด Actuator
์ ๊ธฐ๋ฅ์ ์ ๊ณต โ ๋ฑ๋ก๋ Bean
ํ์ธ
@ComponentScan
(base-package
๊ฐ ์ ์๋์ง ์์ผ๋ฉด)
ํด๋น ์ด๋
ธํ
์ด์
์ด ๋ถ์ classpath
ํ์์ย @Component
ย ๋ค์ ์ค์บ, Bean
์ผ๋ก ๋ฑ๋ก
AOP
Interceptor
๋ ์ผ์ข
์ AOP
?->๋ ์์๋ณด๊ธฐ@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(createTokenInterceptor())
.addPathPatterns("/auth/**");
}
}
//...
public class TokenInterceptor implements AsyncHandlerInterceptor {
private final JwtTokenProvider jwtTokenProvider;
public TokenInterceptor(final JwtTokenProvider jwtTokenProvider) {
this.jwtTokenProvider = jwtTokenProvider;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String accessToken = AuthorizationExtractor.extract(request);
if (!jwtTokenProvider.validateToken(accessToken)) {
throw new AuthorizationException("ํ ํฐ์ด ์ ํจํ์ง ์์ต๋๋ค.");
}
return true;
}
}
ํธ๋ค๋ฌ
์ ์คํ์ ๊ฐ๋ก์ฑ๋คpreHandle
: ์ปจํธ๋กค๋ฌ ํธ์ถ ์ ์คํ / ๋ฆฌํด๊ฐ์ด false์ผ ์ ์์
์ค๋จpostHandle
: ์ปจํธ๋กค๋ฌ ์คํ ํ ํธ์ถ/ view ์์ฑ ์ afterCompletion
: ์ต์ข
view ์คํ ํ ์คํ๋จ//1. ์ค์ ํด๋์ค์์ ArgumentResolver ์ถ๊ฐ ๊ตฌํ(WebMvcConfigurer) ํ์ฉ
@Configuration
public class AuthenticationPrincipalConfig implements WebMvcConfigurer {
@Override
public void addArgumentResolvers(List argumentResolvers) {
argumentResolvers.add(createAuthenticationPrincipalArgumentResolver());
}
@Bean
public AuthenticationPrincipalArgumentResolver createAuthenticationPrincipalArgumentResolver() {
return new AuthenticationPrincipalArgumentResolver(jwtTokenProvider);
}
}
//2. ๋งคํํ ๋ฉ์๋ ์ธ์์ ๋ถ์ผ ์ด๋
ธํ
์ด์
๋ง๋ค๊ธฐ
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthenticationPrincipal {
}
//3. ํด๋์ค ์์์ resolveArgument๋ฉ์๋๋ก ๊ฐ์ฒด ๋งคํ
public class AuthenticationPrincipalArgumentResolver implements HandlerMethodArgumentResolver {
private final JwtTokenProvider jwtTokenProvider;
public AuthenticationPrincipalArgumentResolver(final JwtTokenProvider jwtTokenProvider) {
this.jwtTokenProvider = jwtTokenProvider;
}
@Override
//๋งคํ์ ์ํด ์ฌ์ฉํ ํด๋์ค ์
๋ ฅ
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(AuthenticationPrincipal.class);
}
@Override
//๊ฐ์ฒด ๋งคํ
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) {
HttpServletRequest httpServletRequest = (HttpServletRequest) webRequest.getNativeRequest();
String payload = jwtTokenProvider.getPayload(AuthorizationExtractor.extract(httpServletRequest));
return new TokenRequest(Long.parseLong(payload));
}
}
HandlerMethodArgumentResolver
์ธํฐํ์ด์คsupportsParameter
: ๋ฆฌํ์คํธ ๋ฉ์๋์ ์ธ์์ ์ํ๋ ์ด๋
ธํ
์ด์
์ด ๋ถ์ด์๋์ง ํ์ธ(๊ทธ๋๋ก ์ฌ์ฉ)resolveArgument
: ํน์ ์ด๋
ธํ
์ด์
์ด ๋ถ์ด์๋ ๋ฉ์๋์ parameter๋ฅผ ์ํ๋ ํํ๋ก ์ ๋ณด๋ฅผ ๋ฐ์ธ๋ฉํ์ฌ ๋ฐํsessionLogin
โtokenLogin
โI love reading useful information, thank you for sharing, i always love this and moto x3m
Wow, that's a lot of technical information you have shared. Why don't you hire blog writer services uk and ask them to create a blog on your behalf which can be easily understandable by everyone Plus their services are also very affordable So do try them out
Your posting was really beneficial to me, and I look forward to reading more of your work in the future. You can join me in playing the amazing game smash karts if you have the time as well.