Spring核心与MVC笔记
前言
现在已经很少有新项目不使用SpringBoot而使用基础的、原始的Spring框架以及SpringMVC,但SpringBoot又会需要这些“老东西”的概念,故重新整理SpringBoot的“前辈”相关笔记并合并,主要还是对概念的记录。
Spring IOC
IOC意为控制反转,简单理解为将对象的创建(new)行为由程序员转为由容器执行,程序员只需要在任意要用的地方“注入”。
基于注解定义Bean
因为只是记录原理,故不记录如何在配置文件中启用Bean扫描。
因为现在新项目或者有头脑的Leader迁移到SpringBoot之后基本不会去单独使用这原始的Spring。
定义Bean
- 在类前加上注解@Component, @Service, @Controller, @Repository
四者功能相同,日后可能不同,并且用于约定区分不同类型的Bean并且用于过滤器过滤。
使用@Scope设定作用域:
singleton
默认的scope,表示单例模式。
prototype
一般的new模式,适合有状态要独立的Bean。
request
类似prototype但只在每个http请求(线程或控制器)中独立的。
session
类似prototype但只在每个会话(线程或控制器)中独立的。
- 在类前加上注解@Component, @Service, @Controller, @Repository
注入
构造函数注入
类前添加了Bean声明注解的,构造函数会自动注入类所需成员。
Setter注入
在成员的Setter方法前添加@Autowired,将会注入。
直接注入
在类的成员变量上添加
@Autowired或@Resource,将会注入。
参数注入
固定参数注入
在类成员变量上添加@Value注解
配置文件参数注入
别问为什么没用也别学
XML配置方式繁杂且基本不会去使用,故不记录
Spring AOP
面向切面编程,简单理解为在某个类的某个方法执行的前、后等时刻基于额外操作,也能够拦截传入的参数。
使用得并不多,但很有用。
基本概念
后面所说的通知类,指通常所说的代理Proxy类
连接点:类中可以被增强(代理)的方法
切入点:实际上被增强的连接点
通知:增强部分的代码
- 前置通知、后置通知:方法执行前或后的增强
- 环绕通知:前和后都增强
- 异常通知:出现异常时处理
- 最终通知:无论如何都会最后执行的(try后的finally
切面:把通知应用到切入点的过程(织入、执行
基于注解使用AOP
不使用SpringBoot的话,实际上需要在配置文件中开启扫描,忽略同上。
但在SpringBoot中使用AOP要另外引入Starter!
通知类前添加@Aspect注解
同时,通知类与要增强的类(AOP受体)均要为Bean。
通知方法前加上注解
注解 用途 @Before 前置通知,在连接点前执行 @AfterReturning 连接点正常执行后通知,没有抛出错误时执行 @AfterThrowing 连接点抛出错误时执行 @After 无论有没有抛出错误都在连接点结束后执行(finally) @Around 在@Before前和没有抛出错误结束后都执行 通知方法的顺序
@Around前 –>
@Before –>
切入点(本体)–>
@AfterReturning/@AfterThrowing –>
@Around后
不同版本可能会有不同
通知的参数语法(切入点选择)
- execution(* 包.类.方法(参数类型表))
指定为这个方法 - execution(* 包.类.*(..两个点表示任意))
指定为这个类的所有方法 - execution(* 包..(..))
指定为这个包下所有类的所有方法(当然也可指定所有类的某个方法 - execution(* 包...(..))
在上一个的基础上,一同搜索子包里的 - execution(* *A(..))
所有以“A”结尾的方法 - within(包.*)
包内的所有接入点,也可双点搜索子包
Spring AOP Only - this/target(接口全路径)
实现了这个接口的类的接入点
this: 匹配不到被重写了的接口中的方法
target: 全部 - 相关功能注解
- @Target(注解类)
同target execution用法 - @Annotation(注解类)
所有含有这个注解的方法(接入点) - @Within(注解类)
同this execution用法 - @Order(优先级,小的优先)
多个通知同时作用于一个切入点时控制通知链的内部的顺序
- @Target(注解类)
- 抽取公共(复用)切入点
在通知类中对某个方法使用@Pointcut选择切入点,其他通知的参数写上该方法名
- execution(* 包.类.方法(参数类型表))
Spring MVC
简化了万恶的Servlet。
原理
工作流程如图:
- 当接收到用户的请求时,请求进入到DispatcherServlet进行处理
- DispatcherServlet根据请求的URL从HandlerMapping获取映射的处理请求的Bean,也就是Controller
- 通过HandlerAdapter调用Controller(应该是适配处理了数据转换),Controller内部处理业务
- Controller返回ModelAndView(Model相当于请求响应参数,View是指定要跳转的视图)
- ViewResolver根据返回的指定的View(可能没有)进行跳转
配置
同上述IOC、AOP中的情况,SpringMVC配置一样很繁琐,甚至还要依赖web.xml,现在已经没有多少项目使用(就是使用你也不怎么用动配置文件或者百度一下就能轻松知道。
用配置文件配置控制器已经要被扫进垃圾桶辣!
通过注解实现控制器
类加上注解@RestController
- 相当于@Controller + @ResponseBody
- @ResponseBody表示这个方法返回的字符串直接写到响应内容
控制器类的每个http接口需要@RequestMapping, @GetMapping, @PostMapping等
返回数据与重定向
- RestController的return直接返回对应数据给前端
数据与重定向(ModelAndView)
- 返回值的ModelAndView将Model(给View的数据)和View(指定跳转的视图)返回给DispatcherServlet(经Adapter)
- ModelAndView通过.addObject()等方法添加参数(类似基本Servlet向请求或响应中setAttribute),通过.setViewName()指定跳转的视图
- 如果需要Model则在方法参数列表声明(org.springframework.ui.)Model变量
返回字符串的方法会将Model转发 - 参数列表的ModelMap
与Model或ModelAndView相比就是个HashMap和简化出常用方法的区别
直接重定向 (非RestController)
若没有在XML或配置类中配置ViewResolver,实际上能够在return视图的名称时直接指定,也可以使用前缀指定是转发还是重定向:1
2
3
4
5//转发
return "/your-path/page.jsp";
return "forward:/sbv/sss.jsp";
//重定向
return "redirect:/aaaa.jsp";- 转发是指带着请求的参数到下一个地方去
- 重定向是客户端浏览器自己进行跳转的行为(相当于用户自己重新访问新页面
重定向无法访问WEB-INF
传入的HTTP参数
一般参数传入,非Restful(…/method?param=value&…)
获取参数
1
2@RequestMapping("/echo")
public ModelAndView handleRequest(String msg) throws Exception {}中,当使用”…/echo?msg=xxx”访问时能正确获得msg参数。
当url中参数名和方法参数表变量名不一致时,可在方法参数前加@RequesParam(“url中的实际名称”)来指定,如:
1
2@RequestMapping("/echo")
public ModelAndView handleRequest(@RequestParam("message") String msg) throws Exception {}此时使用”…/echo?message=xxx”访问能正确填充msg。
组成成对象
当传入的参数可以组成一个类(并且名字与类属性一一对应)时,可以直接把类写到参数,如:
1
2
3
4
5@RequestMapping("/echo")
public ModelAndView handleRequest(User user) throws Exception {}
/*
User: int id; string name;
*/此时使用”…/echo?id=xxx&name=xxx”访问能正确填充user。
Restful参数传入
HTTP接口方法可在参数列表使用@PathVariable获取url参数。
@RequestMapping中需要注明参数名像:
@RequstMapping("/map/{varA}/{varB}")
然后对参数表中的参数注解如:@PathVariable("varA") String bbb
如果RequestMapping中的参数名称和方法参数表得到相同可省略@PathVariable的参数。
@RequestMapping中可以指定method为GET/PUT/POST/DELETE,或直接使用@GetMapping/@PostMapping等。