当前位置:   article > 正文

Spring Boot第3部分:依赖注入和@RestController

通过resourced 注入@restcontroller

Spring Boot第3部分:依赖注入和@RestController

介绍

本系列文章将研究Spring Boot的功能。 第三篇文章通过演示Spring Dependency Injection的基础知识来构建该系列文章。 为了创建可演示的代码,该示例还创建了@RestController实现,这是一个简单的共享属性服务器,客户端可以在其中放置和获取属性值。

Github上提供了该系列以及本部分的完整源代码。

@ComponentScan和依赖注入

这不是详尽的描述,仅描述了Spring依赖项注入的最简单(但可以说是最常见)的功能。

Spring Boot进程从Launcher::main方法(与本系列的第1部分和第2部分描述的实现保持不变)开始,并构造 SpringApplication并调用其run方法。 使用@SpringBootApplication注释类等同于使用@Configuration @EnableAutoConfiguration@ComponentScan @EnableAutoConfiguration@ComponentScan注释。

  1. @SpringBootApplication
  2. @NoArgsConstructor @ToString @Log4j2
  3. public class Launcher {
  4. public static void main ( String [] argv ) throws Exception {
  5. SpringApplication application = new SpringApplication ( Launcher . class );
  6. application . run ( argv );
  7. }
  8. }

SpringApplicationapplication.Launcher类开始分析。 @EnableAutoConfiguration指示Spring Boot应该在必要时尝试“猜测”。 @ComponentScan批注指示Spring Boot应该开始在application包(包含Launcher包)中扫描用@Component批注的@Component 。 注意:用@Component注释的注释类型也是组件。 例如, @Configuration@Controller@RestController都是@Component S,而不是相反。

对于每个用@Component注释的@Component ,Spring:

  1. 实例化一个实例,

  2. 对于每个带@Value注释的实例字段,请评估SpEL表达式1并使用结果初始化该字段,

  3. 对于@Configuration类中每个以@Bean注释的方法,请只调用一次该方法以获得Bean值,然后,

  4. 对于每个用@Autowired注释的字段,分配通过评估@Bean方法获得的相应值。

同样,以上内容是一个过分的简化,并非详尽无遗,它依赖于挥手,但应该足以上手。

本文的示例代码不需要@Value注入,但是上一篇文章在其MysqldConfiguration实现中提供了示例:

  1. @Value ( "${mysqld.home}" )
  2. private File home ;
  3. @Value ( "${mysqld.defaults.file:${mysqld.home}/my.cnf}" )
  4. private File defaults ;
  5. @Value ( "${mysqld.datadir:${mysqld.home}/data}" )
  6. private File datadir ;
  7. @Value ( "${mysqld.port}" )
  8. private Integer port ;
  9. @Value ( "${mysqld.socket:${mysqld.home}/socket}" )
  10. private File socket ;
  11. @Value ( "${logging.path}/mysqld.log" )
  12. private File console ;

上面的代码利用了在SpEL表达式中指定默认值和自动类型转换的优势。

在此实现的简单属性服务器在DictionaryConfiguration中创建一个“字典” bean:

  1. @Configuration
  2. @NoArgsConstructor @ToString @Log4j2
  3. public class DictionaryConfiguration {
  4. @Bean
  5. public Map < String , String > dictionary () {
  6. return new ConcurrentSkipListMap <>();
  7. }
  8. }

并将该bean连接到DictionaryRestController ,如下所示:

  1. @RestController
  2. ...
  3. @NoArgsConstructor @ToString @Log4j2
  4. public class DictionaryRestController {
  5. @Autowired private Map < String , String > dictionary = null ;
  6. ...
  7. }

下一节描述@RestController的实现。

@RestController实现

@RestController实现的@RestController提供以下Web API:

方法 URI 查询参数 退货
GET http://localhost:8080/dictionary/get key关联的值(可以为null
GET 2 http://localhost:8080/dictionary/put = key关联的先前值(可以为null
GET http://localhost:8080/dictionary/remove 先前与key关联的值(可以为null
GET http://localhost:8080/dictionary/size 没有 整型
GET http://localhost:8080/dictionary/entrySet 没有 键值对数组
GET http://localhost:8080/dictionary/keySet 没有 键值数组

DictionaryRestController@RestController@RequestMapping注释,其value = { "/dictionary" }指示请求路径将以/dictionary前缀,并produces = "application/json"指示HTTP响应应以JSON编码。

  1. @RestController
  2. @RequestMapping ( value = { "/dictionary" }, produces = MediaType . APPLICATION_JSON_VALUE )
  3. @NoArgsConstructor @ToString @Log4j2
  4. public class DictionaryRestController {
  5. @Autowired private Map < String , String > dictionary = null ;
  6. ...
  7. }

如上一节所述,字典映射为@Autowired

/dictionary/put方法的实现是:

  1. @RequestMapping ( method = { RequestMethod . GET }, value = { "/put" })
  2. public Optional < String > put ( @RequestParam Map < String , String > parameters ) {
  3. if ( parameters . size () != 1 ) {
  4. throw new IllegalArgumentException ();
  5. }
  6. Map . Entry < String , String > entry =
  7. parameters . entrySet (). iterator (). next ();
  8. String result = dictionary . put ( entry . getKey (), entry . getValue ());
  9. return Optional . ofNullable ( result );
  10. }

Spring将在方法调用中将请求的查询参数作为parameters注入。 该方法验证是否恰好指定了一个查询参数,将该键值放入字典中,然后返回结果(映射中该键的先前值)。 Spring将String解释为文字JSON因此该方法将结果包装在Optional以强制Spring编码为JSON

/dictionary/get方法的实现是:

  1. @RequestMapping ( method = { RequestMethod . GET }, value = { "/get" })
  2. public Optional < String > get ( @RequestParam Map < String , String > parameters ) {
  3. if ( parameters . size () != 1 ) {
  4. throw new IllegalArgumentException ();
  5. }
  6. Map . Entry < String , String > entry =
  7. parameters . entrySet (). iterator (). next ();
  8. String result = dictionary . get ( entry . getKey ());
  9. return Optional . ofNullable ( result );
  10. }

同样,必须完全有一个查询参数,并将结果包装在Optional/dictionary/remove请求的实现几乎相同。

/dictionary/size方法的实现是:

  1. @RequestMapping ( method = { RequestMethod . GET }, value = { "/size" })
  2. public int size ( @RequestParam Map < String , String > parameters ) {
  3. if (! parameters . isEmpty ()) {
  4. throw new IllegalArgumentException ();
  5. }
  6. return dictionary . size ();
  7. }

不应指定查询参数。 /dictionary/entrySet的实现与Set<Map.Entry<String,String>>的方法返回类型几乎相同:

  1. @RequestMapping ( method = { RequestMethod . GET }, value = { "/entrySet" })
  2. public Set < Map . Entry < String , String >> entrySet ( @RequestParam Map < String , String > parameters ) {
  3. if (! parameters . isEmpty ()) {
  4. throw new IllegalArgumentException ();
  5. }
  6. return dictionary . entrySet ();
  7. }

/dictionary/keySet的实现遵循相同的模式。

Maven项目POM提供了本系列第一篇文章中描述的spring-boot:run配置文件,并且服务器可以通过mvn -B -Pspring-boot:run 。 使用此配置文件启动后 ,即可使用Spring Boot执行器@RestServer处理程序映射可以通过以下查询进行验证:

  1. $ curl -X GET http://localhost:8081/actuator/mappings \
  2. > | jq '.contexts.application.mappings.dispatcherServlets[][]
  3. | {handler: .handler, predicate: .predicate}'
  4. {
  5. "handler" : "application.DictionaryRestController#remove(Map)" ,
  6. "predicate" : "{GET /dictionary/remove, produces [application/json]}"
  7. }
  8. {
  9. "handler" : "application.DictionaryRestController#get(Map)" ,
  10. "predicate" : "{GET /dictionary/get, produces [application/json]}"
  11. }
  12. {
  13. "handler" : "application.DictionaryRestController#put(Map)" ,
  14. "predicate" : "{GET /dictionary/put, produces [application/json]}"
  15. }
  16. {
  17. "handler" : "application.DictionaryRestController#size(Map)" ,
  18. "predicate" : "{GET /dictionary/size, produces [application/json]}"
  19. }
  20. {
  21. "handler" : "application.DictionaryRestController#entrySet(Map)" ,
  22. "predicate" : "{GET /dictionary/entrySet, produces [application/json]}"
  23. }
  24. {
  25. "handler" : "application.DictionaryRestController#keySet(Map)" ,
  26. "predicate" : "{GET /dictionary/keySet, produces [application/json]}"
  27. }
  28. {
  29. "handler" : "org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#errorHtml(HttpServletRequest, HttpServletResponse)" ,
  30. "predicate" : "{ /error, produces [text/html]}"
  31. }
  32. {
  33. "handler" : "org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#error(HttpServletRequest)" ,
  34. "predicate" : "{ /error}"
  35. }
  36. {
  37. "handler" : "ResourceHttpRequestHandler [ \" classpath:/META-INF/resources/webjars/ \" ]" ,
  38. "predicate" : "/webjars/**"
  39. }
  40. {
  41. "handler" : "ResourceHttpRequestHandler [ \" classpath:/META-INF/resources/ \" , \" classpath:/resources/ \" , \" classpath:/static/ \" , \" classpath:/public/ \" , \" / \" ]" ,
  42. "predicate" : "/**"
  43. }

使用curl验证put操作(请注意第一次和第二次调用返回值的不同):

  1. $ curl -X GET -i http://localhost:8080/dictionary/put?foo = bar
  2. HTTP/1.1 200
  3. Content-Type: application/json
  4. Transfer-Encoding: chunked
  5. Date: Wed, 11 Dec 2019 19:56:43 GMT
  6. null
  7. $ curl -X GET -i http://localhost:8080/dictionary/put?foo = bar
  8. HTTP/1.1 200
  9. Content-Type: application/json
  10. Transfer-Encoding: chunked
  11. Date: Wed, 11 Dec 2019 19:56:44 GMT
  12. "bar"

然后使用get操作验证先前的put:

  1. $ curl -X GET -i http://localhost:8080/dictionary/get?foo
  2. HTTP/1.1 200
  3. Content-Type: application/json
  4. Transfer-Encoding: chunked
  5. Date: Wed, 11 Dec 2019 19:59:22 GMT
  6. "bar"

检索字典条目集演示了复杂的JSON编码:

  1. $ curl -X GET -i http://localhost:8080/dictionary/entrySet
  2. HTTP/1.1 200
  3. Content-Type: application/json
  4. Transfer-Encoding: chunked
  5. Date: Wed, 11 Dec 2019 20:00:24 GMT
  6. [ {
  7. "foo" : "bar"
  8. } ]

提供查询参数大小可演示错误处理:

  1. $ curl -X GET -i http://localhost:8080/dictionary/size?foo
  2. HTTP/1.1 500
  3. Content-Type: application/json
  4. Transfer-Encoding: chunked
  5. Date: Wed, 11 Dec 2019 20:03:42 GMT
  6. Connection: close
  7. {
  8. "timestamp" : "2019-12-11T20:03:42.110+0000" ,
  9. "status" : 500,
  10. "error" : "Internal Server Error" ,
  11. "message" : "No message available" ,
  12. "trace" : "java.lang.IllegalArgumentException \n\t at application.DictionaryRestController.size(DictionaryRestController.java:65) \n ..." ,
  13. "path" : "/dictionary/size"
  14. }

摘要

本文通过展示如何“演示基本春天依赖注入@Value的”可以被计算并注入“ @Bean的”可以创建和“ @Autowired在” @RestController实现。

本系列的第4部分将讨论Spring MVC,并以一个简单的国际化时钟应用程序为例。


  1. SpEL还提供对application.properties资源中定义的属性的访问。

  2. 不幸的是, GET HTTP方法与Map put方法结合使用可能会造成混乱,并且更复杂的API定义可能会合理地使用POSTPUT方法获取其语义值。

From: https://dev.to/allenball/spring-boot-part-3-dependency-injection-and-restcontroller-3374

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/580095
推荐阅读
相关标签
  

闽ICP备14008679号