要想全面快速学习Spring的内容,最好的方法肯定是先去Spring官网去查阅文档,在Spring官网中找到了适合新手了解的官网Guides,一共68篇,打算全部过一遍,能尽量全面的了解Spring框架的每个特性和功能。
开始吧,自己按照顺序给每篇Guide编了号。
guide1、Building a restful web service
主要讲的是如何创建一个restful web服务,每篇guide里还提供了示例代码,可以自己git clone下来看看,当然每篇guide只是介绍了Spring的一个点,因此代码也不复杂,自己动手写也很快。
核心代码是编写一个Controller,启动程序后,可以根据路径直接访问接口。
@RestController
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
@GetMapping("/greeting")
public Greeting greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
return new Greeting(counter.incrementAndGet(), String.format(template, name));
}
}
Guide涉及注解:
@RestController: spring4.0引入该注解以简化restful web服务的创建。相当于@Controller + @ResponseBody注解。
@Controller注解是@Component的注解的一种特殊化,被用来注解controller类,该类可以接收HTTP请求。
@ResponseBody, 使用后将返回对象自动序列化到HttpResponse中。
如果需要返回内容,例如json数据,@RestController自己就可以,@Controller需要和@ResponseBody搭配才行。
@Component注解,可以让 Spring 自动检测使用该注解的bean。
Spring 将:
扫描应用程序以查找使用@Component注解的类
实例化它们并将任何指定的依赖项注入其中
在需要的地方注入它们
@requestMapping注解:简单讲,就是将web请求映射到spring controller的方法上。
value参数是指定的映射路径地址,method参数代表的是请求类型,headers代表的是指定的请求头信息。示例代码:
@RequestMapping(value = "/ex/foos", headers = "key=val", method = GET)
@ResponseBody
public String getFoosWithHeader() {
return "Get some Foos with Header";
}
spring 4.3引入了其他的几个新http映射注解,都是基于@requestMapping的。
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
这五个注解分别用来处理不同类型的http请求。
@PathVariable()注解:用来映射URL中绑定的占位符。如果参数名称与路径变量名称匹配,可以变为:@PathVariable long id。示例代码:
@RequestMapping(value = "/ex/foos/{id}", method = GET)
@ResponseBody
public String getFoosBySimplePathWithPathVariable(@PathVariable("id") long id)
{
return "Get a specific Foo with id=" + id;
}
@requestParam注解用来映射url参数, 如下例,从而获取id参数。可以用name属性或者value属性配置参数名称。以及require属性标记该参数是否被需要。defaultValue参数提供默认值。示例代码:
@RequestMapping(value = "/ex/bars", method = GET)
@ResponseBody
public String getBarBySimplePathWithRequestParam(@RequestParam("id") long id)
{
return "Get a specific Bar with id=" + id;
}
@requestBody 注释将HttpRequest body自动反序列化到 Java 对象上。一般是用来处理content-type为application/json的类型。
注意点:
GET方式无请求体,所以使用@RequestBody接收数据时,前端不能使用GET方式提交数据,需要用POST方式进行提交。在后端的同一个接收方法里,@RequestBody与@RequestParam()可以同时使用,@RequestBody最多只能有一个,而@RequestParam()可以有多个。
@SpringBootApplication:使用这个注解来标记 Spring Boot 应用程序的主类。并且@SpringBootApplication封装了@Configuration、 @EnableAutoConfiguration和**@ComponentScan注解及其默认属性。
@Configuration该注解表示一个类声明了一个或多个拥有 @Bean注解的方法,并且这些拥有 @Bean的方法的返回对象将被 Spring 容器管理,在其他类中就可以使用 @Autowired注解注入这些 Bean。
@EnableAutoConfiguration 注解表示开启自动配置功能。意味着spring boot在类路径上寻找自动配置的bean并自动运用它。
@ComponentScan 注解其实很简单,它主要就是定义扫描的包路径,然后从中找出标识了需要装配的类自动装配到Spring的Bean容器。
guide2、consuming a restful web service
主要讲的是如何利用restTemplate发请求,并获取接口返回数据。
Guide涉及注解:
@JsonIgnoreProperties:忽略类中不存在的字段;也可以指定要忽略的字段。参数ignoreUnknown:该属性定义在反序列化期间是否可以忽略任何无法识别的字段。
举例:
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class Request {
private String deviceName;
private String deviceType;
}
在类上加了该注解,如果该Request类是后台接收的实体类。且接收到的序列化json
{
"deviceName": "xxx",
"deviceType": "xxx",
"devicePower": 120
}
加上该注解后,因为devicePower在类中不存在,所以反序列化时会忽略该字段。
@JsonProperty:此注解用于实体类的属性上,功能是把属性名称转换为另一个名称。
import com.fasterxml.jackson.annotation.JsonProperty;
public class Student {
@JsonProperty("name")
private String trueName;
}
CommandLineRunner:项目启动之后就立即执行的操作
@Bean
public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
return args -> {
Quote quote = restTemplate.getForObject(
"http://localhost:8080/api/random", Quote.class);
log.info(quote.toString());
};
}
如果有多个类实现CommandLineRunner接口类,如果需要按照一定的顺序去执行,那么就需要在实体类上使用一个@Order注解(或者实现Order接口)来表明顺序。
guide3、building java project with maven
讲的是如何用maven创建java项目。
主要是pom.xml文件,定义了maven项目的名称、版本和对外部库的依赖等。
以及maven的生命周期,使用mvn compile 、mvn package、mvn install进行编译、打包、打包到本地依赖库等。Guide只是简单介绍下用maven创建项目。
详细了解Maven可以直接去Maven官网。 https://maven.apache.org/
guide4、upload file
主要讲的是如何上传文件, 关键是Path类与Files类。
java.nio.file.Path类:Java Path实例表示文件系统中的路径。路径可以指向文件或目录。路径可以是绝对的或相对的。
1、创建Path实例:
// 可以在Paths类(java.nio.file.Paths)中使用静态方法创建Path实例。
Path path = Paths.get("c:\\data\\myfile.txt");
2、File、Path、URI之间的转换:
File file = new File("C:/my.ini");
Path path = file.toPath();
path.toFile();
file.toURI();
java.nio.file.Files类:
guide里演示的文件上传其实就是使用了:
--文件的复制,将文件输入流中的数据复制到path里。
Files.copy(InputStream in, Path target, CopyOption... options)
Files还提供的有其他api等等
--创建目录
createDirectory(Path dir, FileAttribute<?>... attrs)
--创建文件
createFile(Path path, FileAttribute<?>... attrs)
顺便扩展工作中遇到的相关知识:
file的输入输出流:https://blog.csdn.net/Steriles_/article/details/82800245
BASE64与图片互转的代码:https://note.youdao.com/s/AnIZafUY
Guide涉及注解:
@Service注解用于类上,标记当前类是一个service类,加上该注解会将当前类自动注入到spring容器中,不需要再在applicationContext.xml文件定义bean了。
@ConfigurationProperties注解:
在 SpringBoot 中,当想需要获取到配置文件数据时,除了可以用 Spring 自带的 @Value 注解外,SpringBoot 还提供了一种更加方便的方式:@ConfigurationProperties。只要在 Bean 上添加上了这个注解,指定好配置文件的前缀,那么对应的配置文件数据就会自动填充到 Bean 中。
比如在application.properties文件中有如下配置文件
config.username=jay.zhou
config.password=3333
那么按照如下注解配置,SpringBoot项目中使用@ConfigurationProperties的Bean,它的username与password就会被自动注入值了。就像下面展示的那样
@Component
@ConfigurationProperties(prefix = "config")
public class TestBean{
private String username;
private String password;
}
@value注解:是将配置文件的属性读出来,这就是读取配置项中的spring.port属性
@Value("${spring.port}")
private String port;
@EnableConfigurationProperties注解的作用是:使用了 @ConfigurationProperties 注解的类生效。一般用在启动类上, 如下:
@SpringBootApplication
@EnableConfigurationProperties(StorageProperties.class)
public class UploadingFilesApplication {
public static void main(String[] args) {
SpringApplication.run(UploadingFilesApplication.class, args);
}
}
如果一个配置类只配置@ConfigurationProperties注解,而没有使用@Component,那么在IOC容器中是获取不到properties 配置文件转化的bean。说白了 @EnableConfigurationProperties 相当于把使用 @ConfigurationProperties 的类进行了一次注入。
guide5、Messaging with Redis
这篇guide主要讲的是简单使用redis去发布和订阅消息。
redis不仅提供一个noSql数据存储,还提供了一个消息传递系统。虽然平常工作一般只是拿Redis去做缓存,提高访问数据的速度。但是Guide这里也介绍了如何用Redis去发消息。
1、先定义一个消息接收者。
简单创建一个具有响应消息方法的接收器。如下,这
Receiver是一个 POJO,它定义了接收消息的方法 receiveMessage。
public class Receiver {
private static final Logger LOGGER = LoggerFactory.getLogger(Receiver.class);
private AtomicInteger counter = new AtomicInteger();
public void receiveMessage(String message) {
LOGGER.info("Received <" + message + ">");
int i = counter.incrementAndGet();
System.out.println(i);
}
public int getCount() {
return counter.get();
}
}
2、注册监听器并发送消息
spring data reids 提供了使用redis发送和接收消息所需的所有组件。具体需要配置:
- 连接工厂
- 一个消息监听器容器
- 一个 Redis 模板
@SpringBootApplication
public class MessagingRedisApplication {
private static final Logger LOGGER = LoggerFactory.getLogger(MessagingRedisApplication.class);
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(listenerAdapter, new PatternTopic("chat"));
return container;
}
--因为Receiver是一个POJO,所以需要去包装为一个消息监听适配器MessageListenerAdapter。
消息侦听器适配器还配置为在消息到达时调用该receiveMessage()方法。
@Bean
MessageListenerAdapter listenerAdapter(Receiver receiver) {
return new MessageListenerAdapter(receiver, "receiveMessage");
}
@Bean
Receiver receiver() {
return new Receiver();
}
@Bean
StringRedisTemplate template(RedisConnectionFactory connectionFactory) {
return new StringRedisTemplate(connectionFactory);
}
public static void main(String[] args) throws InterruptedException {
ApplicationContext ctx = SpringApplication.run(MessagingRedisApplication.class, args);
StringRedisTemplate template = ctx.getBean(StringRedisTemplate.class);
Receiver receiver = ctx.getBean(Receiver.class);
while (receiver.getCount() == 0) {
LOGGER.info("Sending message...");
template.convertAndSend("chat", "Hello from Redis!");
Thread.sleep(500L);
}
System.exit(0);
}
}
在main方法中,通过创建spring应用程序上下文来启动所有操作。应用程序上下文启动消息监听容器,receiver bean开始侦听消息。
然后在应用程序上下文中启动stringTenplate bean并使用它发送主题chat的消息Hello from Redis!。
运行结果:
2023-04-23 12:57:12.848 INFO 35396 --- [ main] c.e.m.MessagingRedisApplication : Started MessagingRedisApplication in 1.511 seconds (JVM running for 3.685)
2019-04-23 12:57:12.849 INFO 35396 --- [ main] c.e.m.MessagingRedisApplication : Sending message...
2019-04-23 12:57:12.861 INFO 35396 --- [ container-2] com.example.messagingredis.Receiver : Received <Hello from Redis!>