java笔记3-Spring应用
主要学习:(93条消息) Java之spring新手教程(包教包会)_卿乌的博客-CSDN博客_java spring教程
1.Sping应用的核心
1.概念
Spring是一个开源框架,是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
多用于服务器端的开发。
2.核心
1.控制反转:当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。促进了松耦合。
但在 Spring 应用中,Java 对象创建的控制权是掌握在 IoC 容器手里的,其大致步骤如下。
- 开发人员通过 XML 配置文件、注解、Java 配置类等方式,对 Java 对象进行定义,例如在 XML 配置文件中使用 标签、在 Java 类上使用 @Component 注解等。
- Spring 启动时,IoC 容器会自动根据对象定义,将这些对象创建并管理起来。这些被 IoC 容器创建并管理的对象被称为 Spring Bean。
- 当我们想要使用某个 Bean 时,可以直接从 IoC 容器中获取(例如通过 ApplicationContext 的 getBean() 方法),而不需要手动通过代码(例如 new Obejct() 的方式)创建。
IoC 带来的最大改变不是代码层面的,而是从思想层面上发生了“主从换位”的改变。原本调用者是主动的一方,它想要使用什么资源就会主动出击,自己创建;但在 Spring 应用中,IoC 容器掌握着主动权,调用者则变成了被动的一方,被动的等待 IoC 容器创建它所需要的对象(Bean)。
2.面向切面:Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。
面向切片编程(AOP—Aspect Oriented Programming)可以说是对OOP(面向对象编程)的补充和完善,面向对象就是将事物的特性和行为抽象为一个对象,如people类有身高、体重、年龄等属性,也有吃饭、睡觉等行为。把这些特性和行为封装成一个类,然后可以统一调用。面向切片也可以举个例子,比如people类有自己的属性和行为,但是有小一部分人生病要去医院看病,看病这个业务逻辑就不属于哪一个类,因为people泛指所有人,所有人不会都看病。AOP就是把医院看病这一个业务逻辑功能抽取出来,然后动态把这个功能切入到需要的方法(或行为)中,需要的才切入,这样便于减少系统的重复代码,降低模块间的耦合度。常用到AOP的就是安全校验、日志操作、事务操作等,给你先定义好,然后在想用的地方用,这样不会影响已经在务器运行的项目,然后又能注入新功能,灵活。我们开发dao->service->controller是纵向的,这个AOP就是横向切入,如横向切入一个日志Log,打印执行过程。
理解:切面 = 通知 + 连接点 + 切入点。通知把控切入位置,前面还是后面,切点就是要切入的具体内容
Spring AOP支持的五种类型通知:
1.前置通知
2.正常返回通知
3.异常返回通知
4.返回通知
5.环绕通知
1 2 3 4 5 6 7 8 9
| <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
|
2.Spring应用知识点
1.Bean定义
由Spring IoC容器管理的对象称为Bean,Bean根据Spring配置文件中的信息创建。配置文件支持两种格式:XML文件格式Propertie文件格式(以key-value)键值对的形式存在。
XML格式的配置文件,根元素是<beans>
。该元素的多个子元素<bean>
,每一个定义了一个Bean,并描述了Bean是如何被装配到Spring容器中。
一个样例:
1 2 3 4 5 6 7 8 9 10
| <?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-3.0.xsd">
<bean id="helloWorld" class="net.biancheng.c.HelloWorld"> <property name="message" value="Hello World!"/> </bean> </beans>
|
2.Bean属性注入
Spring通过构造函数注入和setter注入两种方式实现将属性注入到Bean的过程。
1.构造函数注入
构造函数注入:在<bean>
元素使用<constructor-arg>
元素,对构造函数内的属性进行赋值。
例子:
一个Student的类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package net.biancheng.c; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class Student { private static final Log LOGGER = LogFactory.getLog(Student.class); private int id; private String name; private Grade grade; public Student(int id, String name, Grade grade) { LOGGER.info("正在执行 Course 的有参构造方法,参数分别为:id=" + id + ",name=" + name + ",grade=" + grade); this.id = id; this.name = name; this.grade = grade; } @Override public String toString() { return "Student{" + "id=" + id + ", name='" + name + '\'' + ", grade=" + grade + '}'; } }
|
主类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package net.biancheng.c; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainApp { private static final Log LOGGER = LogFactory.getLog(MainApp.class); public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml"); Student student = context.getBean("student", Student.class); LOGGER.info(student.toString()); } }
|
配置文件
1 2 3 4 5 6 7 8 9 10 11
| <?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-3.0.xsd"> <bean id="student" class="net.biancheng.c.Student"> <constructor-arg name="id" value="2"></constructor-arg> <constructor-arg name="name" value="李四"></constructor-arg> <constructor-arg name="grade" ref="grade"></constructor-arg> </bean> </beans>
|
2.setter注入
通过Bean的setter方法属性值注入到Bean的属性中。大致步骤如下:
- 在 Bean 中提供一个默认的无参构造函数(在没有其他带参构造函数的情况下,可省略),并为所有需要注入的属性提供一个 setXxx() 方法;
- 在 Spring 的 XML 配置文件中,使用
<beans>
及其子元素 <bean>
对 Bean 进行定义;
- 在
<bean>
元素内使用<property>
元素对各个属性进行赋值。
3.bean继承
如果父Bean的abstract属性值为true,表明这个Bean是抽象的,抽象的父Bean只能座位模板被子Bean继承,不能实例化,也不能被其他Bean引用,父Bean的定义中,既可以指定class属性,也可以不指定class属性,如果父Bean定义没有明确指定class属性,父Bean的abstract属性必须为true。
3.Spring Boot框架
1.controller
1.新建controller
在package下新建一个controller的包,包中可以添加不同路由的响应函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package com.yongxingsec.lytask2.controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController;
@RestController public class WelcomeController { @ResponseBody @RequestMapping("/hello") public String Welcome() { return "Welcome to Ly server!"; } }
|
2.处理json对象
SpringBoot框架可以将自定义的一般对象,List,Map自动转为JSON数据包返回。
如果我自定义了一个JSON响应数据包,(可能)要在自定义类的JSON响应包里补充get private变量的方法。
2.http调用
Springboot项目想要调用http请求,需要先导入相关依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.4.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.2</version> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
|
其次在启动类同一个包下创建一个RestTemplateConfig.java类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.web.client.RestTemplate;
@Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate(ClientHttpRequestFactory factory){ return new RestTemplate(factory); } @Bean public ClientHttpRequestFactory simpleClientHttpRequestFactory(){ SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); factory.setConnectTimeout(15000); factory.setReadTimeout(5000); return factory; } }
|
最后就可以执行相关调用函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| import com.alibaba.fastjson.JSONObject; import com.swordfall.model.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.*; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate;
@Service public class RestTemplateToInterface { @Autowired private RestTemplate restTemplate;
public User doGetWith1(String url){ ResponseEntity<User> responseEntity = restTemplate.getForEntity(url, User.class); User user = responseEntity.getBody(); return user; }
public User doGetWith2(String url){ User user = restTemplate.getForObject(url, User.class); return user; }
public String doPostWith1(String url){ User user = new User("小白", 20); ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, user, String.class); String body = responseEntity.getBody(); return body; }
public String doPostWith2(String url){ User user = new User("小白", 20); String body = restTemplate.postForObject(url, user, String.class); return body; }
public String doExchange(String url, Integer age, String name){ HttpHeaders headers = new HttpHeaders(); String token = "asdfaf2322"; headers.add("authorization", token); headers.setContentType(MediaType.APPLICATION_JSON); JSONObject obj = new JSONObject(); obj.put("age", age); obj.put("name", name); HttpEntity<JSONObject> request = new HttpEntity<>(obj, headers); ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, request, String.class); String body = responseEntity.getBody(); return body; } }
|