lombok安装
当一个类的字段特别多时,整个文件看起来将非常不简洁。所幸IDEA提供了一款lombok插件,可以在代码阶段,通过添加注解的形式,省去手写getter, setter的麻烦。
File - settings
依次点击: Plugins -> Browse repositories -> Lombok -> Install
安装好了以后重启
pom.xml添加依赖
<!-- lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>compile</scope> </dependency>
还是上一节的Cat类,去掉所有的setter和getter方法,还有toString方法。改成这样
@Component @ConfigurationProperties(prefix = "cat" ) @Data public class Cat { private String name; private int sex; private List<String> hobbies; private String nameAndSex; }
多环境切换
实际开发项目的时候,分为多套环境,比如开发环境,测试环境,生产环境。不同环境的配置是不一样的。
spring: profiles: active: dev --- cat: name: 机器猫${random.int[1,100]} #sex: hobbies: - 吃铜锣烧 - 和小咪聊天 - 用竹蜻蜓飞天 nameAndSex: ${cat.name},性别是${cat.sex:男} spring: profiles: dev --- cat: name: Hello Kitty #sex: hobbies: - 不知道 nameAndSex: ${cat.name},性别是${cat.sex:女} spring: profiles: test
用---代表配置文件的分组,profiles的意思是当前环境的名称,在最顶上可以设置实际激活的环境名称。
使用SpringBoot进行web开发
彻底搞定静态资源
先找到这个类:WebMvcAutoConfiguration,在这个jar包里面,还是自动配置
WebMvcAutoConfiguration中有一个 addResourceHandlers 方法,这是自动配置静态资源目录的。
public void addResourceHandlers(ResourceHandlerRegistry registry) { if (!this.resourceProperties.isAddMappings()) { logger.debug("Default resource handling disabled"); } else { this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/"); this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> { registration.addResourceLocations(this.resourceProperties.getStaticLocations()); if (this.servletContext != null) { ServletContextResource resource = new ServletContextResource(this.servletContext, "/"); registration.addResourceLocations(new Resource[]{resource}); } }); } }
先看这个:
if (!this.resourceProperties.isAddMappings()) { logger.debug("Default resource handling disabled"); }
如果isAddMappings为false,就打印默认资源映射路径失效了。isAddMappings方法其实就是返回一个addMappings变量(在WebProperties中)
addMappings的含义就是运行访问静态资源,如果你设置成false,就是禁用所有静态资源映射。
站长在写这篇教程的时候,用的SpringBoot版本为2.5.1,是目前最新的版本。发现和之前的版本比起来,改动还是很大的。翻源码很麻烦,我就直接告诉你结论就行了。
默认的静态资源目录是:
new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
这点和以前是一样的,测试一下
访问什么路径能返回public.js呢?
在WebMvcProperties中,有一个staticPathPattern属性。
默认就是/**,所以,无论你访问什么,都可以被静态资源处理器接受。
启动项目,访问http://localhost:8888/public.js
成功访问,现在我们手动添加一个静态目录。
spring: profiles: test resources: static-locations: [classpath:/my/]
访问http://localhost:8888/my.txt,也成功了。
最后,把静态资源开关关掉。
spring: profiles: test resources: static-locations: [classpath:/my/] add-mappings: false
这样就访问不到任何静态资源了,不过一般来说不用关。
再谈static-locations
static-locations表示自定义静态目录,如果配置了这个属性,默认的静态资源目录就会失效!
也可以用这个配置来访问本地资源
spring: profiles: test resources: static-locations: file:C:/upload/article/ add-mappings: true
file:表示访问本地文件。
比如我现在要访问1.jpg
重启项目,访问 http://localhost:8888/20210415/1.jpg ,可以成功访问。
但是,其他静态资源就访问不了了。因为我们设置了static-locations,是一个覆盖操作,默认的目录都没了。
像访问这种本地文件的情况,一般是文件上传和下载的目录,这种的都是放在本地磁盘的,不会和项目绑定。
如果原来的目录我们也想要获取,又要访问本地文件该咋办呢?这个时候,就不要去配置static-locations,我们可以额外配置一个资源映射。
注释掉,正常情况下,用默认的资源映射绰绰有余了。难道那么多文件夹还不够你放资源吗。。。
(注意:上图中的resources也要注释掉,不然会报错)
然后,新建一个配置类。
package com.java18.vipmgr.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class MyWebResourcesHandler implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/upload/**") .addResourceLocations("file:C:/upload/article/"); } }
重启,访问http://localhost:8888/upload/20210415/1.jpg就能看到图片了,并且也不会影响原来的资源目录。这才是项目中推荐的做法。
SpringBoot整合JDBC
添加jdbc依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency>
mysql依赖本来就有:
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>
修改yml配置:
spring: profiles: test #resources: #static-locations: file:C:/upload/article/ #add-mappings: true #配置数据源 datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/idea?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC username: root password:
默认用的是mysql8.x的驱动包,url要注意加上时区,不然会报错的。
测试数据源是否加载成功:
@SpringBootTest class DataTests { @Autowired DataSource dataSource; @Test void dataSource() { System.out.println(dataSource.getClass()); } }
打印:class com.zaxxer.hikari.HikariDataSource
这是springboot默认的数据源。
测试sql语句查询
@Test void dataSource() { //System.out.println(dataSource.getClass()); List<Map<String, Object>> users = jdbcTemplate.queryForList("select * from users"); System.out.println(users); }
结果:[{id=1, username=zhangsan, password=123, points=1000}]
数据库:
举一反三:
1.为什么jdbcTemplate能直接用?
因为SpringBoot有自动配置,条件是:
@ConditionalOnClass({DataSource.class, JdbcTemplate.class}) @ConditionalOnSingleCandidate(DataSource.class)
DataSource已经配好了,JdbcTemplate因为引入了spring-boot-starter-jdbc,肯定也是有的。所以就直接自动配置了。
再看JdbcTemplateConfiguration:
SpringBoot整合Druid数据源
首先帮大家理清几个概念,啥是数据源?
数据源就是连接池,啥是连接池?
我们正常写jdbc代码,不是要获取连接,用完再关闭连接吗。一开一关,是不是很影响性能啊!
既然如此,我们为什么不在一开始就生成假如20个jdbc连接呢?你要用就给你一个,用完你再还回来,岂不美哉!
druid就是阿里公司针对jdbc自己封装的一套连接池代码,说白了就是一个jar包,里面有一些类。
所以:
Druid数据源
= 一个jar包
= 一个dependency
好了,明白这些概念后,我们开始整合Druid数据源。
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.18</version> </dependency>
注意,每次导入新的依赖,都要右键项目,maven,reload一下,有的idea是reimport。
然后,在application.yml配置文件中修改默认的数据源配置。
#配置数据源 datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/idea?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC username: root password: type: com.alibaba.druid.pool.DruidDataSource
就是加一个type属性,如果不加则用的是默认的数据源。
druid还有一些其他配置,直接贴上去,和type是平级的。
initialSize: 5 minIdle: 5 maxActive: 20 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: SELECT 1 FROM DUAL testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙 filters: stat,wall,log4j maxPoolPreparedStatementPerConnectionSize: 20 useGlobalDataSourceStat: true connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
重点:编写配置类,开启sql监控
package com.java18.vipmgr.config; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.support.http.StatViewServlet; import com.alibaba.druid.support.http.WebStatFilter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @Configuration public class DruidConfig { /** * 用ConfigurationProperties的方式装配Druid对象 * @return */ @ConfigurationProperties(prefix = "spring.datasource") @Bean public DataSource druid(){ return new DruidDataSource(); } //配置Druid的监控 //其实就是相当于在web.xml中配置一个管理后台的Servlet //这个Servlet开启后可以访问后台页面,映射地址为/druid/* @Bean public ServletRegistrationBean statViewServlet(){ /** * Druid内置提供了一个StatViewServlet用于展示Druid的统计信息。 * 这个StatViewServlet的用途包括: * 提供监控信息展示的html页面 * 提供监控信息的JSON API */ ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*"); Map<String,String> initParams = new HashMap<>(); //这里是配置管理员的账号密码,写死即可 initParams.put("loginUsername","admin"); initParams.put("loginPassword","123456"); initParams.put("allow","");//默认就是允许所有访问 initParams.put("deny","192.168.x.x"); //这是默认禁止某个IP访问 bean.setInitParameters(initParams); return bean; } //2、配置一个web监控的filter @Bean public FilterRegistrationBean webStatFilter(){ FilterRegistrationBean bean = new FilterRegistrationBean(); bean.setFilter(new WebStatFilter()); Map<String,String> initParams = new HashMap<>(); initParams.put("exclusions","*.js,*.css,/druid/*"); bean.setInitParameters(initParams); bean.setUrlPatterns(Arrays.asList("/*")); return bean; } }
为了方便测试,我们加一个Controller
package com.java18.vipmgr.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; import java.util.Map; @RestController @RequestMapping("user") public class UserController { @Autowired JdbcTemplate jdbcTemplate; @GetMapping("getAll") public List<Map<String,Object>> getAll(){ return jdbcTemplate.queryForList("select * from users"); } }
注意,这边有个小坑,因为我们用了druid的监控功能,会默认打印日志,于是就需要引入log4j。
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
启动项目,访问http://localhost:8888/user/getAll,可以查询数据。然后再访问 http://localhost:8888/druid
输入账号密码就可以进入监控页面啦
可以查看各条sql的运行情况,这就是为什么使用Druid的原因啦。