Spring MVC知识
1 Spring 框架
Spring 框架指的都是 Spring Framework,它是很多模块的集合,使用这些模块可以很方便地协助我们进行开发。
Spring 自带 IoC(Inverse of Control:控制反转) 和 AOP(Aspect-Oriented Programming:面向切面编程)、可以很方便地对数据库进行访问、可以很方便地集成第三方组件(电子邮件,任务,调度,缓存等等)、对单元测试支持比较好、支持 RESTful Java 应用程序的开发。
构建最基础的Spring项目
1.1 核心容器四个包
- spring-beans-4.1.3.RELEASE.jar
- 这个jar 文件是所有应用都要用到的,它包含访问配置文件、创建和管理bean 以及进行Inversion of Control / Dependency Injection(IoC/DI)操作相关的所有类。如果应用只需基本的IoC/DI 支持,引入spring-core.jar 及spring-beans.jar 文件就可以了。 外部依赖spring-core,(CGLIB)。
- spring-context-4.1.3.RELEASE.jar
- 这个jar 文件为Spring 核心提供了大量扩展。可以找到使用Spring ApplicationContext特性时所需的全部类,JDNI 所需的全部类,instrumentation组件以及校验Validation 方面的相关类。 外部依赖spring-beans, (spring-aop)。
- spring-core-4.1.3.RELEASE.jar
- 这个jar 文件包含Spring 框架基本的核心工具类。Spring 其它组件要都要使用到这个包里的类,是其它组件的基本核心,当然你也可以在自己的应用系统中使用这些工具类。 外部依赖Commons Logging, (Log4J)。
- spring-expression-4.1.3.RELEASE.jar
1.2 核心容器依赖的日志包
- commons-logging-1.2.jar 当于一个日志接口,log4j相当于该接口的实现,如果不添加log4j包也可以,因为commons-logging也有一个简单的实现会自动使用。
- log4j-1.2.17.jar
1.3 测试类包
- spring-test-4.1.3.RELEASE.jar
- junit-4.10.jar(高于4.10版本还需要hamcrest-core.jar + hamcrest-library.jar)
1.4 测试类用到了AOP必须导入aop包
1. spring-aop-4.1.3.RELEASE.jar
1.1 IOC: 控制反转,依赖注入(DI)。比喻A对象创建时,注入到Spring容器,容器会为A对象依赖注入所需要的B对象,由主动变为被动。
Spring提供实现IoC容器的两种方式(两个接口)
1)BeanFactory :IoC容器基本实现,是Spring内部使用的接口,不提供开发人员使用。
BeanFactory加载配置文件时不创建对象,在获取对象(使用)时才创建
2)ApplicationContext :实际是BeanFactory的子接口,提供更强大的功能,提供给开发人员使用。ApplicationContext加载配置文件时就创建对象。
https://blog.csdn.net/weixin_44775375/article/details/124958143
1.2 AOP: 分为JDK动态代理(实现了接口的类生成代理),CGlib动态代理(类实现代理)
https://www.cnblogs.com/flashsun/p/7286475.html
什么时候用JDK动态代理,什么时候用CJLIB动态代理
1、目标对象生成了接口 默认用JDK动态代理
2、如果目标对象使用了接口,可以强制使用cglib
3、如果目标对象没有实现接口,必须采用cglib库,Spring会自动在JDK动态代理和cglib之间转换
Cglib和JDK的效率比较
1、cglib底层是ASM字节码生成框架,但是字节码技术生成代理类,在JDL1.8之后比使用java反射的效率要低
2、Cglib不能对声明final的方法进行代理,因为cglib是动态生成代理对象,final关键字修饰的类不可变只能被引用不能被修改
Spring如何选择是用JDK还是cglib
1、当bean实现接口时,会用JDK代理模式
2、当bean没有实现接口,用cglib实现
3、可以强制使用cglib(在spring配置中加入<aop:aspectj-autoproxy proxyt-target-class=”true”/>)
AOP的应用场景:
1.日志处理
2.用户登录
3.权限(Authentication )
4.性能优化(Performance optimization)
5.事务(Transactions )
6.记录跟踪 优化 校准(logging, tracing, profiling and monitoring)
7.调试(Debugging)
8.懒加载(Lazy loading)
9.错误处理(Error handling)
10.资源池(Resource pooling)
11.同步(Synchronization)
- JDK动态代理最简代码(需要会lambda,反射知识才能看懂)
public static void main(String[] args) { //主方法 ClacInterface myClac = new MyClac(); //被代理的对象 //生成了一个代理类对象proxyBean ClacInterface proxyBean = (ClacInterface)Proxy.newProxyInstance( //第一个参数被代理类的类加载器 myClac.getClass().getClassLoader(), //第二个参数myClac的所以实现接口 myClac.getClass().getInterfaces(), //第三参数是InvocationHandler 这里是lambda简化的匿名内部类写法 (a, b, c) -> { System.out.println("我代理了myClac对象"); return b.invoke(myClac, c); } ); System.out.println("proxyBean.add(1, 3) = " + proxyBean.add(1, 3)); }
//创建接口 public interface ClacInterface { int add(int a ,int b ); } //实现接口类 public class MyClac implements ClacInterface{ @Override public int add(int a, int b) { System.out.println("a+b"+"="+(a+b)); return a+b; } }
- CGlib动态代理代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; import java.util.Arrays; /** * @program: CGLibProxy * @description: cglib的动态代理 * @author: 辰兮要努力 * @create: 2021-10-25 21:05 */ public class CGLibProxy implements MethodInterceptor { // CGlib需要代理的目标对象 private Object targetObject; public Object createProxyObject(Object obj) { this.targetObject = obj; //1.工具类 Enhancer enhancer = new Enhancer(); //2.设置父类 enhancer.setSuperclass(obj.getClass()); //3.设置回调函数 enhancer.setCallback(this); //4.创建子类(代理对象) Object proxyObj = enhancer.create(); return proxyObj; } @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { //模拟一下新增部分业务逻辑 handle(); System.out.println("这是增强方法前......"); System.out.println("获取拦截方法:" + method.getName()); System.out.println("获取方法参数:" + Arrays.toString(args)); System.out.println("MethodProxy:" + methodProxy); Object obj = method.invoke(targetObject, args); System.out.println("这是增强方法后......"); return obj; } private void handle(){ //处理一些业务逻辑 System.out.println("CGLibProxy处理业务逻辑"); } } //创建一个user对象 @Data public class User { private String id; private String name; private Integer age; } //创建一个接口 public interface UserManager { public void addUser(String id, String userName); } //创建如上接口的实现类 public class UserManagerImpl implements UserManager { @Override public void addUser(String id, String password) { System.out.println("调用了UserManagerImpl.addUser()方法!"+id+"-"+password); } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * @program: demo * @description: ProxyTest 测试类 */ public class ProxyTest { public static void main(String[] args) { /** * 优点:基于字节码生成真实对象的子类;运行效率高于JDK 代理;真实对象不需要实现接口 * 缺点:需要额外导入jar包 * * cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理(子类也是动态代理对象) */ UserManager userManagerCGLib = (UserManager)new CGLibProxy().createProxyObject(new UserManagerImpl()); System.out.println("CGLibProxy:"); userManagerCGLib.addUser("1", "chenXI"); } }
2 什么是Spring MVC
-
MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范。
-
是将业务逻辑、数据、显示分离的方法来组织代码。
-
MVC主要作用是降低了视图与业务逻辑间的双向偶合。
-
MVC不是一种设计模式,MVC是一种架构模式。当然不同的MVC存在差异。
Model(模型):数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或JavaBean组件(包含数据和行为),不过现在一般都分离开来:Value Object(数据Dao) 和 服务层(行为Service)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。
View(视图):负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。
Controller(控制器):接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。也就是说控制器做了个调度员的工作。
@Controller注解类型用于声明Spring类的实例是一个控制器
3 SpringMVC执行原理
前端控制器DispatcherServlet(接收请求)-> 调用 处理器映射器HandlerMapping(将请求URL和方法建立关系映射)-> 请求执行Handlder -> 处理器适配器HandlerAdapter(调用具体方法)-> 请求控制器Controller -> 委托Model进行处理(Service和Dao)-> 返回给控制器 -> 返回给视图解析器 ViewResolver -> 返回视图前端控制器DispatcherServlet(响应)
1. 前端控制器 DispatcherServlet(不需要程序员开发) --> 接收请求、响应结果,相当于转发器
2. 处理器映射器HandlerMapping(不需要程序员开发) --> 根据请求的URL来查找Handler
3. 处理器适配器HandlerAdapter --> 按照HandlerAdapter要求的规则去编写,这样适配器HandlerAdapter才可以正确的去执行Handler
4. 处理器Handler(需要程序员开发) --> 按照具体的请求让Controller执行
5. 视图解析器 ViewResolver(不需要程序员开发)
- DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求(Strust2 --> Springboot)
-
HandlerMapping为处理器映射。DispatcherServlet调用 HandlerMapping,HandlerMapping根据请求url查找Handler。
-
HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello。
-
HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。
-
HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。
-
Handler让具体的Controller执行。
-
Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。
-
HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。
-
DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。
-
视图解析器将解析的逻辑视图名传给DispatcherServlet。
-
DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。
-
最终视图呈现给用户。
Model1:
Model2:
SpringMVC
4 Spring bean生命周期
Spring Bean的完整生命周期从创建Spring容器开始,直到最终Spring容器销毁Bean,这其中包含了一系列关键点
5 RestFul风格
Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
资源:互联网所有的事物都可以被抽象为资源
资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。
分别对应 添加、 删除、修改、查询。
传统方式操作资源 :通过不同的参数来实现不同的效果!方法单一,post 和 get
资源
https://www.cnblogs.com/twq46/p/16601237.html