一、springboot整合jdbc

1.1、导入的maven依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-jdbc</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>mysql</groupId>
  7. <artifactId>mysql-connector-java</artifactId>
  8. <scope>runtime</scope>
  9. </dependency>

1.2、配置相关数据源:

  1. spring:
  2. datasource:
  3. username: root
  4. data-password: 123456
  5. url: jdbc:mysql://47.104.128.12:3306/test
  6. driver-class-name: com.mysql.jdbc.Driver

1.3、测试

  1. @Autowired
  2. private DataSource dataSource;
  3. @Test
  4. public void contextLoads() {
  5. }
  6. @Test
  7. public void testDbType() {
  8. System.out.println("自动装配数据源的类型:"+dataSource.getClass());
  9. }

1.4、jdbc 以及数据源的自动装配原理

1.4.1)数据源的自动装配

  1. /**
  2. * Tomcat Pool DataSource configuration.
  3. */
  4. @ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class)
  5. @ConditionalOnMissingBean(DataSource.class)
  6. @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.tomcat.jdbc.pool.DataSource", matchIfMissing = true)
  7. static class Tomcat {
  8. //配置tomcat 连接池的数据源
  9. @Bean
  10. @ConfigurationProperties(prefix = "spring.datasource.tomcat")
  11. public org.apache.tomcat.jdbc.pool.DataSource dataSource(
  12. DataSourceProperties properties) {
  13. org.apache.tomcat.jdbc.pool.DataSource dataSource = createDataSource(
  14. properties, org.apache.tomcat.jdbc.pool.DataSource.class);
  15. DatabaseDriver databaseDriver = DatabaseDriver
  16. .fromJdbcUrl(properties.determineUrl());
  17. String validationQuery = databaseDriver.getValidationQuery();
  18. if (validationQuery != null) {
  19. dataSource.setTestOnBorrow(true);
  20. dataSource.setValidationQuery(validationQuery);
  21. }
  22. return dataSource;
  23. }
  24. }
  25. /**
  26. * Hikari DataSource configuration.
  27. */
  28. @ConditionalOnClass(HikariDataSource.class)
  29. @ConditionalOnMissingBean(DataSource.class)
  30. @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource", matchIfMissing = true)
  31. static class Hikari {
  32. @Bean
  33. @ConfigurationProperties(prefix = "spring.datasource.hikari")
  34. public HikariDataSource dataSource(DataSourceProperties properties) {
  35. HikariDataSource dataSource = createDataSource(properties,
  36. HikariDataSource.class);
  37. if (StringUtils.hasText(properties.getName())) {
  38. dataSource.setPoolName(properties.getName());
  39. }
  40. return dataSource;
  41. }
  42. }
  43. /**
  44. * DBCP DataSource configuration.
  45. */
  46. @ConditionalOnClass(org.apache.commons.dbcp2.BasicDataSource.class)
  47. @ConditionalOnMissingBean(DataSource.class)
  48. @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.commons.dbcp2.BasicDataSource", matchIfMissing = true)
  49. static class Dbcp2 {
  50. @Bean
  51. @ConfigurationProperties(prefix = "spring.datasource.dbcp2")
  52. public org.apache.commons.dbcp2.BasicDataSource dataSource(
  53. DataSourceProperties properties) {
  54. return createDataSource(properties,
  55. org.apache.commons.dbcp2.BasicDataSource.class);
  56. }
  57. }
  58. //通过spring.dataSource.tpye 来指定装配的数据源
  59. @ConditionalOnMissingBean(DataSource.class)
  60. @ConditionalOnProperty(name = "spring.datasource.type")
  61. static class Generic {
  62. @Bean
  63. public DataSource dataSource(DataSourceProperties properties) {
  64. return properties.initializeDataSourceBuilder().build();
  65. }
  66. }
  67. //用于整合druid 等数据源配置的
  68. public DataSourceBuilder<?> initializeDataSourceBuilder() {
  69. return DataSourceBuilder.create(getClassLoader()).type(getType())
  70. .driverClassName(determineDriverClassName()).url(determineUrl())
  71. .username(determineUsername()).password(determinePassword());
  72. }
  73. public T build() {
  74. //数据源类型
  75. Class<? extends DataSource> type = getType();
  76. //t通过反射创建数据源
  77. DataSource result = BeanUtils.instantiateClass(type);
  78. maybeGetDriverClassName();
  79. bind(result);
  80. return (T) result;
  81. }

1.4.2)jdbcTemplate自动装配

  1. @Configuration
  2. @ConditionalOnClass({ DataSource.class, JdbcTemplate.class })
  3. @ConditionalOnSingleCandidate(DataSource.class)
  4. @AutoConfigureAfter(DataSourceAutoConfiguration.class)
  5. @EnableConfigurationProperties(JdbcProperties.class)
  6. public class JdbcTemplateAutoConfiguration {
  7. @Configuration
  8. static class JdbcTemplateConfiguration {
  9. private final DataSource dataSource;
  10. private final JdbcProperties properties;
  11. JdbcTemplateConfiguration(DataSource dataSource, JdbcProperties properties) {
  12. this.dataSource = dataSource;
  13. this.properties = properties;
  14. }
  15. //jdbcTemplate 配置
  16. @Bean
  17. @Primary
  18. @ConditionalOnMissingBean(JdbcOperations.class)
  19. public JdbcTemplate jdbcTemplate() {
  20. JdbcTemplate jdbcTemplate = new JdbcTemplate(this.dataSource);
  21. JdbcProperties.Template template = this.properties.getTemplate();
  22. jdbcTemplate.setFetchSize(template.getFetchSize());
  23. jdbcTemplate.setMaxRows(template.getMaxRows());
  24. if (template.getQueryTimeout() != null) {
  25. jdbcTemplate
  26. .setQueryTimeout((int) template.getQueryTimeout().getSeconds());
  27. }
  28. return jdbcTemplate;
  29. }
  30. }
  31. @Configuration
  32. @Import(JdbcTemplateConfiguration.class)
  33. static class NamedParameterJdbcTemplateConfiguration {
  34. @Bean
  35. @Primary
  36. @ConditionalOnSingleCandidate(JdbcTemplate.class)
  37. @ConditionalOnMissingBean(NamedParameterJdbcOperations.class)
  38. public NamedParameterJdbcTemplate namedParameterJdbcTemplate(
  39. JdbcTemplate jdbcTemplate) {
  40. return new NamedParameterJdbcTemplate(jdbcTemplate);
  41. }
  42. }
  43. }

测试:

  1. @Autowired
  2. private JdbcTemplate jdbcTemplate;
  3. @Test
  4. public void testDbType() {
  5. System.out.println("自动装配数据源的类型:"+dataSource.getClass());
  6. }
  7. @Test
  8. public void testJdbcTemplate() {
  9. List<Map<String,Object>> employeeList = jdbcTemplate.queryForList("select * from employee");
  10. System.out.println(employeeList.size());
  11. }


二、springboot如何优雅的整合druid +监控

2.1、加入druid的依赖

  1. <dependency>
  2. <groupId>com.alibaba</groupId>
  3. <artifactId>druid</artifactId>
  4. <version>1.1.10</version>
  5. </dependency>
  6. //自定义属性绑定配置
  7. <dependency>
  8. <groupId>org.springframework.boot</groupId>
  9. <artifactId>spring-boot-configuration-processor</artifactId>
  10. <optional>true</optional>
  11. </dependency>

2.2、配置druid的数据源属性



我们发现上面部分 红框 部分是显示黄色,在datasource.properties的文件中,没有属性进行一一映射**

所以我们看到的带红框部分是没有映射到数据源中.
**

2.3、解决办法(优雅)就是我们自己配置一个druid数据源

  1. spring:
  2. datasource:
  3. druid:
  4. username: root
  5. password: 123456
  6. url: jdbc:mysql://47.104.128.12:3306/test
  7. driverClassName: com.mysql.jdbc.Driver
  8. initialSize: 5
  9. minIdle: 5
  10. maxActive: 20
  11. maxWait: 60000
  12. timeBetweenEvictionRunsMillis: 60000
  13. minEvictableIdleTimeMillis: 300000
  14. validationQuery: SELECT 1 FROM DUAL
  15. testWhileIdle: true
  16. testOnBorrow: false
  17. testOnReturn: false
  18. poolPreparedStatements: true
  19. # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
  20. filters: stat,wall,log4j
  21. maxPoolPreparedStatementPerConnectionSize: 20
  22. useGlobalDataSourceStat: true
  23. connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

对应的接受配置类(省略了getSet方法….)

  1. @ConfigurationProperties(prefix = "spring.datasource.druid") //扫描配置类的属性前缀
  2. public class DruidDataSourceProperties {
  3. private String username;
  4. private String password;
  5. private String jdbcUrl;
  6. private String driverClassName;
  7. private Integer initialSize;
  8. private Integer maxActive;
  9. private Integer minIdle;
  10. private long maxWait;
  11. private boolean poolPreparedStatements;
  12. }

自己定制一个druid的配置类

  1. @Configuration
  2. @EnableConfigurationProperties(value = DruidDataSourceProperties.class)
  3. public class DruidDataSourceConfig {
  4. @Autowired
  5. private DruidDataSourceProperties druidDataSourceProperties;
  6. @Bean
  7. public DataSource dataSource() {
  8. System.out.println(druidDataSourceProperties);
  9. DruidDataSource druidDataSource = new DruidDataSource();
  10. druidDataSource.setUsername(druidDataSourceProperties.getUsername());
  11. druidDataSource.setPassword(druidDataSourceProperties.getPassword());
  12. druidDataSource.setUrl(druidDataSourceProperties.getJdbcUrl());
  13. druidDataSource.setDriverClassName(druidDataSourceProperties.getDriverClassName());
  14. druidDataSource.setInitialSize(druidDataSourceProperties.getInitialSize());
  15. druidDataSource.setMinIdle(druidDataSourceProperties.getMinIdle());
  16. druidDataSource.setMaxActive(druidDataSourceProperties.getMaxActive());
  17. druidDataSource.setMaxWait(druidDataSourceProperties.getMaxWait());
  18. druidDataSourceProperties.setPoolPreparedStatements(druidDataSourceProperties.isPoolPreparedStatements());
  19. return druidDataSource;
  20. }
  21. }

再来查看对应的数据源的属性 已经成功的映射到数据源中

2.4、配置数据源监控,配置一个statViewSerlvet(后端管理) WebStatFilter sql监控

  1. /**
  2. * 配置druid管理后台的servlet
  3. * @return
  4. */
  5. @Bean
  6. public ServletRegistrationBean statViewSerlvet() {
  7. ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(),"/druid/*");
  8. Map<String,Object> initParameters = new HashMap<>();
  9. initParameters.put("loginUsername","admin");
  10. initParameters.put("loginPassword","123456");
  11. bean.setInitParameters(initParameters);
  12. return bean;
  13. }
  14. @Bean
  15. public FilterRegistrationBean filterRegistrationBean() {
  16. FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
  17. filterRegistrationBean.setUrlPatterns(Arrays.asList("/*"));
  18. Map<String,Object> initParams = new HashMap<>();
  19. initParams.put("exclusions","*.js,*.css,/druid/*");
  20. filterRegistrationBean.setInitParameters(initParams);
  21. return filterRegistrationBean;
  22. }

监控访问路径:http://localhost:8080/druid/

三、springboot整合 mybaits

3.1、导入maven依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-jdbc</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-web</artifactId>
  8. </dependency>
  9. <dependency>
  10. <groupId>org.mybatis.spring.boot</groupId>
  11. <artifactId>mybatis-spring-boot-starter</artifactId>
  12. <version>2.0.0</version>
  13. </dependency>
  14. <dependency>
  15. <groupId>mysql</groupId>
  16. <artifactId>mysql-connector-java</artifactId>
  17. <scope>runtime</scope>
  18. <version>5.1.46</version>
  19. </dependency>

3.2、让我们看下mybatis自动配置类给我们配置了什么组件

  1. ①:导入了SqlSessionFactory<br /> ②:导入了sqlSessionTemplate<br /> ③:导入了mapperScanner
  1. @org.springframework.context.annotation.Configuration
  2. @ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
  3. @ConditionalOnSingleCandidate(DataSource.class)
  4. @EnableConfigurationProperties(MybatisProperties.class)
  5. @AutoConfigureAfter(DataSourceAutoConfiguration.class)
  6. public class MybatisAutoConfiguration implements InitializingBean {
  7. //1:自动装配了 sqlSessionFactory
  8. @Bean
  9. @ConditionalOnMissingBean
  10. public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
  11. SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
  12. factory.setDataSource(dataSource);
  13. factory.setVfs(SpringBootVFS.class);
  14. if (StringUtils.hasText(this.properties.getConfigLocation())) {
  15. factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));
  16. }
  17. applyConfiguration(factory);
  18. if (this.properties.getConfigurationProperties() != null) {
  19. factory.setConfigurationProperties(this.properties.getConfigurationProperties());
  20. }
  21. if (!ObjectUtils.isEmpty(this.interceptors)) {
  22. factory.setPlugins(this.interceptors);
  23. }
  24. if (this.databaseIdProvider != null) {
  25. factory.setDatabaseIdProvider(this.databaseIdProvider);
  26. }
  27. if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) {
  28. factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());
  29. }
  30. if (this.properties.getTypeAliasesSuperType() != null) {
  31. factory.setTypeAliasesSuperType(this.properties.getTypeAliasesSuperType());
  32. }
  33. if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) {
  34. factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());
  35. }
  36. if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {
  37. factory.setMapperLocations(this.properties.resolveMapperLocations());
  38. }
  39. return factory.getObject();
  40. }
  41. //2:配置了sqlSessionTemplate
  42. @Bean
  43. @ConditionalOnMissingBean
  44. public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
  45. ExecutorType executorType = this.properties.getExecutorType();
  46. if (executorType != null) {
  47. return new SqlSessionTemplate(sqlSessionFactory, executorType);
  48. } else {
  49. return new SqlSessionTemplate(sqlSessionFactory);
  50. }
  51. }
  52. //3:自动装配 导入mapperScanner
  53. public static class AutoConfiguredMapperScannerRegistrar
  54. implements BeanFactoryAware, ImportBeanDefinitionRegistrar, ResourceLoaderAware {
  55. private BeanFactory beanFactory;
  56. private ResourceLoader resourceLoader;
  57. @Override
  58. public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
  59. if (!AutoConfigurationPackages.has(this.beanFactory)) {
  60. logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.");
  61. return;
  62. }
  63. logger.debug("Searching for mappers annotated with @Mapper");
  64. List<String> packages = AutoConfigurationPackages.get(this.beanFactory);
  65. if (logger.isDebugEnabled()) {
  66. packages.forEach(pkg -> logger.debug("Using auto-configuration base package '{}'", pkg));
  67. }
  68. ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
  69. if (this.resourceLoader != null) {
  70. scanner.setResourceLoader(this.resourceLoader);
  71. }
  72. scanner.setAnnotationClass(Mapper.class);
  73. scanner.registerFilters();
  74. scanner.doScan(StringUtils.toStringArray(packages));
  75. }
  76. }
  77. }
  1. <br />

3.3、把sql写在方法上(mapper文件上必须加上@Mapper注解)

  1. @Mapper
  2. public interface EmployeeMapper {
  3. @Select("select * from employee")
  4. List<Employee> list();
  5. @Select("select * from employee where id=#{id}")
  6. Employee findOne(Integer id);
  7. @Options(useGeneratedKeys =true,keyProperty = "id")
  8. @Insert("insert into employee(last_name,email,gender,dept_id)values(#{lastName},#{email},#{gender},#{deptId})")
  9. int save(Employee employee);
  10. }

3.4、把sql写在配置文件上

需要制定配置文件位置

  1. #配置mybatis
  2. mybatis:
  3. configuration:
  4. map-underscore-to-camel-case: true 开启驼峰命名
  5. mapper-locations: classpath:/mybatis/mapper/*.xml 指定配置文件的位置

四、整合Redis

4.1、导入的maven依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-data-redis</artifactId>
  4. </dependency>

4.2、自动装配的组件

  1. @Configuration
  2. @ConditionalOnClass(RedisOperations.class)
  3. @EnableConfigurationProperties(RedisProperties.class)
  4. @Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
  5. public class RedisAutoConfiguration {
  6. //1:自动装配了redis的操作模板类
  7. @Bean
  8. @ConditionalOnMissingBean(name = "redisTemplate")
  9. public RedisTemplate<Object, Object> redisTemplate(
  10. RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
  11. RedisTemplate<Object, Object> template = new RedisTemplate<>();
  12. template.setConnectionFactory(redisConnectionFactory);
  13. return template;
  14. }
  15. //2:自动装配了StringRedisTemplate模板类
  16. @Bean
  17. @ConditionalOnMissingBean
  18. public StringRedisTemplate stringRedisTemplate(
  19. RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
  20. StringRedisTemplate template = new StringRedisTemplate();
  21. template.setConnectionFactory(redisConnectionFactory);
  22. return template;
  23. }
  24. }
  25. @Configuration
  26. @ConditionalOnClass({ GenericObjectPool.class, JedisConnection.class, Jedis.class })
  27. class JedisConnectionConfiguration extends RedisConnectionConfiguration {
  28. //redis的链接工厂
  29. @Bean
  30. @ConditionalOnMissingBean(RedisConnectionFactory.class)
  31. public JedisConnectionFactory redisConnectionFactory() throws UnknownHostException {
  32. return createJedisConnectionFactory();
  33. }

4.3、所需的配置类,我们去RedisProperties配置类 看下可以具体配置哪些属性

  1. @ConfigurationProperties(prefix = "spring.redis")
  2. public class RedisProperties {
  3. private int database = 0;
  4. private String url;
  5. private String host = "localhost";
  6. private String password;
  7. private int port = 6379;
  8. private boolean ssl;
  9. private Duration timeout;
  10. private Sentinel sentinel;
  11. private Cluster cluster;
  12. }

具体的配置项

  1. spring:
  2. redis:
  3. host: 47.104.128.12
  4. port: 6379
  5. password: 123456
  6. jedis:
  7. pool:
  8. max-active: 20
  9. max-idle: 10
  10. min-idle: 5

4.4、使用redis 自动配置的默认的redisTemplate是使用jdk自带的 序列化工具,通过redis 客户端工具看到的key value是 字节形式的

阅读起来不方便,

我们如何修改 redisTemplate的序列化工具 就是我们自己配置一个RedisTemplate

  1. @Configuration
  2. public class RedisConfig {
  3. @Bean
  4. public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
  5. RedisTemplate<Object, Object> template = new RedisTemplate<>();
  6. //设置自己的序列化工具
  7. template.setDefaultSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
  8. template.setConnectionFactory(redisConnectionFactory);
  9. return template;
  10. }
  11. }



五、整合Swagger2

5.1、Swagger2是什么?

它的出现就是为了方便进行测试后台的restful形式的接口,实现动态的更新,当我们在后台的接口修改了后,swagger可以实现自动的更新,而不需要认为的维护这个接口进行测试

5.2、为啥要用Swagger

  1. 程序员最喜欢什么? 最喜欢别人写文档<br /> 程序员最不喜欢什么?最不喜欢自己写文旦

5.3、整合步骤

第一步:加入maven依赖

  1. <dependency>
  2. <groupId>io.springfox</groupId>
  3. <artifactId>springfox-swagger2</artifactId>
  4. <version>2.7.0</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>io.springfox</groupId>
  8. <artifactId>springfox-swagger-ui</artifactId>
  9. <version>2.7.0</version>
  10. </dependency>

5.4、加入swagger2的配置

  1. @Configuration
  2. public class Swagger2Config {
  3. @Bean
  4. public Docket createRestApi() {
  5. return new Docket(DocumentationType.SWAGGER_2)
  6. .apiInfo(apiInfo())
  7. .select()
  8. .apis(RequestHandlerSelectors.basePackage("com.test.controller")) //你需要生成文档所在的包
  9. .paths(PathSelectors.any())
  10. .build();
  11. }
  12. private ApiInfo apiInfo() {
  13. return new ApiInfoBuilder()
  14. .title("springboot利用swagger构建api文档")//文档标题
  15. .description("简单优雅的restfun风格,http://blog.csdn.net/saytime") //描述
  16. .termsOfServiceUrl("http://blog.csdn.net/saytime")
  17. .version("1.0")
  18. .build();
  19. }
  20. }

5.5、在配置类上开启swagger2的文档

  1. @SpringBootApplication
  2. @EnableSwagger2
  3. public class TestSpringbootSwagger2Application {

5.6、使用示例:

  1. package com.test.controller;
  2. import com.test.entity.DataNode;
  3. import com.test.entity.User;
  4. import com.test.entity.UserCondition;
  5. import io.swagger.annotations.*;
  6. import org.springframework.web.bind.annotation.*;
  7. import java.util.ArrayList;
  8. import java.util.List;
  9. /**
  10. * Created by Administrator on 2019/3/23.
  11. */
  12. @RestController
  13. @RequestMapping("/user")
  14. @Api(value = "用户服务",description = "用户的基本操作")
  15. public class UserController {
  16. @ApiOperation(value = "用户列表服务",notes = "查詢所有用戶的列表信息")
  17. @RequestMapping(value = "/list",method = RequestMethod.GET)
  18. public List<User> list() {
  19. List<User> userList = new ArrayList<>();
  20. for(String key: DataNode.users.keySet()) {
  21. userList.add(DataNode.users.get(key));
  22. }
  23. return userList;
  24. }
  25. @ApiOperation(value ="根据用户ID查询用户信息",notes="根据url的id来获取用户详细信息")
  26. @ApiImplicitParam(name="userId",value = "用户ID",required = true,dataType ="Integer",paramType = "path")
  27. @RequestMapping(value = "/findOneById/{userId}",method = RequestMethod.GET)
  28. public User findOneById(@PathVariable("userId") Integer userId) {
  29. for(String key: DataNode.users.keySet()) {
  30. User user = DataNode.users.get(key);
  31. if(user.getUserId() == userId) {
  32. return user;
  33. }
  34. }
  35. return null;
  36. }
  37. @ApiOperation(value = "根据用户名获取用户信息")
  38. @RequestMapping(value = "/findOneUserName/{userName}",method = RequestMethod.GET)
  39. public User findOneByName(@ApiParam(value ="用户名",type = "String") @PathVariable("userName") String userName) {
  40. for(String key: DataNode.users.keySet()) {
  41. User user = DataNode.users.get(key);
  42. if(user.getUserName().equals(userName)) {
  43. return user;
  44. }
  45. }
  46. return null;
  47. }
  48. @ApiOperation(value = "根据用户名获取用户信息")
  49. @ApiImplicitParams({
  50. @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "int", paramType = "query"),
  51. @ApiImplicitParam(name = "userName", value = "用户名称", required = true, dataType = "String", paramType = "query")
  52. }
  53. )
  54. @RequestMapping(value = "/findOneByIdAndName",method = RequestMethod.GET)
  55. public User findOneByIdAndName(@RequestParam String userName,@RequestParam Integer id) {
  56. for(String key: DataNode.users.keySet()) {
  57. User user = DataNode.users.get(key);
  58. if(user.getUserName().equals(userName) && id==user.getUserId()) {
  59. return user;
  60. }
  61. }
  62. return null;
  63. }
  64. @ApiOperation(value = "根据查询条件获取用户信息")
  65. @RequestMapping(value = "/findOneByCondition",method = RequestMethod.GET)
  66. public User findOneByCondition(UserCondition userCondition) {
  67. for(String key: DataNode.users.keySet()) {
  68. User user = DataNode.users.get(key);
  69. if(user.getUserName().equals(userCondition.getUserName()) &&
  70. user.getUserId()==userCondition.getUserId()) {
  71. return user;
  72. }
  73. }
  74. return null;
  75. }
  76. }
  77. @ApiModel(value = "用户实体")
  78. public class User {
  79. public User(Integer userId, String userName, String password, String email, String birthDate) {
  80. this.userId = userId;
  81. this.userName = userName;
  82. this.password = password;
  83. this.email = email;
  84. this.birthDate = birthDate;
  85. }
  86. @ApiModelProperty(name = "用户id",dataType = "String" ,notes = "用户Id")
  87. private Integer userId;
  88. @ApiModelProperty(name = "用户名",dataType = "String" ,notes="用户名")
  89. private String userName;
  90. @ApiModelProperty(name = "密码",dataType = "String",notes = "密码")
  91. private String password;
  92. @ApiModelProperty(name = "邮箱",dataType = "String" ,notes = "邮箱")
  93. private String email;
  94. @ApiModelProperty(name = "生日",dataType = "String" ,notes = "生日")
  95. private String birthDate;
  96. }

5.7、访问地址:http://localhost:8080/swagger-ui.html


常用参数解析:
- @Api()用于类;
表示标识这个类是swagger的资源
- @ApiOperation()用于方法;
表示一个http请求的操作
- @ApiParam()用于方法,参数,字段说明;
表示对参数的添加元数据(说明或是否必填等)
- @ApiModel()用于类
表示对类进行说明,用于参数用实体类接收
- @ApiModelProperty()用于方法,字段
表示对model属性的说明或者数据操作更改
- @ApiIgnore()用于类,方法,方法参数
表示这个方法或者类被忽略
- @ApiImplicitParam() 用于方法
表示单独的请求参数
- @ApiImplicitParams() 用于方法,包含多个 @ApiImplicitParam

六、整合rabbitmq

6.1、我们项目中为什么需要使用消息中间件?

①:异步
场景:用户注册后,把用户数据入库,然后向用户发送一封邮件,然后在发送一条短信
同步等待:150ms


异步发送:用户注册,把用户数据入库,然后通过异步任务分别执行发送邮件和短信


队列形式:用户注册数据入库同时,然后发送消息写入mq中(由于写mq的时间很短,机会可以忽略不计)


②:解耦 (用户下订单成功,然后发送一条减少库存的消息发送到mq中)

③:流量削峰
比如10W人来抢10个商品,在Mq中 设置队列的长度为10,若队列长度超过10,那么后面的请求直接舍弃
从而来降低对DB的压力

6.2、rabbtimq的核心概念理解?

①:Publisher(消息生产者)消息的生产者,也是一个向交换器发布消息的客户端应用程序
②:Message (消息对象)消息,消息是不具名的,它由消息头和消息体组成。消息体是不透明的,而消息头则由一系列的可选属性组
成,这些属性包括routing-key(路由键)、priority(相对于其他消息的优先权)、delivery-mode(指出
该消息可能需要持久性存储)等
③:交换器,用来接收生产者发送的消息并将这些消息路由给服务器中的队列。
Exchange有4种类型:direct(默认),fanout(扇形交换机), topic(主题交换机), 和headers(不同交换机),不同类型的Exchange转发消息的策略有
所区别
④:Queue
消息队列,用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息
可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将其取走。
⑤:Binding
绑定,用于消息队列和交换器之间的关联。一个绑定就是基于路由键将交换器和消息队列连
接起来的路由规则,所以可以将交换器理解成一个由绑定构成的路由表。
Exchange 和Queue的绑定可以是多对多的关系
⑥:Connection
网络连接,比如一个TCP连接。
⑦:Channel
信道,多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的TCP连接内的虚
拟连接,AMQP 命令都是通过信道发出去的,不管是发布消息、订阅队列还是接收消息,这
些动作都是通过信道完成。因为对于操作系统来说建立和销毁 TCP 都是非常昂贵的开销,所
以引入了信道的概念,以复用一条 TCP 连接。
⑧:Consumer
消息的消费者,表示一个从消息队列中取得消息的客户端应用程序。
⑨:Virtual Host
虚拟主机,表示一批交换器、消息队列和相关对象。虚拟主机是共享相同的身份认证和加
密环境的独立服务器域。每个 vhost 本质上就是一个 mini 版的 RabbitMQ 服务器,拥有
自己的队列、交换器、绑定和权限机制。vhost 是 AMQP 概念的基础,必须在连接时指定,
RabbitMQ 默认的 vhost 是 / 。
⑩:Broker
表示消息队列服务器实体

6.3、交换机的特性以及分类

6.4、整合三板斧

①:导入maven依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-amqp</artifactId>
  4. </dependency>

②:查看自动配置以及对应的自动配置属性类

  1. @Configuration
  2. @ConditionalOnClass({ RabbitTemplate.class, Channel.class })
  3. @EnableConfigurationProperties(RabbitProperties.class)
  4. @Import(RabbitAnnotationDrivenConfiguration.class)
  5. public class RabbitAutoConfiguration {
  6. @Configuration
  7. @ConditionalOnMissingBean(ConnectionFactory.class)
  8. protected static class RabbitConnectionFactoryCreator {
  9. //rabbitmq 连接工厂
  10. @Bean
  11. public CachingConnectionFactory rabbitConnectionFactory(RabbitProperties properties,ObjectProvider<ConnectionNameStrategy> connectionNameStrategy)
  12. throws Exception {
  13. PropertyMapper map = PropertyMapper.get();
  14. //创建连接工厂
  15. CachingConnectionFactory factory = new CachingConnectionFactory(getRabbitConnectionFactoryBean(properties).getObject());
  16. //连接地址
  17. map.from(properties::determineAddresses).to(factory::setAddresses);
  18. //生产端的消息确认
  19. map.from(properties::isPublisherConfirms).to(factory::setPublisherConfirms);
  20. //不可路由消息的处理
  21. map.from(properties::isPublisherReturns).to(factory::setPublisherReturns);
  22. //配置通信管道
  23. RabbitProperties.Cache.Channel channel = properties.getCache().getChannel();
  24. map.from(channel::getSize).whenNonNull().to(factory::setChannelCacheSize);
  25. map.from(channel::getCheckoutTimeout).whenNonNull().as(Duration::toMillis)
  26. .to(factory::setChannelCheckoutTimeout);
  27. //配置管道缓存
  28. RabbitProperties.Cache.Connection connection = properties.getCache()
  29. .getConnection();
  30. map.from(connection::getMode).whenNonNull().to(factory::setCacheMode);
  31. map.from(connection::getSize).whenNonNull()
  32. .to(factory::setConnectionCacheSize);
  33. map.from(connectionNameStrategy::getIfUnique).whenNonNull()
  34. .to(factory::setConnectionNameStrategy);
  35. return factory;
  36. }
  37. }
  38. @Configuration
  39. @Import(RabbitConnectionFactoryCreator.class)
  40. protected static class RabbitTemplateConfiguration {
  41. //模版配置类
  42. @Bean
  43. @ConditionalOnSingleCandidate(ConnectionFactory.class)
  44. @ConditionalOnMissingBean
  45. public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
  46. PropertyMapper map = PropertyMapper.get();
  47. RabbitTemplate template = new RabbitTemplate(connectionFactory);
  48. //配置消息转换器
  49. MessageConverter messageConverter = this.messageConverter.getIfUnique();
  50. if (messageConverter != null) {
  51. template.setMessageConverter(messageConverter);
  52. }
  53. //设置为true 那么不可达消息会交给RetrunConfirm 处理,若设置为false 消息队列直接删除该消息
  54. template.setMandatory(determineMandatoryFlag());
  55. //配置模版属性
  56. RabbitProperties.Template properties = this.properties.getTemplate();
  57. if (properties.getRetry().isEnabled()) {
  58. template.setRetryTemplate(createRetryTemplate(properties.getRetry()));
  59. }
  60. //设置超时时间
  61. map.from(properties::getReceiveTimeout).whenNonNull().as(Duration::toMillis)
  62. .to(template::setReceiveTimeout);
  63. //配置 回复超时时间
  64. map.from(properties::getReplyTimeout).whenNonNull().as(Duration::toMillis)
  65. .to(template::setReplyTimeout);
  66. //配置交换机
  67. map.from(properties::getExchange).to(template::setExchange);
  68. //配置路由key
  69. map.from(properties::getRoutingKey).to(template::setRoutingKey);
  70. return template;
  71. }
  72. private boolean determineMandatoryFlag() {
  73. Boolean mandatory = this.properties.getTemplate().getMandatory();
  74. return (mandatory != null) ? mandatory : this.properties.isPublisherReturns();
  75. }
  76. private RetryTemplate createRetryTemplate(RabbitProperties.Retry properties) {
  77. PropertyMapper map = PropertyMapper.get();
  78. RetryTemplate template = new RetryTemplate();
  79. SimpleRetryPolicy policy = new SimpleRetryPolicy();
  80. map.from(properties::getMaxAttempts).to(policy::setMaxAttempts);
  81. template.setRetryPolicy(policy);
  82. ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
  83. map.from(properties::getInitialInterval).whenNonNull().as(Duration::toMillis)
  84. .to(backOffPolicy::setInitialInterval);
  85. map.from(properties::getMultiplier).to(backOffPolicy::setMultiplier);
  86. map.from(properties::getMaxInterval).whenNonNull().as(Duration::toMillis)
  87. .to(backOffPolicy::setMaxInterval);
  88. template.setBackOffPolicy(backOffPolicy);
  89. return template;
  90. }
  91. @Bean
  92. @ConditionalOnSingleCandidate(ConnectionFactory.class)
  93. @ConditionalOnProperty(prefix = "spring.rabbitmq", name = "dynamic", matchIfMissing = true)
  94. @ConditionalOnMissingBean
  95. public AmqpAdmin amqpAdmin(ConnectionFactory connectionFactory) {
  96. return new RabbitAdmin(connectionFactory);
  97. }
  98. }
  99. @Configuration
  100. @ConditionalOnClass(RabbitMessagingTemplate.class)
  101. @ConditionalOnMissingBean(RabbitMessagingTemplate.class)
  102. @Import(RabbitTemplateConfiguration.class)
  103. protected static class MessagingTemplateConfiguration {
  104. @Bean
  105. @ConditionalOnSingleCandidate(RabbitTemplate.class)
  106. public RabbitMessagingTemplate rabbitMessagingTemplate(
  107. RabbitTemplate rabbitTemplate) {
  108. return new RabbitMessagingTemplate(rabbitTemplate);
  109. }
  110. }
  111. }

③:在yml文件中 配置关键属性

  1. public class RabbitProperties {
  2. /**
  3. * RabbitMQ host.
  4. */
  5. private String host = "localhost";
  6. /**
  7. * RabbitMQ port.
  8. */
  9. private int port = 5672;
  10. /**
  11. * Login user to authenticate to the broker.
  12. */
  13. private String username = "guest";
  14. /**
  15. * Login to authenticate against the broker.
  16. */
  17. private String password = "guest";
  18. /**
  19. * SSL configuration.
  20. */
  21. private final Ssl ssl = new Ssl();
  22. /**
  23. * Virtual host to use when connecting to the broker.
  24. */
  25. private String virtualHost;
  26. /**
  27. * Comma-separated list of addresses to which the client should connect.
  28. */
  29. private String addresses;
  30. /**
  31. * Requested heartbeat timeout; zero for none. If a duration suffix is not specified,
  32. * seconds will be used.
  33. */
  34. @DurationUnit(ChronoUnit.SECONDS)
  35. private Duration requestedHeartbeat;
  36. /**
  37. * Whether to enable publisher confirms.
  38. */
  39. private boolean publisherConfirms;
  40. /**
  41. * Whether to enable publisher returns.
  42. */
  43. private boolean publisherReturns;
  44. /**
  45. * Connection timeout. Set it to zero to wait forever.
  46. */
  47. private Duration connectionTimeout;
  48. /**
  49. * Cache configuration.
  50. */
  51. private final Cache cache = new Cache();
  52. /**
  53. * Listener container configuration.
  54. */
  55. private final Listener listener = new Listener();
  56. private final Template template = new Template();
  57. private List<Address> parsedAddresses;
  1. #可配置常用属性
  2. spring:
  3. rabbitmq:
  4. host: 47.104.128.10
  5. port: 5672
  6. virtual-host: springboot-rabbitmq
  7. username: guest
  8. password: guest
  9. connection-timeout: 5000
  10. template:
  11. mandatory: true

七、springboot整合 actuator 监控管理

通过引入spring-boot-starter-actuator,可以使用Spring Boot为我们提供的准
生产环境下的应用监控和管理功能。我们可以通过HTTP,JMX,SSH协议来进
行操作,自动得到审计、健康及指标信息等

7.1、监控访问路径前缀

management.endpoints.web.base-path=/actuator 这个是springboot监控默认的 我们可以修改为自己的

management.endpoints.web.base-path=/Monitor


总结 不管监控路径 是默认的还是 自己修改的, 为了安全起见,必须要通过spring security 来控制访问权限以免暴露你的服务信息

7.2、http 健康监控端点 默认只暴露了 health,info端点

①:通过 management.endpoints.web.exposure.include=* 来指定开放所有的端点

②:通过 management.endpoints.web.exposure.include=health,info,beans 通过逗号分开来指定开放哪些端点
或者也可以通过 management.endpoint.具体端点.enabled=true|false 来开放或者打开哪些端点

7.3、具体端点分析

1)服务监控端点 http://localhost:8080//Monitor/health

2)审计事件监控端点 http://localhost:8080//Monitor/auditevents

3) 服务装配bean的报告 端点: http://localhost:8080//Monitor/beans

4) 条件自动装配报告端点: http://localhost:8080//Monitor/conditions

5) 配置属性(配置前缀)端点 http://localhost:8080/Monitor/configprops

6) 服务环境端点 http://localhost:8080/Monitor/env

7)应用 各个包 中的日志等级级别 端点 http://localhost:8080/Monitor/loggers

8)应用堆栈端点 http://localhost:8080/Monitor/heapdump 下载
9) 线程dump端点监控 http://localhost:8080/Monitor/threaddump

10) 各项应用指标端点: http://localhost:8080/Monitor/metrics

11)定时任务端点 http://localhost:8080/Monitor/scheduledtasks

12) 应用映射端点 http://localhost:8080/Monitor/mappings

13)最新调用 监控端点: http://localhost:8080/Monitor/httptrace

14)自定义信息端点: http://localhost:8080/Monitor/info