Spring
IOC
IOC概念:(Inversion of Control)控制反转,IOC就是一个对象管理容器,在调用对象时就无需主动new去生成对象,而是又IOC容器提供。
Spring框架实现了这个思想,提供了IOC容器来充当IOC思想的”外部”
IOC容器负责对象的创建,初始化等一些列工作,被创建或者被管理的对象在IOC容器中被称为Bean
DI:(Dependency Injection)依赖注入,在容器中建立Bean与Bean之间的依赖关系的整个过程,称为依赖注入。
现在有一个Service对象,需要运行,那么我需要去容器中取出来这个Service对象,但是Service运行必须依赖Dao对象才可以运行,所以就还得从IOC中取出来Dao对象。这就不是一个一个取出了,而是两个一块取出来,就是一种依赖关系,所以是依赖注入。
IOC主要是一个将创建对象的操作都放在配置文件中,然后通过加载配置文件
导入Spring坐标
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.10.RELEASE</version></dependency></dependencies>
需要有Spring的配置文件,一般命名为applicationContext.xml文件,在这里配置对应类作为Spring管理的bean
当然bean在定义时有一些需要主义的地方,看下面配置文件具体写法。
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 1. 导入spring的坐标spring-context, 对应版本是5.2.10.RELEASE--><!-- 2. 配置beanbean标签表示配置bean, id表示给bean起一个名字, class表示给bean定义类型--><bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/><bean id="bookService" class="com.itheima.service.impl.BookServiceImpl"/></beans>
获取IOC容器
//获取IOC容器ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");//获取beanBookDao bookDao = (BookDao) applicationContext.getBean("bookDao");//(类型强制转换)
注意在获取IOC容器时,一般使用ClassPathXmlApplicationContext(),因为ApplicationContext不是个类,而是接口。

DI
在这里主要就是要删除业务层中使用new的方式创建的dao对象(为了降低耦合度)
不使用new的方式去创建对象,那么就需要提供一个set方法,这是IOC提供的对象进入业务层的方法。
现在配置需要的对象的依赖关系
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/><bean id="bookService" class="com.itheima.service.impl.BookServiceImpl"><!--配置service与dao的关系--><property name="bookDao" ref="bookDao"/> <!--两个bookDao的关系,第一个是指赋值给谁?是指service的一个属性;第二个bookDao是指需要将谁(指一个bean的id)赋值给第一个bookDao--></bean>
搞清楚这个依赖关系,谁依赖谁
Bean
bean的基础配置
属性- id:在容器中id值唯一,用来获取对应的bean
- class:bean的类型,即配置的bean的全路径类名
bean标签中有个name属性,使用来定义bean的别名的,看案例
<bean id="bookDao" name="dao bookDao2, dao2; dao3" class="com.itheima.dao.impl.BookDaoImpl"/>
可以看到,这里的name中的值,我定义了很多个别名,都是可以自定义的,按照自己的命名习惯来。
其中可以很明显的观察到:可以定义很多个类名,然后分隔符可以使用空格/逗号/分号
作用范围spring创建的bean默认是一个单例实例。类似于new的对象都是一个对象,内存地址都一样
用scope可以配置 是否单例,默认值为singleton(单例)换用prototype就会发现生成的对象是不同的对象了,内存中的地址也不一样。
F:默认为单例? Q:如果每用一个就创建一个新的,那么对IOC容器来说,压力也会很大。效率也会更高。 当然也不是全都适合单例的,不然也不会存在这个非单例的类型了,适合交给IOC管理器进行管理的bean都有:表现层对象(Servlet),业务层对象(Service),数据层对象(Dao),工具对象。 不适合交给容器管理的bean:封装实体的域对象 #### bean的实例化 创建bean的三种形式 1. 提供可访问的构造方法(不论public or private)目前最常用Spring创建对象的时候调用的是无参的构造方法,如果没有无参的构造方法,则会报错。
- 静态工厂(了解即可)
创建一个factory.java类
import com.itheima.dao.OrderDao;import com.itheima.dao.impl.OrderDaoImpl;public class OrderDaoFactory {public static OrderDao getOrderDao(){return new OrderDaoImpl();}}
怎么去创建并调用
首先在配置文件中声明
<bean id="orderDaoFactory" class="com.itheima.factory.OrderDaoFactory" factory-method="getOrderDao"/>
这个factory-method是要说明是工厂中的哪个方法来创建对象的。
调用方法去创建对象
OrderDao orderDao = OrderDaoFactory.getOrderDao();orderDao.save();
bean的生命周期
关于从创建到销毁的过程
首先在Impl文件中创建相对应的初始化方法,和销毁方法
//初始化public void init(){System.out.println("init.....");}//销毁public void destory(){System.out.println("destory......");}
然后在配置文件中加上相应的属性说明:init-method和destory-method
<bean id="bookDao" name="dao bookDao2, dao2; dao3" class="com.itheima.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>
一般在程序执行完毕,Java虚拟机都是直接关闭的,所以一般没有机会执行销毁方法
如果注册一个关闭容器的钩子,提醒Java虚拟机在推出前先关闭容器。
registerShutdownHook();//注册关闭容器钩子
另一种Spring自用的生命周期控制方法
调用InitializingBean, DisposableBean 中的两个方法分别是destory()和afterPropertiesSet()
import com.itheima.dao.BookDao;import com.itheima.service.BookService;import org.springframework.beans.factory.DisposableBean;import org.springframework.beans.factory.InitializingBean;public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {private BookDao bookDao;public void save(){System.out.println("book service save .....");bookDao.save();}public void setBookDao(BookDao bookDao) {this.bookDao = bookDao;}@Overridepublic void destroy() throws Exception {System.out.println("service destory.....");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("service init.....");}}
这样就无需在配置文件中添加init-method和destory-method属性了。
依赖注入方式
Setter注入
- 引用类型
setter注入就是在bean中定义引用类型属性并提供可访问的set方法

在配置文件中,使用

- 简单类型
就是需要传入简单的值的时候,不再使用ref属性,ref属性只能是引用一个bean,而传值则使用的value值。
<bean id="bookDao" name="dao" class="com.itheima.dao.impl.BookDaoImpl"><property name="age" value="19"/><property name="name" value="m0re"/></bean>
构造器注入
构造器注入同样是简单类型和引用类型,与Setter类型不一样的地方就是使用的标签不一样,构造器注入使用的标签是constructor-arg,其他基本操作上与Setter注入类似。
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"><constructor-arg name="age" value="19"/><constructor-arg name="name" value="m0re"/></bean>
只不过构造器注入是注入的构造方法,一般构造方法有参数,直接使用name会造成程序耦合度很高,几乎是绑定了。但是现在需要解除耦合,那么就可以使用type属性来不使用具体名字来传值。
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"><constructor-arg type="int" value="19"/><constructor-arg type="java.lang.String" value="m0re"/></bean>
F:但是多个传参,且传入的参数类型是一样的又该怎么操作?
Q:可以使用index=”0”顺序来定义,直接type也不需要了。
总结:使用位置顺序来解决参数类型不匹配的问题
依赖注入方式选择
- 强制依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现
- 可选依赖使用setter注入进行,灵活性强
- 自己开发模块使用setter注入
- ………….
依赖自动装配
自动装配就是不用自己写依赖注入,但是如果是setter注入的话,set方法还是需要自己提供。
多了一个参数autuwire,一般是使用按类型

正确格式
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" autowire="byType"/>
注解开发
注解开发定义bean,在class上面的位置,注解一般使用Component,形式如下
@Component("bookDao")@Repository("bookDao")@Service("bookDao")@Controller("bookDao")
三种注解使用方式完全一样,不一样的仅仅是名字,做标志区分。
然后是纯注解开发使用一个类代替配置文件

@Configuration //表示是配置文件类@ComponentScan("com.itheima") //扫描bean,用于指定扫描路径,并且只能添加一次,如有多个,则写出数组形式@ComponentScan({"com.itheima.service", "com.itheima.dao"})
暂时不写了……..
AOP面向切面编程
AOP案例
package com.itheima.dao;public interface BookDao {public void save();public void update();}
package com.itheima.dao.impl;import com.itheima.dao.BookDao;import org.springframework.stereotype.Repository;@Repositorypublic class BookDaoImpl implements BookDao {public void save(){System.out.println(System.currentTimeMillis());System.out.println("book dao save.....");}public void update(){System.out.println("book dao update.....");}}
package com.itheima.config;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration@ComponentScan("com.itheima")@EnableAspectJAutoProxy//告诉Spring,我使用了注解开发的Beanpublic class SpringConfig {}
package com.itheima.aop;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;import org.springframework.stereotype.Component;@Component//接受Spring控制@Aspect//告诉Spring,我这是AOPpublic class MyAdvice {@Pointcut("execution(void com.itheima.dao.BookDao.update())")private void cut(){}@Before("cut()")public void method(){System.out.println(System.currentTimeMillis());}}
@Pointcut表示添加切点,execution表示执行,参数说明
void:需要添加切点的方法的类型,这里update()在BookDaoImpl中可以看到是void
后面参数表示方法的具体位置
在需要执行的方法前添加@Before()可以在那个方法前执行切点方法
package com.itheima;import com.itheima.config.SpringConfig;import com.itheima.dao.BookDao;import org.springframework.context.ApplicationContext;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class App {public static void main(String[] args) {ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);BookDao bookDao = ctx.getBean(BookDao.class);bookDao.update();}}

AOP表达式
当有多个切入点的时候,就可以通过使用通配符来快速匹配

详细说明
* 表示任意一个..表示任意多个+ 不常用,匹配子类
Spring MVC
请求方式
@RequestMapping("/user")@GetMapping("/user")@PostMapping("/user")
GetMapping()只能接受get请求方式传输的参数
PostMapping()则是只能接收post方式传输的参数
RequestMapping()两种方式都可以接收
@RequestMapping("/user")public class Account {@GetMapping("/data")public void data(@RequestParam("username") String name, @RequestParam("ageId") int age){System.out.println("username"+name+"is"+age+"years old...");System.out.println("this is data.....");}}
两处知识点,路径设置,可以这样子设计。最后实现效果/user/data
参数传递
- 普通传递,也就是上面的那种方式
- POJO参数传递,在User类中,有几个变量就可以传几个参数,会自动绑定。
@RequestMapping("/pojo")@ResponseBodypublic void pojo(User user){System.out.println(user);}
- 嵌套POJO参数,如果存在引用型变量,也可以使用上述方式传输,只不过在前端传参时的形式需要变化。
- 数组传参
@RequestMapping("/array")@ResponseBodypublic void array(String[] likes){System.out.println(likes);}
- 集合传参
@RequestMapping("/list")@ResponseBodypublic void listParam(List<String> service){System.out.println(service);}
日期参数传输
日期的常见三种方式
- 2000/11/11
- 2000-11-11
- 2000/11/11 11:54:04
实现方式
@RequestMapping("/date")@ResponseBodypublic void thedate(Date date,@DateTimeFormat(pattern = "yyyy-mm-dd") Date date1,@DateTimeFormat(pattern = "yyyy/mm/dd HH:mm:ss") Date date2){System.out.println(date);System.out.println(date1);System.out.println(date2);}
@DateTimeFormat实现格式的定义,需要传什么格式的日期,就定义什么格式。
响应
有请求就有响应,响应界面这么写
@RequestMapping("/tojump")public String tojump(){System.out.println("=========");return "page.jsp";}
返回页面数据的话,如上,需要设置类型为String
@RequestMapping("/totext")@ResponseBodypublic String totext(){System.out.println("=========");return "response text";}
返回文本类型的数据,需要设置类型为String,注意@ResponseBody
@RequestMapping("/toPojo")public BookDao pojoPage(){System.out.println("响应pojo对象");BookDao bookDao = new BookDaoImpl();bookDao.update();bookDao.save();return bookDao;}
返回json对象数据
REST开发模式
REST风格,路径传参。
//http://127.0.0.1:8080/user 仅限POST方式提交@RequestMapping(value = "/user", method = RequestMethod.POST)@ResponseBodypublic String save(){System.out.println("user save....");return "{user save}";}//http://127.0.0.1:8080/user/1 仅限DELETE方式提交@RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)@ResponseBodypublic String delete(@PathVariable Integer id){System.out.println("user delete...."+id);return "{user delete}";}
注意第二种,@PathVariable的使用。
在REST实际开发中,注解开发可以使用@RestController代替@Controller和@ResponseBody
@RestController//@Controller//@ResponseBody
然后就是Mapping的各种形式
@PostMapping@GetMapping@PutMapping@DeleteMapping
SSM整合
没必要记录笔记,毕竟我也不学开发,就过一遍,看看他们是怎么进行开发的就可以
拦截器
大概是做权限验证的吧。
Maven
分模块开发,当模块整合时,在maven中的操作是先将要被导入的模块的pom.xml中去查找,注意install是可以将模块打包的。
跳过……
Spring-Boot
Spring-Boot相关漏洞资料:https://github.com/LandGrey/SpringBootVulExploit
关于Spring-Boot的配置文件有三种形式
- application.properties
- application.yml
- application.yaml
三种格式的文件都是spring-boot的配置文件,当三种配置文件同时存在时,优先级依次为<font style="color:#E8323C;">properties>yml>yaml</font>
但是在开发中多使用yml格式。
开启debug需要在配置文件中
debug: true
