1 spring的发展
1.1 Spring1.x
在Spring1.x时代,都是通过xml文件配置bean,随着项目的不断扩大,需要将xml配置放到不同的配置文件中,需要频繁的在Java文件和xml文件中切换
1.2 Spring2.x
在Spring2.x时代,jdk1.5支持注解,可以使用注解对bean进行声明和注入,大大的减小了xml配置文件,简化了项目开发
那么,问题来了,究竟是应该使用xml还是注解呢?
1 应用的基本配置用xml,比如:数据源、资源文件等;
2业务开发用注解,比如:Service中注入bean等;
1.3 Spring3.x到Spring4.x
从Spring3.x开始提供了Java配置方式,使用Java配置方式可以更好的理解你配置的Bean,现在我们就处于这个时代,并且Spring4.x和Spring boot都推荐使用java配置的方式。
2 Spring的Java配置方式
Java配置是Spring4.x推荐的配置方式,可以完全替代xml配置。
2.1 @Configuration 和 @Bean
@Configuration作用于类上,表示该类是一个配置文件。
@Bean作用于方法上,相当于xml中的<bean>
2.2 示例
该示例演示了通过Java配置的方式进行配置Spring,并且实现了Spring IOC功能。
2.2.1创建工程以及导入依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.itcast.springboot</groupId>
<artifactId>itcast-springboot</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.jolbox</groupId>
<artifactId>bonecp-spring</artifactId>
<version>0.8.0.RELEASE</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<!-- 资源文件拷贝插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- java编译插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<!-- 配置Tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
2.2.2 编写User对象
public class User {
private String username;
private String password;
private Integer age;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
2.2.3编写UserDAO 用于模拟与数据库的交互
public class UserDAO {
public List<User> queryUserList(){
List<User> result = new ArrayList<User>();
// 模拟数据库的查询
for (int i = 0; i < 10; i++) {
User user = new User();
user.setUsername("username_" + i);
user.setPassword("password_" + i);
user.setAge(i + 1);
result.add(user);
}
return result;
}
}
2.2.4 编写UserService 用于实现User数据操作业务逻辑
@Service
public class UserService {
@Autowired // 注入Spring容器中的bean对象
private UserDAO userDAO;
public List<User> queryUserList() {
// 调用userDAO中的方法进行查询
return this.userDAO.queryUserList();
}
}
2.2.5 编写SpringConfig 用于实例化Spring容器
@Configuration //通过该注解来表明该类是一个Spring的配置,相当于一个xml文件
@ComponentScan(basePackages = "cn.itcast.springboot.javaconfig") //配置扫描包
public class SpringConfig {
@Bean // 通过该注解来表明是一个Bean对象,相当于xml中的<bean>
public UserDAO getUserDAO(){
return new UserDAO(); // 直接new对象做演示
}
}
2.2.6 编写测试方法 用于启动Spring容器
public class Main {
public static void main(String[] args) {
// 通过Java配置来实例化Spring容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
// 在Spring容器中获取Bean对象
UserService userService = context.getBean(UserService.class);
// 调用对象中的方法
List<User> list = userService.queryUserList();
for (User user : list) {
System.out.println(user.getUsername() + ", " + user.getPassword() + ", " + user.getPassword());
}
// 销毁该容器
context.destroy();
}
}
3 SpringBoot实战
3.1 读取外部配置文件,@PropertySource,通过@value注解获取值
@Configuration //通过该注解来表明该类是一个Spring的配置,相当于一个xml文件
@ComponentScan(basePackages = "cn.itcast.springboot.javaconfig") //配置扫描包
@PropertySource(value= {"classpath:jdbc.properties","xxx"},ignoreResourceNotFound=true)
public class SpringConfig {
@Value("${jdbc.url}")
private String jdbcUrl;
@Bean // 通过该注解来表明是一个Bean对象,相当于xml中的<bean>
public UserDAO getUserDAO(){
return new UserDAO(); // 直接new对象做演示
}
}
3.2 配置数据库连接池
pom.xml中导入依赖
<!-- 连接池 -->
<dependency>
<groupId>com.jolbox</groupId>
<artifactId>bonecp-spring</artifactId>
<version>0.8.0.RELEASE</version>
</dependency>
以前的spring.xml配置
<!-- 定义数据源 -->
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource"
destroy-method="close">
<!-- 数据库驱动 -->
<property name="driverClass" value="${jdbc.driverClassName}" />
<!-- 相应驱动的jdbcUrl -->
<property name="jdbcUrl" value="${jdbc.url}" />
<!-- 数据库的用户名 -->
<property name="username" value="${jdbc.username}" />
<!-- 数据库的密码 -->
<property name="password" value="${jdbc.password}" />
<!-- 检查数据库连接池中空闲连接的间隔时间,单位是分,默认值:240,如果要取消则设置为0 -->
<property name="idleConnectionTestPeriod" value="60" />
<!-- 连接池中未使用的链接最大存活时间,单位是分,默认值:60,如果要永远存活设置为0 -->
<property name="idleMaxAge" value="30" />
<!-- 每个分区最大的连接数 -->
<!--
判断依据:请求并发数
-->
<property name="maxConnectionsPerPartition" value="100" />
<!-- 每个分区最小的连接数 -->
<property name="minConnectionsPerPartition" value="5" />
</bean>
现在的Java配置
@Value("${jdbc.url}")
private String jdbcUrl;
@Value("${jdbc.driverClass}")
private String jdbcDriverClassName;
@Value("${jdbc.username}")
private String jdbcUsername;
@Value("${jdbc.password}")
private String jdbcPassword;
public DataSource dataSource(){
BoneCPDataSource boneCPDataSource=new BoneCPDataSource();
// 数据库驱动
boneCPDataSource.setDriverClass(jdbcDriverClassName);
// 相应驱动的jdbcUrl
boneCPDataSource.setJdbcUrl(jdbcUrl);
// 数据库的用户名
boneCPDataSource.setUsername(jdbcUsername);
// 数据库的密码
boneCPDataSource.setPassword(jdbcUsername);
// 检查数据库连接池中空闲连接的间隔时间,单位是分,默认值:240,如果要取消则设置为0
boneCPDataSource.setIdleConnectionTestPeriodInMinutes(60);
// 连接池中未使用的链接最大存活时间,单位是分,默认值:60,如果要永远存活设置为0
boneCPDataSource.setIdleMaxAgeInMinutes(30);
// 每个分区最大的连接数
boneCPDataSource.setMaxConnectionsPerPartition(100);
// 每个分区最小的连接数
boneCPDataSource.setMinConnectionsPerPartition(5);
return boneCPDataSource;
}
SpringBoot快速入门
3.2.1 设置spring boot的parent
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
说明:Spring boot的项目必须要将parent设置为spring boot的parent,该parent包含了大量默认的配置,大大简化了我们的开发
3.2.2 导入spring boot的web支持
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
3.2.3编写第一个Spring Boot的应用
@Controller
@SpringBootApplication
@Configuration
public class HelloApplication {
@RequestMapping("hello")
@ResponseBody
public String hello(){
return "hello world!";
}
public static void main(String[] args) {
SpringApplication.run(HelloApplication.class, args);
}
代码说明:
1、@SpringBootApplication:Spring Boot项目的核心注解,主要目的是开启自动配置。;
他是一个组合注解,包含了@Configuration
@EnableAutoConfiguration 根据类路径中的jar依赖为当前项目进行自动配置,如添加了spring-boot-starter-web依赖,会自动添加Tomcat和SpringMVC的依赖,springBoot对Tomcat和springmvc进行自动配置
@ComponentScan:不写的话默认扫描@SpringBootApplication所在类的同级目录以及它的子目录,主要来扫描controller,如果controller不在@SpringBootApplication的同级目录中,用@ComponentScan("controller的包名"),如果只用@SpringBootApplication需要用@SpringBootApplication(scanBasePackages = "包名")来指定controller的位置
2、@Configuration:这是一个配置Spring的配置类;
3、@Controller:标明这是一个SpringMVC的Controller控制器;
4、main方法:在main方法中启动一个应用,即:这个应用的入口;
4 springboot 核心
4.1 全局配置文件,名字必须是application.properties或者applicatio.yml
修改默认端口号server.port=8088
修改请求路径后缀server.servlet-path=*.do
修改项目访问根目录server.servlet.context-path=/ww
4.2 获取自定义配置的值
在application.properties中的自定义配置如
book.author=张三
book.name=springboot
要获取属性值使用@Value注解,把属性值给一个变量
@Value("${book.author}")
private String author,这样author就获得了属性的值
4.3 类型安全的配置(简化4.2中的配置)
如果有很多自定义的配置,且这些配置的前缀相同,可以使用@ConfigurationProperties(prefix=“book”)来实现
prefix中写上前缀
@ConfigurationProperties(prefix=“book”)注解要写在类上
定义一个变量名字和自定义的属性名相同,如private String name,用name来接收book.name的值,private String author来接收book.author的值
要为name和author变量提供get set方法
4.4 profile用来在不同的环境切换不同的全局配置文件
1 有三个全局配置文件application-dev.properties application-test.properties application.properties
在application.properties 用spring.profiles.active=test表示使用application-test.properties 配置文件
spring.profiles.active=dev表示使用application-dev.properties 配置文件
4.5 springboot自动配置原理
springbootApplication在初始化的时候会加载spring-boot-autoconfigure下的META-INF/spring.factories文件,
根据文件中的路径名字,找到相关的class文件
当
当满足红框出的条件即存在EnableAspectJAutoProxy.class, Aspect.class, Advice.class, AnnotatedElement.class时就实例化AopAutoConfiguration,然后进行AopAutoConfiguration类的相关属性设置
4.6responseBody使用该注解表示该方法的返回结果直接写入 HTTP response body 中 一般在异步获取数据时使用,不使用该注解就直接进行页面跳转
4.7
@RequestMapping("/info/{msg}")
public String show(@PathVariable String msg){
return "show"+msg;
}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
实际开发过程中不需要添加该依赖
springboot的日志级别有7个 级别从低到高为 trace debug info warn error fatal off
如果设置为warn,则低于warn级别的信息不回输出
springboot默认配置error warn info 级别的日志输出到控制台
4.8 自定义拦截器
1 创建一个类实现HandlerInterceptor接口,重写接口的方法,在类上添加@Configuration注解表示这是一个配置类
2
package com.lyf.interceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//声明这是一个配置类,还要在springboot中添加这个类的包名,让主程序能够扫描到它
@Configuration
public class myInterceptor extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//自定义自己的拦截器
HandlerInterceptor interceptor= new HandlerInterceptor() {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("自定义拦截器123");
System.out.println(request.getRequestURI());
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
};
//添加自己定义的拦截器,并设置拦截的路径,/**表示拦截所有
registry.addInterceptor(interceptor).addPathPatterns("/**");
}
}
4.9 全局异常处理器
1 写一个全局异常处理类,主要是捕获异常,用@ControllerAdvice进行捕获controller层异常,@ExceptionHandler(Exception.class)表示处理Exception类异常,而不是RuntimeException,写一个方法传入exception来处理异常信息
package com.lyf.myspringboot;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;
//用于全局异常处理,减少代码入侵,必须在controller层抛出来,若异常在代码中被抓住了,没有抛出来,是不起作用的。
@ControllerAdvice
public class GlobalExceptionController {
//value表示要捕捉的异常
@ExceptionHandler(Exception.class)
@ResponseBody
public Map<String,Object> handlerException(Exception e){
Map<String,Object> map=new HashMap<>();
map.put("errorcode",500);
//添加异常信息
map.put("errormsg",e.toString());
return map;
}
}
package com.lyf.myspringboot;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ExceptionController {
@RequestMapping("/ee")
public String exception(){
int a=5/0;
return "exception";
}
}
4.10 springboot配置数据源
springboot默认支持四种数据源类型:
org.apache.tomcat.jdbc.pool.DataSource
com.zaxxer.hikari.HikariDataSource
org.apache.commons.dbcp.BasicDataSource
org.apache.commons.dbcp2.BasicDataSource
对于这4种数据源,当 classpath 下有相应的类存在时,Springboot 会通过自动配置为其生成DataSource Bean,DataSource Bean默认只会生成一个,四种数据源类型的生效先后顺序如下:Tomcat--> Hikari --> Dbcp --> Dbcp2
在Springboot 使用JDBC可直接添加官方提供的 spring-boot-start-jdbc 或者 spring-boot-start-data-jpa 依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
在application.properties中进行数据源相关配置
# application.properties文件中添加如下配置:
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=123456
用户名必须是username,不能用name,否则数据库无法连接
在controller中注入service时,用了@Autowired注解后,如果controller所在类不在springboot启动类所在目录或子目录,还要在springboot启动类中添加controller所在包扫描
@SpringBootApplication(scanBasePackages = {"com.lyf.controller","com.lyf.GloableException","com.lyf.service"})
mybatis mapper接口类要单独扫描@MapperScan("com.lyf.mapper")