未命名
添加静态文件
第一种,使用property文件
1 | spring.mvc.static-path-pattern=/static/** |
第二种,使用自定义
1 |
|
未命名
注解的作用
本文打算介绍几个不太容易说出其区别,或者用途的 Spring 注解,比如 @Component 与 @Bean 的比较,@ControllerAdvice 是如何处理自定义异常的等等。
Spring 中的一些注解
1. @Component 和 @Bean 的区别是什么?
- 作用对象不同:@Component 注解作用于类,而 @Bean 注解作用于方法、
- @Component 通常是通过路径扫描来自动侦测以及自动装配到 Spring 容器中(我们可以使用 @ComponentScan 注解定义要扫描的路径从中找出标识了需要装配的类自动装配到 Spring 的 bean 容器中)。@Bean 注解通常是我们在标有该注解的方法中定义产生这个 bean,@Bean 告诉了 Spring 这是某个类的实例,当我们需要用它的时候还给我。
- @Bean 注解比 @Component 注解的自定义性更强,而且很多地方我们只能通过 @Bean 注解来注册 bean。比如当我们引用第三方库中的类需要装配到 Spring 容器时,只能通过 @Bean 来实现。
1 | @Bean //注解使用示例: |
2. Autowire 和 @Resource 的区别
- @Autowire 和 @Resource都可以用来装配bean,都可以用于字段或setter方法。Spring Boot 学习笔记分享给你。
- @Autowire 默认按类型装配,默认情况下必须要求依赖对象必须存在,如果要允许 null 值,可以设置它的 required 属性为 false。
- @Resource 默认按名称装配,当找不到与名称匹配的 bean 时才按照类型进行装配。名称可以通过 name 属性指定,如果没有指定 name 属性,当注解写在字段上时,默认取字段名,当注解写在 setter 方法上时,默认取属性名进行装配。
注意:如果 name 属性一旦指定,就只会按照名称进行装配。
@Autowire和@Qualifier配合使用效果和@Resource一样:
@Autowired(required = false) @Qualifier(“example”) private Example example; @Resource(name = “example”) private Example example;
@Resource 装配顺序
- 如果同时指定 name 和 type,则从容器中查找唯一匹配的 bean 装配,找不到则抛出异常;
- 如果指定 name 属性,则从容器中查找名称匹配的 bean 装配,找不到则抛出异常;
- 如果指定 type 属性,则从容器中查找类型唯一匹配的 bean 装配,找不到或者找到多个抛出异常;
- 如果不指定,则自动按照 byName 方式装配,如果没有匹配,则回退一个原始类型进行匹配,如果匹配则自动装配。
3. 将一个类声明为 Spring 的 bean 的注解有哪些?
- @Component :通用的注解,可标注任意类为 Spring 的组件。如果一个 Bean 不知道属于哪个层,可以使用 @Component 注解标注。
- @Repository :对应持久层即 Dao 层,主要用于数据库相关操作。
- @Service :对应服务层,主要设计一些复杂的逻辑,需要用到 Dao 层。
- @Controller :对应 Spring MVC 控制层,主要用来接受用户请求并调用 Service 层返回数据给前端页面。
- @Configuration :声明该类为一个配置类,可以在此类中声明一个或多个 @Bean 方法。
4. @Configuration :配置类注解
@Configuration 表明在一个类里可以声明一个或多个 @Bean 方法,并且可以由 Spring 容器处理,以便在运行时为这些 bean 生成 bean 定义和服务请求,例如:
1 | @Configuration public class AppConfig { @Bean public MyBean myBean() { // instantiate, configure and return bean ... } } |
我们可以通过 AnnotationConfigApplicationContext 来注册 @Configuration 类:
1 | AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.register(AppConfig.class); ctx.refresh(); MyBean myBean = ctx.getBean(MyBean.class); // use myBean ... |
另外也可以通过组件扫描(component scanning)来加载,@Configuration 使用 @Component 进行原注解,因此 @Configuration 类也可以被组件扫描到(特别是使用 XML 的 元素)。@Configuration 类不仅可以使用组件扫描进行引导,还可以使用 @ComponentScan 注解自行配置组件扫描:
@Configuration @ComponentScan(“com.acme.app.services”) public class AppConfig { // various @Bean definitions … }
使用 @Configuration 的约束:
- 配置类必须以类的方式提供(比如不能是由工厂方法返回的实例)。
- 配置类必须是非 final 的。
- 配置类必须是非本地的(即可能不在方法中声明),native 标注的方法。
- 任何嵌套的配置类必须声明为 static。
- @Bean 方法可能不会反过来创建更多的配置类。
除了单独使用 @Configuration 注解,我们还可以结合一些外部的 bean 或者注解共同使用,比如 Environment API,@PropertySource,@Value,@Profile 等等许多,这里就不做详细介绍了,更多的用法可以参看 Spring @Configuration 的相关文档 。
推荐一个 Spring Boot 基础教程及实战示例:https://github.com/javastacks/spring-boot-best-practice
5. @ControllerAdvice :处理全局异常利器
在 Spring 3.2 中,新增了 @ControllerAdvice、@RestControllerAdvice、@RestController 注解,可以用于定义 @ExceptionHandler、@InitBinder、@ModelAttribute,并应用到所有 @RequestMapping 、@PostMapping、@GetMapping等这些 Controller 层的注解中。
默认情况下,@ControllerAdvice 中的方法应用于全局所有的 Controller。而使用选择器 annotations(),basePackageClasses() 和 basePackages() (或其别名value())来定义更小范围的目标 Controller 子集。Spring Boot 学习笔记分享给你。
如果声明了多个选择器,则应用 OR 逻辑,这意味着所选的控制器应匹配至少一个选择器。请注意,选择器检查是在运行时执行的,因此添加许多选择器可能会对性能产生负面影响并增加复杂性。
@ControllerAdvice 我们最常使用的是结合 @ExceptionHandler 用于全局异常的处理。可以结合以下例子,我们可以捕获自定义的异常进行处理,并且可以自定义状态码返回:
1 | @ControllerAdvice("com.developlee.errorhandle") public class MyExceptionHandler { /** * 捕获CustomException * @param e * @return json格式类型 */ |
更多信息可以参看 Spring @ControllerAdvice 的官方文档。推荐一个 Spring Boot 基础教程及实战示例:https://github.com/javastacks/spring-boot-best-practice
6. @Component, @Repository, @Service 的区别
@Component是一个通用的Spring容器管理的单例bean组件。而@Repository, @Service, @Controller就是针对不同的使用场景所采取的特定功能化的注解组件。
因此,当你的一个类被@Component所注解,那么就意味着同样可以用@Repository, @Service, @Controller 来替代它,同时这些注解会具备有更多的功能,而且功能各异。
最后,如果你不知道要在项目的业务层采用@Service还是@Component注解。那么,@Service是一个更好的选择。
未命名
常用注解解析
1. 有这么一个故事,从xml配置文件的bean说起
Spring用xml配置文件的时候(不知道阅读这篇文章的你用没用过,我用过一段时间,那是黑暗伤痛的回忆QQQ),一个xml配置文件里面有很多个bean。类似这样:
1 | <bean id="helloWorld" class="com.test.spring.beans.HelloWorld"> |
每个bean都对应着一个class,可能是controller,可能是service,可能是dao,xml配置文件就是告诉Spring,我这里有哪些bean,他们都叫啥名字(例如helloworld),他们的class文件在哪(com.test.spring.beans.HelloWorld),他们都有哪些属性。这样,当项目启动时,Spring就回去管理这些类了。
2. 进入@Configuration时代
你现在使用@Service
、@Repository
、@Component
这些注解放在java的类上用来告诉Spring:“我标注的这些类请你来管理”。在以前就是要在xml配置文件里写上面这样的bean,有一个类写一个bean(实在是太麻烦了。。。。。,不方便码代码,不方便阅读,不方便修改),一个xml配置文件写好多bean。
总结一下:
@Configuration
注解就相当于xml配置文件,告诉Spring我这里有好多bean要交给你管理@Bean
注解就相当于xml配置文件里面的bean,告诉Spring这个被注解的类就交给你管理了
到这里,Spring发展史中注解替换xml配置文件的故事就讲完了,是不是很简单!
=十万个为什么的分割线=======
那,既然问题都解决了,有@Component啥事???
年轻人,sometimes naive
3. @Component粉墨登场
无名子曰过,偷懒是人类创造力的源泉。我都把class类写好了,还要再写个@Configuration
注解的class去告诉Spring(除了通知Spring,这个class不产生其他价值),虽然这个class相比于xml配置文件写起来方便又好阅读,但是,这个时候总有但是,我为啥不直接就告诉Spring呢???
@Controller
、@Service
、@Repository
都是@Component
的更具体一点的实现(这里如果说错了,求大佬轻喷)。写完class加上这些注解,其实就是加上@Component
注解,Spring就懂了,奥奥,你小子太懒了,这么多类全部是让我来管理的,不过话说回来谁让我是你baba呢!
是不是这就完事了呢,是的,没有但是,真的就完事了。
4. “但是”又回来了
是的,这里又有但是了。可能有人想到了,既然@Component
跟Spring已经把问题解决了,那,@Bean
这个注解为啥还没退休啊,还在这站着地儿,咋不见新版Spring给加个@Deprecated
???
年轻人,有想法!!!
假设这么一种情况,有几个class,我自己也不是不能写,但是写了周末就没时间去外滩闲逛了,就在这个时候,我发现alimama的老铁们已经写好了同样功能的class,我在maven里import一下就完了,开心三秒,又有问题了,他们写的时候没用Spring:
- 1)打好的jar包,我不能在class上面加
@Component
注解; - 2)我没有他们的源码,也不能把他们的代码复制过来,假装自己重写了一遍QQQ
这时候@Bean
的作用就体现出来了,请看:
1 | @Configuration |
虽然又回到了@Component出场
之前的@Configuration
时代。但是你也不需要经常使用这个对吧
4. 让我们以一点小干货结束今天的故事
Spring管理的Bean我们需要通过@Autowired
或者@Resource
导入来使用,这两的区别啥的你可以自己去搜索一下,这里只说一个问题。@Autowired
是按照类型装配的,@Resource
是按照名称装配的,加入同一类型有多个bean,只是名字不一样,@Autowired
直接导入会报错。这时候课题通过@Resource(name="name")
或者@Autowired@Qualifier("name")
来按名称装配,解决问题。
未命名
java-jwt使用
单点登录
https://github.com/longguikeji/arkid
JwtUtil.java
1 | package com.macro.mall.tiny.security.util; |
UserController.java
1 | package com.example.first.controller; |
未命名
初始化执行操作
通常的我们的项目开发中,经常会遇到那种在服务一启动就需要自动执行一些业务代码的情况。比如将数据库中的配置信息或者数据字典之类的缓存到redis,或者在服务启动的时候将一些配置化的定时任务开起来。关于spring mvc或者springboot如何在项目启动的时候就执行一些代码
@PostConstruct
注解
从Java EE5规范开始,Servlet中增加了两个影响Servlet生命周期的注解,@PostConstruct和@PreDestroy,这两个注解被用来修饰一个非静态的void()方法。@PostConstruct会在所在类的构造函数执行之后执行,在init()方法执行之前执行。(@PreDestroy注解的方法会在这个类的destory()方法执行之后执行。)
@PostConstruct
不是spring提供的而是Java自己的注解。
Java中该注解的说明:@PostConstruct该注解被用来修饰一个非静态的void()方法。被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。PostConstruct注释用于需要依赖注入完成后才能执行任何初始化的方法上。 在类投入使用之前,必须调用此方法
在使用spring框架时,在一个类内,如果有构造器(Constructor ),有@PostConstruct,还有@Autowired,他们的先后执行顺序为Constructor >> @Autowired >> @PostConstruct。在类加载的时候,为当前类初始化一些数据,那么可以使用@PostConstruct注解
1 | @Component // 注意 这里必须有 |
实现CommandLineRunner接口并重写run()方法
其实有两个接口ApplicationRunner,CommandLineRunner
这两个接口中有一个run方法,只需要实现这个方法即可。这两个接口的不同之处在于:ApplicationRunner中run方法的参数为ApplicationArguments,而CommandLineRunner接口中run方法的参数为String数组。
:::tip
注意:一定要有@Component这个注解。要不然SpringBoot扫描不到这个类,* 是不会执行。
@Order注解
如果有多个实现类,而需要他们按一定顺序执行的话,可以在实现类上加上@Order注解。@Order(value=整数值)。SpringBoot会按照@Order中的value值从小到大依次执行。
:::
例子
1 | @Component // 注意 这里必须有 |
使用监听器
1 |
|
然后在resources/META-INF/spring.factories
写下
1 | org.springframework.context.ApplicationListener=\ |
就可以在启动前写入sql
未命名
未命名
其他api框架
vert.x
https://github.com/eclipse-vertx/vert.x
jfinal
https://jfinal.com/
https://gitee.com/jfinal/jfinal
jboot
jboot: http://www.jboot.io/
未命名
未命名
springboot使用controller传递参数
:::tip
see https://github.com/yzqdev/spring-tutor/tree/dev/spring-transfer
额外内容 AntPathMatcher和PathPattern的区别
详细文档见spring.io
:::
基本传参方式
直接上代码
:::tip
注意
multipart/form-data与x-www-form-urlencoded的区别:
multipart/form-data:可以上传文件或者键值对,最后都会转化为一条消息
x-www-form-urlencoded:只能上传键值对,而且键值对都是通过&间隔分开的。
application/json: 上传的是json键值对
:::
1 | @RestController |
map传参方式(不推荐)
1 | @RestController |