内容源自文心一言/网上文摘等,只是记录下来自己的思考和提问,便于自己回顾
Springboot的组件扫描机制是怎么样的?为什么我的filter包是放在Spring Boot主应用程序类所在的包下的,为什么不会被扫描到?
原因:是因为Springboot的扫描机制,只会扫描被Spring框架管理的bean,而filter其实不是属于Springboot的,而是属于javaWeb的,所以你及时放在同级包中也没有用,如果要用就得在Springboot启动类中加上@ServletComponentScan注解,这个注解可以用于自动注册实现了@WebFilter、@WebListener或@WebServlet等Servlet 3.0+规范中定义的注解的组件。
详解:
Spring Boot在启动时,其组件扫描机制默认会扫描主应用程序类(即带有@SpringBootApplication注解的类)所在的包及其子包下的组件。这里的“组件”指的是那些被Spring框架管理的Bean,它们通常是通过@Component、@Service、@Repository、@Controller等注解来标注的Java类。
具体来说,Spring Boot的组件扫描机制如下:
基于主应用程序类的包扫描:
当Spring Boot应用程序启动时,它会从主应用程序类(即带有@SpringBootApplication注解的类)所在的包开始扫描。这个扫描过程会递归地查找该包及其所有子包下的Java类。
识别组件:
在扫描过程中,Spring Boot会查找那些被Spring框架的特定注解(如@Component、@Service、@Repository、@Controller等)标注的类。这些被标注的类会被识别为Spring容器需要管理的Bean。
注册组件:
一旦识别出这些组件,Spring Boot就会将它们注册到Spring的IoC(Inversion of Control,控制反转)容器中。
注册后的组件就可以通过Spring的依赖注入机制(如@Autowired注解)被其他组件使用。
需要注意的是,Spring Boot的组件扫描机制并不是扫描主应用程序类所在包及其子包下的所有Java文件。它只会扫描那些被Spring框架的特定注解标注的Java类,并将它们识别为组件进行注册。其他没有被标注的Java文件则不会被Spring Boot的组件扫描机制识别和处理。
此外,如果需要在主应用程序类所在包之外的其他包中扫描组件,可以使用@ComponentScan注解来指定额外的扫描路径。例如:
java
@SpringBootApplication
@ComponentScan(basePackages = {"com.example.otherpackage"})
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
在这个例子中,@ComponentScan注解指定了除了主应用程序类所在包之外,还需要扫描com.example.otherpackage包下的组件。
为什么请求都会经过Filter?是协议规定的吗?
当你是一个Web应用程序,那就有它的规则。客户端,服务端。请求与响应。
详解:
请求会经过Filter并不是由协议直接规定的,而是由Web应用架构和Filter在其中的角色所决定的。具体来说,Filter在Web应用中起着拦截和处理请求与响应的作用,其原理基于责任链模式。以下是关于为什么请求会经过Filter的详细解释:
Filter的作用:
Filter是Java Web应用中一种常用的组件,用于在请求和响应之间进行拦截和处理。通过在请求链和响应链中插入自定义的过滤器,可以对请求和响应进行各种操作,如日志记录、身份验证、授权、数据转换等。
Filter的执行流程:
当一个请求到达服务器时,它首先会经过Web容器(如Tomcat)。
Web容器会根据请求的URL匹配到对应的Servlet或JSP进行处理。
在这个过程中,Filter会被依次执行。Filter的执行顺序是由部署描述符(web.xml)中的配置决定的。
Filter的配置:
在web.xml中,我们可以为Filter配置<filter>和<filter-mapping>元素。
<filter>元素用于定义Filter的名称和类路径。
<filter-mapping>元素用于配置Filter的拦截路径。当请求到达时,Web容器会根据这些配置找到匹配的Filter并执行。
Filter与协议的关系:
虽然HTTP协议定义了Web客户端和服务器之间如何通信,但它并没有规定请求必须经过Filter。
Filter是Web应用架构中的一个组件,用于在Web容器内部对请求和响应进行额外的处理。
因此,请求会经过Filter是由Web应用架构和Filter的角色所决定的,而不是由协议直接规定的。
总结来说,请求会经过Filter是因为Filter在Web应用架构中扮演着拦截和处理请求与响应的角色。虽然这不是由HTTP协议直接规定的,但它是Web应用开发中的一种常见做法,用于实现各种功能需求。
什么是链式编程,在学习JWT令牌技术的时候接触到这个写法,记录一下!
原写法:
@Test
public void testGenJwt(){
Map<String, Object> claims = new HashMap<>();
claims.put("id",1);
claims.put("name","tom");
String jwt = Jwts.builder()
.signWith(SignatureAlgorithm.HS256, "itheima")//签名算法
.setClaims(claims) //自定义内容(载荷)
.setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000))//设置有效期为1h
.compact();
System.out.println(jwt);
}
详解:
链式编程(Chaining Programming),也被称为链式调用或流式编程,是一种编程风格,旨在提高代码的流畅性和简洁性。以下是关于链式编程的详细解释:
定义与概念:
链式编程允许通过点号(.)将多个方法或函数连续调用,而无需在每次调用后都重新引用对象本身。
每个方法调用后返回一个对象或实例,使得可以继续在该对象或实例上调用其他方法,从而形成一条调用链。
核心思想:
每个被调用的方法都需要返回调用它的对象本身(通常是通过返回this指针或当前对象实例),以实现链式调用。
这种编程风格的主要目的是减少代码的冗余,提高代码的可读性和可维护性。
示例:
以Java中的StringBuffer为例,它就是一个典型的链式编程实现。通过连续调用append()方法,可以不断地向StringBuffer中添加内容,而无需每次都重新创建新的StringBuffer对象。
另一个示例是自定义一个StudentBean类,其中setName()和setAge()方法都返回this指针,从而允许链式调用,如new StudentBean().setAge(22).setName("ly")。
优势:
代码更加简洁和流畅,减少了冗余和复杂性。
提高了代码的可读性,使得代码更易于理解和维护。
在某些情况下,链式编程可以提高代码的执行效率,因为它减少了对象的创建和销毁次数。
注意事项:
虽然链式编程带来了很多好处,但过度使用也可能导致代码难以理解和维护。因此,在使用链式编程时需要根据实际情况进行权衡和选择。
链式编程通常适用于那些需要连续设置多个属性的场景,如配置对象或构建复杂的数据结构等。
总之,链式编程是一种强大的编程风格,通过连续调用方法并返回对象本身来实现代码的简洁和流畅。在实际开发中,可以根据项目需求选择是否使用链式编程来提高代码质量。
什么是面向接口编程?
- 思考:以前单机的时候,考虑功能很简单,能实现就行。例如要支付,可能有多种支付方式。那就写一个支付类,然后里面创建各种各样的支付方法(支付宝、微信等等),但是业务一变,我就又得修改源代码,增加新的方法。但是面向接口就有这好处,利用多态,子类继承父类的方法,然后使用父类来引用子类,具体的实现交给具体的子类(把功能抽象出来,具体怎么实现交给子类)
- 详解:
好的,以下是一个简单的面向接口编程的例子。
假设我们要设计一个系统,这个系统可以处理不同的支付方式,比如信用卡支付、支付宝支付等。为了遵循面向接口编程的原则,我们可以首先定义一个支付接口,然后为每种支付方式创建一个实现类。
首先,我们定义一个名为Payment的接口:
public interface Payment {
void pay(double amount);
}
这个接口定义了一个pay方法,它接受一个金额参数。接下来,我们为每种支付方式创建一个实现类。首先是信用卡支付:
public class CreditCardPayment implements Payment {
@Override
public void pay(double amount) {
System.out.println("Paying " + amount + " with credit card.");
// 具体的支付逻辑
}
}
然后是支付宝支付:
public class AliPay implements Payment {
@Override
public void pay(double amount) {
System.out.println("Paying " + amount + " with AliPay.");
// 具体的支付逻辑
}
}
现在,我们的系统可以很容易地支持新的支付方式,只需要创建一个新的类并实现Payment接口即可。
在主程序中,我们可以这样使用这些支付方式:
public class Main {
public static void main(String[] args) {
Payment creditCardPayment = new CreditCardPayment();
creditCardPayment.pay(100.0);
Payment aliPay = new AliPay();
aliPay.pay(200.0);
}
}
这个例子展示了面向接口编程的核心思想:定义接口来抽象功能,然后创建实现这些功能的类。这样做的好处是,当需要添加新的支付方式时,只需要创建一个新的类并实现相应的接口,而不需要修改现有的代码。这大大提高了代码的可扩展性和可维护性。