首页 文章 精选 留言 我的

精选列表

搜索[整合],共10000篇文章
优秀的个人博客,低调大师

idea 创建的maven+spring+mybatis项目整合 报错无法创建bean

最近在做一个由maven构建的spring+spring mvc+mybatis项目,刚开始的时候是用自己的电脑Win10环境下的eclipse写的,托管到了码svn上面,刚开始什么问题都没有 同学用的是win10+idea,结果问题就来了,下载下来的代码居然不能运行!!!,各种看着一脸懵逼的报错信息(idea的tomcat运行日志文件很不好找,找了好久)辛辛苦苦弄了一周左右,期间经历了把项目删了又建,然后自己搭环境等各种坑爹的环节,一开始报错信息千奇百怪,在弄了这么久之后大概就稳定成了如下的样子: mybatis.xml]:Initializationofbeanfailed;nestedexceptionisorg.springframework.beans.TypeMismatchException:Failedtoconvertpropertyvalueoftype'java.lang.String'torequiredtype'org.springframework.core.io.Resource[]'forproperty'mapperLocations';nestedexceptionisjava.lang.IllegalArgumentException:Couldnotresolveresourcelocationpattern[classpath:com/scpchome/dao/mapping/*.xml]:classpathresource[com/scpchome/dao/mapping/]cannotberesolvedtoURLbecauseitdoesnotexist 一直是不能创建bean的样子,经过一行一行地阅读报错信息。。最后发现mybatis的映射xml文件居然没有找到,然后又去翻classes目录,结果果然没有,知道具体的错误就好办了,随后百度了一发在pom文件中加入了如下代码,困扰了一周的问题成功解决 <!--如果不添加此节点mybatis的mapper.xml文件都会被漏掉。--> <build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> </resources> </build>

优秀的个人博客,低调大师

碎片化技术正在整合 智能家居等领域成发展热点

智能家居市场产品品项及品牌交错复杂,使用者程度落差大,物联网标准不一的问题,恐怕将会成为智能家居市场成长的最大阻力。但随着越来越多联网设备及业者加入智能家居市场,通讯标准不一的问题可望逐步减少。 中国信息通信研究院副院长何桂立日前表示,随着移动物联网与云计算、大数据等新一代信息技术结合得更为紧密,解决了以前制约和影响物联网发展的碎片化问题,中国已正式迈入物联网2.0时代,智能制造、公共事业/智慧城市、车联网/交通物流、智能家居和可穿戴五大领域将成为物联网发展热点。 何桂立是在9月1日由江西省工信委、鹰潭市政府和中国信息通信研究院联合主办的江西省移动物联网发展战略新闻发布会上作出上述表述的。何桂立认为,我国从物联网1.0时代迈入2.0时代具体体现在三方面变化上。 一是技术标准。过去的技术准备不足,如标准化方面不完整。而如今移动物联网已形成由NB-IoT(窄带物联网)、eMTC(增强性机器通信技术),以及蜂窝网的未来演进技术5G(第五代移动通信技术)共同构成的技术体系。 二是产业环境。在物联网1.0时代,产业结构、链条不完整。目前,我国已初步形成涵盖芯片、模组、系统、平台在内的移动物联网产业体系,产业发展正进入快速上升期,物联网在新技术发展的产业环境有了很大的提升。 三是应用场景。人们从最初“只知技术、不明用途”的探索阶段,到如今已明确这一新技术能应用到什么领域、解决什么问题。 何桂立表示,2020年我国移动物联网市场将超过四万亿元,其中智能制造和公共事业/智慧城市将成为万亿市场。 本文转自d1net(转载)

优秀的个人博客,低调大师

微软将自研图像生成模型 MAI-Image-1 整合至 Bing、Copilot

MAI-Image-1 是微软完全自主开发的首个文本生成图像 (text-to-image) 模型。近日,官方宣布它已被集成到微软部分产品中,包括 Bing Image Creator 和 Copilot Audio Expressions(为故事模式的音频生成自定义封面)。 https://www.bing.com/images/create https://copilot.microsoft.com/labs/audio-expression 微软 AI 部门负责人 Mustafa Suleyman 介绍称,MAI-Image-1 在生成食物、自然风景、艺术化光效及写实细节等图像方面“表现尤为出色”。 据介绍,MAI-Image-1 模型针对创意场景进行了优化,微软在训练模型过程中刻意避免“重复或风格化过度”的输出,并征询了创意专业人员(艺术家、设计师)的反馈,可生成多种类型的图像,尤其擅长食物、自然场景以及“艺术化光线+摄影真实感细节”的图像。

优秀的个人博客,低调大师

《灯灯》多租户快速开发平台 5.2.1 发布,租户平台整合开放平台

升级日志 feat(lamp-web-pro): 同步完成【开放平台】相关功能 feat(lamp-web-pro-soybean): 同步完成【开放平台】相关功能 feat(lamp-sdk): 完善 对外接口的sdk feat(sop-gateway-server): 集成 开放平台网关,解决开放平台接口调用和鉴权等问题。 集成sop-gateway sop网关改造,使得可以解析isv绑定的租户id 改造 sop-gateway 支持jdk17和spring boot3.4.4 sop-admin启动时,不在强依赖sop-gateway dubbo.version>3.3.4 smart-doc.version>3.1.0 feat(lamp-boot-sop-server):新增 lamp-boot-sop-server ,解决单体版集成sop时,依赖过多的问题。 lamp-boot-server 等价于 普通单体版 lamp-boot-sop-server 等价于 普通单体版 + SOP开放平台能力 refactor(lamp-openapi): 完善 对外接口服务 示例接口 refactor(lamp-core): 全局对象R,封装全局请求ID给前端 refactor(lamp-sop-admin): 删除isv时,级联删除其他数据 refactor(lamp-validator-starter): 优化表单校验,后端long类型返回为前端string类型 refactor: 弃用 fastjson 改用fastjson2 fix(lamp-boot-server): 修复单体版 生产环境 无法启用 禁止修改拦截器的bug fix(lamp-sop-admin): 文档树 返回 创建时间和修改时间 fix(lamp-sop-admin): 修改应用时,返回id fix(lamp-sop-admin): 数据为空时,返回空数组,而非null fix(lamp-sop-admin): 删除分组时,级联删除其他数据 fix(lamp-swagger-starter): 修复 knife4j doc.html 无法访问的问题 fix(lamp-sa-token-ext): MDC记录请求头中的数据 体验网址 vben2 版 vben5 版 soybean 版 数据源模式 点我体验 点我体验 点我体验 字段模式 点我体验 点我体验 点我体验 本次升级功能预览 1. 开放文档首页 2. 开放文档 3. 全局响应码 4. 应用申请 5. 开放接口 6. 文档配置 7、 文档管理 8. 开放应用 9. 应用分组 关于 lamp 灯灯(简称灯,英文名:lamp),她是一个项目集,为满足高内聚低耦合设计原则,将一个大项目拆解为以下几个子项目: lamp-util:后端工具集 lamp-cloud:基于 Spring Cloud 实现的后台 lamp-boot:基于 Spring Boot 实现的后台 lamp-job:基于 xxl-job 集成本项目的分布式定时任务 lamp-generator:代码生成器 lamp-web:前端 lamp-cloud简介 lamp-cloud是基于SpringCloudAlibaba、SpringCloud、SpringBoot开发的微服务中后台快速开发平台,支持jdk17、jdk11和jdk8,专注于多租户 (SaaS 架构) 解决方案,亦可作为普通项目(非 SaaS 架构)的基础开发框架使用,目前已实现数据库隔离、字段隔离等租户隔离方案以及非租户隔离的解决方案。 她拥有自研 RBAC(基于租户应用的角色权限控制体系)、网关统一鉴权、数据权限、优雅缓存解决方案、防缓存击穿、前后端统一表单校验、字典数据自动回显、可视化前后端代码生成器、支持多种文件存储、支持多种短信邮件发送接口、灰度发布、防 XSS 攻击、防 SQL 注入、分布式事务、分布式定时任务等功能;支持多业务系统并行开发,支持多服务并行开发,是中后台系统开发脚手架的最佳选择。 lamp-cloud 代码简洁,注释齐全,架构清晰,非常适合个人学习以及中小企业作为基础框架使用。采用 Spring Cloud Alibaba、SpringBoot、Mybatis、Seata、Sentinel、RabbitMQ、FastDFS/MinIO、SkyWalking 等主要框架和中间件。本项目旨在实现基础框架能力,不涉及具体业务。 关注项目 官网:https://tangyh.top 源码:https://github.com/dromara/lamp-cloud 源码:https://gitee.com/dromara/lamp-cloud

优秀的个人博客,低调大师

【SpringBoot技术专题】「JWT技术专区」SpringSecurity整合JWT授权和认证实现

JWT基本概念 JWT,即 JSON Web Tokens(RFC 7519),是一个广泛用于验证 REST APIs 的标准。虽说是一个新兴技术,但它却得以迅速流行。 JWT的验证过程是: 前端(客户端)首先发送一些凭证来登录(我们编写的是 web 应用,所以这里使用用户名和密码来做验证)。 后端(服务端)这里指Spring应用校验这些凭证,如果校验通过则生成并返回一个 JWT。 客户端需要在请求头的Authorization字段中以 “Bearer TOKEN” 的形式携带获取到的token,服务端会检查这个token是否可用并决定授权访问或拒绝请求。 token中可能保存了用户的角色信息,服务端可以根据用户角色来确定访问权限。 实现 我们来看一下在实际的 Spring 项目中是如何实现JWT登录和保存机制的。 依赖 下面是我们示例代码的 Maven 依赖列表,注意,截图中并未包含Spring Boot、Hibernate等核心依赖(你需要自行添加)。 用户模型 创建一个包含保存用户信息、基于用户名和密码验证用户权限功能的 controller。 创建一个名为 User 的实体类,它是数据库中 USER 表的映射。需要的话,可以在其中添加其他属性。 还需要定义一个 UserRepository 类来保存用户信息,重写其 findByUsername 方法,在验证过程中会用到。 public interface UserRepository extends JpaRepository<User, String>{ User findByUsername(String username); } 千万不能在数据库中保存明文密码,因为很多用户喜欢在各种网站上使用相同的密码。 哈希算法有很多,BCrypt是最常用的之一,它也是推荐用于安全加密的算法。关于这个话题的更多内容,可以查看 这篇文章。 为了加密密码,我们在 @bean 注解标记的主类中定义一个 BCrypt Bean,如下所示: @Bean public BCryptPasswordEncoder bCryptPasswordEncoder() { return new BCryptPasswordEncoder(); } 加密密码的时候将会调用这个Bean里面的方法。 创建一个名为 UserController 的类,为其添加 @RestController 注解并定义路由映射。 在这个应用中,我们接收前端传入的 UserDto 对象来保存用户信息。你也可以选择在 @RequestBody 参数中接收 User 对象。 @RestController @RequestMapping("/api/services/controller/user") @AllArgsConstructor public class UserController { private UserService userService; @PostMapping() public ResponseEntity<String> saveUser(@RequestBody UserDto userDto) { return new ResponseEntity<>(userService.saveDto(userDto), HttpStatus.OK); } } 我们使用之前定义的 BCrypt Bean 来加密传入的 UserDto 对象的 password 字段。这个操作也可以在 controller 之中执行,但是把逻辑操作集中到 service 类中是更好的做法。 @Transactional(rollbackFor = Exception.class) public String saveDto(UserDto userDto) { userDto.setPassword(bCryptPasswordEncoder.encode(userDto.getPassword())); return save(new User(userDto)).getId(); } 验证过滤器 需要通过权限验证来确定用户的真实身份。这里我们使用经典的【用户名-密码对】的形式来完成。 验证步骤: 创建继承 UsernamePasswordAuthenticationFilter 的验证过滤器 创建继承 WebSecurityConfigurerAdapter 的安全配置类并应用过滤器 验证过滤器的代码如下——也许你已经知道了,过滤器是 Spring Security 的核心。 public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter { private AuthenticationManager authenticationManager; public JWTAuthenticationFilter(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; setFilterProcessesUrl("/api/services/controller/user/login"); } @Override public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res) throws AuthenticationException { try { User creds = new ObjectMapper().readValue(req.getInputStream(), User.class); return authenticationManager.authenticate( new UsernamePasswordAuthenticationToken( creds.getUsername(), creds.getPassword(), new ArrayList<>()) ); } catch (IOException e) { throw new RuntimeException(e); } } @Override protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain, Authentication auth) throws IOException { String token = JWT.create() .withSubject(((User) auth.getPrincipal()).getUsername()) .withExpiresAt(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) .sign(Algorithm.HMAC512(SECRET.getBytes())); String body = ((User) auth.getPrincipal()).getUsername() + " " + token; res.getWriter().write(body); res.getWriter().flush(); } } Spring Security 默认使用继承了 UsernamePasswordAuthenticationFilter 的子类进行密码验证 ,我们可以在其中编写自定义的验证逻辑。 我们在构造函数中调用setFilterProcessesUrl 方法,设置默认登录地址。 如果删除这行代码,Spring Security 会生成一个默认的 “/login” 端点,我们可以不用在 controller 中显式地定义登录端点。 这行代码执行之后,我们的登录端点将被设置为 /api/services/controller/user/login,你可以根据自己的实际代码来设置。 我们重写了 UsernameAuthenticationFilter 类的 attemptAuthentication 和 successfulAuthentication 方法。 用户登录时会执行 attemptAuthentication方法,它会读取凭证信息、创建用户 POJO、校验凭证并授权。 我们传入用户名、密码以及一个空列表。我们还没有定义用户角色,所以把这个表示用户权限(角色)的列表留空就行。 如果验证成功,就会执行 successfulAuthentication 方法,它的参数由Spring Security自动注入。 attemptAuthentication返回Authentication对象,这个对象包含了我们传入的权限信息。 我们想在验证成功之后返回一个使用用户名、密钥和过期时间创建的 token。先定义SECRET和 EXPIRATION_DATE。 public class SecurityConstants { public static final String SECRET = "SECRET_KEY"; public static final long EXPIRATION_TIME = 900_000; // 15 mins public static final String TOKEN_PREFIX = "Bearer "; public static final String HEADER_STRING = "Authorization"; public static final String SIGN_UP_URL = "/api/services/controller/user"; } 创建一个类作为常量的容器,SECRET 的值可以任意设置,最佳的做法是在 hash 算法支持的范围内使用尽可能长的字符串。例如我们使用的是 HS256 算法,SECRET 字符串的最佳长度即为 256 bits/32 个字符。 超时时间设置为 15 分钟,这是防御暴力破解密码的最佳实践。此处使用的时间单位为毫秒。 验证过滤器准备好了,但还不可用,我们还要创建一个授权过滤器,再通过一个配置类来应用它们。 授权过滤器会校验 Authorization 请求头中的 token 是否存在及其可用性。在配置类中指明哪些端点需要使用这个过滤器。 授权过滤器 doFilterInternal 方法拦截请求并校验 Authorization 请求头,如果不存在或者它的值不是以 “BEARER” 开头,则直接转到下一个过滤器。 如果这个请求头携带了合法的值,会调用 getAuthentication 方法,校验这个 JWT,如果这个 token 是可用的,它会返回一个Spring内部使用的 token。 这个新生成的 token 会被保存在 SecurityContext 中,如果需要基于用户角色进行授权的话,可以向这个 token 传入用户权限。 过滤器都准备好了,现在要通过配置类把它们投入使用。 public class JWTAuthorizationFilter extends BasicAuthenticationFilter { public JWTAuthorizationFilter(AuthenticationManager authManager) { super(authManager); } @Override protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException { String header = req.getHeader(HEADER_STRING); if (header == null || !header.startsWith(TOKEN_PREFIX)) { chain.doFilter(req, res); return; } UsernamePasswordAuthenticationToken authentication = getAuthentication(req); SecurityContextHolder.getContext().setAuthentication(authentication); chain.doFilter(req, res); } // Reads the JWT from the Authorization header, and then uses JWT to validate the token private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) { String token = request.getHeader(HEADER_STRING); if (token != null) { // parse the token. String user = JWT.require(Algorithm.HMAC512(SECRET.getBytes())) .build() .verify(token.replace(TOKEN_PREFIX, "")) .getSubject(); if (user != null) { // new arraylist means authorities return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>()); } return null; } return null; } 配置处理 给这个类添加 @EnableWebSecurity 注解,同时让它继承 WebSecurityConfigureAdapter 并实现自定义的安全逻辑。 自动注入之前定义的 BCrypt Bean,同时自动注入 UserDetailsService 用来获取用户账户信息。 最重要的是那个接收一个 HttpSecurity 对象作为参数的方法,其中声明了如何在各个端点中应用过滤器、配置了 CORS、放行了所有对注册接口的 POST 请求。 可以添加其他匹配器来基于 URL 模式和角色进行过滤,你也可以 查看 StackOverflow 上这个问题的相关示例。另一个方法配置了 AuthenticationManager 在登录校验时使用我们指定的编码器。 @EnableWebSecurity public class WebSecurity extends WebSecurityConfigurerAdapter { private UserDetailsServiceImpl userDetailsService; private BCryptPasswordEncoder bCryptPasswordEncoder; public WebSecurity(UserDetailsServiceImpl userService, BCryptPasswordEncoder bCryptPasswordEncoder) { this.userDetailsService = userService; this.bCryptPasswordEncoder = bCryptPasswordEncoder; } @Override protected void configure(HttpSecurity http) throws Exception { http.cors().and().authorizeRequests() .antMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll() .anyRequest().authenticated() .and() .addFilter(new JWTAuthenticationFilter(authenticationManager())) .addFilter(new JWTAuthorizationFilter(authenticationManager())) // this disables session creation on Spring Security .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); } @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder); } @Bean CorsConfigurationSource corsConfigurationSource() { final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration corsConfiguration = new CorsConfiguration().applyPermitDefaultValues(); source.registerCorsConfiguration("/**", corsConfiguration); return source; } } 测试实现 发送一些请求来测试应用是否正常工作。 使用 GET 请求访问受保护的资源,服务端返回了 403 状态码。 这是程序设计预期的行为,因为我们没有在请求头中携带 token 信息。 现在创建一个用户: 发送一个携带了用户信息数据的 POST 请求,以创建用户。稍后将登陆这个账户来获取 token。 获取到 token 了,现在可以用这个 token 来访问受保护的资源。 在 Authorization 请求头中携带 token,就可以访问受保护的端点了。 总结 Spring 中实现 JWT 授权和密码认证的步骤,同时学习了如何安全地保存用户信息。 参考内容 How to Set Up Java Spring Boot JWT Authorization and

优秀的个人博客,低调大师

JPA项目多数据源模式整合Sharding-jdbc实现数据脱敏

引言 前一篇博文,已经完整的介绍了数据库脱敏的场景及方案,来自京东数科的Sharding-JDBC开源项目通过对数据源中间代理的方式透明化的实现了这个功能,但是,功能虽然实现了,sql兼容的小问题还是很多,比如目前不支持子查询,数据库定义的关键字不允许使用,等等问题,反观我们需要加解密的字段,其实相比业务的sql来说占比非常小,即使遇到了和组件不兼容的地方也可以稍加改动解决掉,所以最后博主给出了一个比较完善的组件集成方案:多数据源模式,需要加解密的数据源和业务其他数据源隔离。即解决了数据库字段加解密的问题,同时也解决了组件对sql的兼容问题。下面是具体的集成步骤以及需要注意的点 引入依赖 <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> <version>${sharding.jdbc.version}</version> </dependency> 这里需要说明下,虽然采用多数据源兼容后,不能使用组件基于spring boot自动装配功能,但是这里还是建议导入sharding-spring-boot-starter包,因为这个包下内置了配置映射的类,在自定义数据源的时候非常有用 添加sharding数据源配置 #数据库源配置 spring.shardingsphere.datasource.name = ds spring.shardingsphere.datasource.ds.type = com.zaxxer.hikari.HikariDataSource spring.shardingsphere.datasource.ds.driver-class-name = com.mysql.jdbc.Driver spring.shardingsphere.datasource.ds.jdbc-url = jdbc:mysql://xxx?autoReconnect=true&useUnicode=true&characterEncoding=utf-8 spring.shardingsphere.datasource.ds.username = root spring.shardingsphere.datasource.ds.password = xxx spring.shardingsphere.encrypt.encryptors.encryptor_aes.type = aes spring.shardingsphere.encrypt.encryptors.encryptor_aes.props.aes.key.value = 123456 spring.shardingsphere.encrypt.tables.account.columns.password.plainColumn = password spring.shardingsphere.encrypt.tables.account.columns.password.cipherColumn = password_encrypt spring.shardingsphere.encrypt.tables.account.columns.password.encryptor = encryptor_aes spring.shardingsphere.props.sql.show = true spring.shardingsphere.props.query.with.cipher.column = true 排除自动装配 @SpringBootApplication(exclude = SpringBootConfiguration.class) 由于导入了starter包,所以这里需要手动排除自动装载类, 业务数据源配置 多数据源后,业务本身的数据源也需要手动配置,默认的spring boot jpa自动转载类会判断上线文中是否存在EntityManagerFactory类,如果有就不会初始化了,所以两个数据源都需要手动配置 @Configuration @EnableConfigurationProperties(JpaProperties.class) public class DataSourceConfiguration{ private final JpaProperties jpaProperties; private final Environment environment; public DataSourceConfiguration(JpaProperties jpaProperties, Environment environment) { this.jpaProperties = jpaProperties; this.environment = environment; } @Primary @Bean public DataSource dataSource(){ String prefix = "spring.shardingsphere.datasource."; String each = getDataSourceNames(prefix).get(0); try { return getDataSource(prefix, each); } catch (final ReflectiveOperationException ex) { throw new ShardingSphereException("Can't find datasource type!", ex); } } @Primary @Bean public EntityManagerFactory entityManagerFactory() { HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); vendorAdapter.setDatabase(Database.MYSQL); vendorAdapter.setGenerateDdl(true); vendorAdapter.setShowSql(true); LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); factory.setJpaVendorAdapter(vendorAdapter); factory.setPersistenceUnitName("default"); factory.setPackagesToScan(Constants.BASE_PACKAGES); factory.setDataSource(dataSource()); factory.setJpaPropertyMap(jpaProperties.getProperties()); factory.afterPropertiesSet(); return factory.getObject(); } @Bean @Primary public EntityManager entityManager(EntityManagerFactory entityManagerFactory){ return SharedEntityManagerCreator.createSharedEntityManager(entityManagerFactory); } @Primary @Bean public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory){ JpaTransactionManager txManager = new JpaTransactionManager(); txManager.setEntityManagerFactory(entityManagerFactory); return txManager; } private ListgetDataSourceNames(final String prefix) { StandardEnvironment standardEnv = (StandardEnvironment) environment; standardEnv.setIgnoreUnresolvableNestedPlaceholders(true); return null == standardEnv.getProperty(prefix + "name") ? new InlineExpressionParser(standardEnv.getProperty(prefix + "names")).splitAndEvaluate() : Collections.singletonList(standardEnv.getProperty(prefix + "name")); } @SuppressWarnings("unchecked") private DataSource getDataSource(final String prefix, final String dataSourceName) throws ReflectiveOperationException { Map dataSourceProps = PropertyUtil.handle(environment, prefix + dataSourceName.trim(), Map.class); Preconditions.checkState(!dataSourceProps.isEmpty(), "Wrong datasource properties!"); DataSource result = DataSourceUtil.getDataSource(dataSourceProps.get("type").toString(), dataSourceProps); DataSourcePropertiesSetterHolder.getDataSourcePropertiesSetterByType(dataSourceProps.get("type").toString()).ifPresent( dataSourcePropertiesSetter -> dataSourcePropertiesSetter.propertiesSet(environment, prefix, dataSourceName, result)); return result; } } 上面代码需要注意三个地方,一是数据源的配置,是以sharding的配置来解析获得的,是因为我们已经集成过了,不想改动配置,所以如此,如果还没集成过,可以直接使用spring 配置数据源的方式配置即可。二是EntityManager的初始化,通过SharedEntityManagerCreator包装了下,是因为我们业务的查询通过继承SimpleJpaRepository来扩展功能的,通过SharedEntityManagerCreator包装保留了SimpleJpaRepository内部定义的事务功能。三是需要给所有的业务数据源的配置添加@Primary注解,让sprign上下文默认使用业务数据源 加解密数据源配置 /** * @author: kl @kailing.pub * @date: 2020/5/18 */ @Configuration @EnableConfigurationProperties({JpaProperties.class,SpringBootEncryptRuleConfigurationProperties.class, SpringBootPropertiesConfigurationProperties.class}) @AutoConfigureAfter({DataSourceAutoConfiguration.class, DataSourceConfiguration.class}) public class EncryptDataSourceConfiguration { private final SpringBootPropertiesConfigurationProperties props; private final SpringBootEncryptRuleConfigurationProperties encryptRule; private final JpaProperties jpaProperties; private final DataSource dataSource; public EncryptDataSourceConfiguration(SpringBootPropertiesConfigurationProperties props, SpringBootEncryptRuleConfigurationProperties encryptRule, JpaProperties jpaProperties, DataSource dataSource) { this.props = props; this.encryptRule = encryptRule; this.jpaProperties = jpaProperties; this.dataSource = dataSource; } @Bean public DataSource encryptDataSource() throws SQLException { return EncryptDataSourceFactory.createDataSource(dataSource, new EncryptRuleConfigurationYamlSwapper().swap(encryptRule), props.getProps()); } @Bean public EntityManagerFactory encryptEntityManagerFactory() throws SQLException { HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); vendorAdapter.setDatabase(Database.MYSQL); LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); factory.setJpaVendorAdapter(vendorAdapter); factory.setPersistenceUnitName("encryptPersistenceUnit"); factory.setPackagesToScan(Constants.BASE_PACKAGES); factory.setDataSource(encryptDataSource()); factory.setJpaPropertyMap(jpaProperties.getProperties()); factory.afterPropertiesSet(); return factory.getObject(); } @Bean public EntityManager encryptEntityManager() throws SQLException { return SharedEntityManagerCreator.createSharedEntityManager(encryptEntityManagerFactory()); } @Bean public PlatformTransactionManager encryptTransactionManager() throws SQLException { JpaTransactionManager txManager = new JpaTransactionManager(); txManager.setEntityManagerFactory(encryptEntityManagerFactory()); return txManager; } } 加解密数据源的源来自于业务数据源,只是在这里给业务数据源又代理了一层加解密的逻辑。加解密的规则配置采用了sharding-spring-boot-starter包中的映射类,所以可以保留和spring boot配置方式一致。 加解密数据源的使用 在使用时,因为默认使用的是业务数据源,所以需要在需要加解密的地方通过@Qualifier("encryptEntityManager")显示的注入加解密的数据源代理,如: @Repository public class AccountRepository extends AbstractJpaRepository { public AccountRepository(@Qualifier("encryptEntityManager") EntityManager em) { super(AccountModel.class, em); } @Override @Transactional(transactionManager = "encryptTransactionManager") public S save(S entity) { return super.save(entity); } } 另,需要手动指定加解密数据源的事务管理器。 如果你使用了JpaRepository等接口,在启用@EnableJpaRepositories的注解里,默认装载的业务数据源配置的EntityManagerFactory实例,需要加解密时,要设置如下参数: @EnableJpaRepositories(basePackages = "com.xxx",entityManagerFactoryRef = "encryptEntityManagerFactory",transactionManagerRef = "encryptTransactionManager") 结语 没有十全十美的组件,Sharding-JDBC的数据脱敏方案已经趋向于完美了。由于组件本身的架构设计,确实不好做到100%的兼容。在发现加解密组件不支持子查询时,博主发现实现这个功能很简单,尝试过向官方提交这个功能的pr。经过对组件的进一步了解发现,从全局考虑实现这个功能非常复杂,也就放弃了,熟悉java的DBA有志之士可以去试试。目前这个多数据源模式可以很好的解决了sql兼容问题,如果有更好的集成方案,欢迎在下面留言交流 作者简介: 陈凯玲,2016年5月加入凯京科技。负责基础架构中间件的迭代,救火队队长。独立博客KL博客(http://www.kailing.pub)博主。

优秀的个人博客,低调大师

将物联网整合到医疗保健,农业和运输用例中

云栖号资讯:【点击查看更多行业资讯】在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! 物联网技术每天都在扩展到新的领域。尤其是医疗,农业和运输行业,将从这些新技术中获得不可思议的收益。 当你把一个传统的设备,比如手表,加上计算、连接和一层智能,你最终会改变用户体验,这难道不是很吸引人吗? 什么是物联网?我们将物理设备连接到internet以改变用户体验。对于物联网用例,你可以想象出一系列的可能性。智能家居可能是大众媒体最常讨论的话题。想象一下你的车库门,家里的灯和音响都在一起工作,当你到家的时候,它们能创造一个更好的氛围,根据你的喜好和需要调节你的环境。 现在,对于商业用例,可以想象一个农民通过智能手机管理整个农场。安全摄像头、灌溉设备、温度传感器都可以连接起来,这样它们就能更好地协同工作。在一个城市的公共交通系统中,你可以管理交通、公共汽车时刻表、停车点和维护,你可以为生活在城市中的人们创造更好的体验。 将物联网和机器学习带入医疗保健 当今的医疗保健机构越来越多地采用可提供多种远程监控,医疗保健交付和家庭诊断功能的技术,这些技术可以利用机器学习和物联网。如今,智能医疗系统集成了全天候的实时数据流,用药提醒和实时医疗诊断,所有这些都减少了对医院就诊的需求。 IoT在医疗保健行业有时被称为“医疗物联网(IoMT)”。它由医疗设备,患者监视工具,可穿戴设备和其他传感器组成,这些设备可以通过互联网将信号发送到其他设备。这些工具生成大量数据,必须对其进行存储,集成和分析,以便针对慢性病管理和急诊患者护理需求生成可行的见解。 预测住院环境中患者的恶化或感染需要床边设备的持续反馈,而诸如蓝牙的血压袖带,体重计和药瓶之类的家庭监控工具可以使患者遵守诊所以外的慢性病管理协议。传感器,机器学习,大数据分析和区块链可能都是IoMT潜在有用的技术。 农业行业的物联网用例 借助物联网,农民可以监控和管理每一个细微的细节,从土壤和单个植物的水分,营养和酸度含量到有害生物和当地天气模式,再到牛的健康和每分钟的运动情况。 随着这些元素之间的联系,农民可以从大数据分析中获得巨大的洞察力,从而可以做出更好的决策。 物联网和遥感技术有助于发掘新的创新。例如,GroundCover使用农场图像来绘制和预测马铃薯的产量;其CanopyCheck应用程序使用智能手机向农民添加地理位置信息。孟山都的综合农业系统(IFS)使用分析工具,例如 “ FieldScript”,提供有关种植,精确播种和遗传增益的建议。GrowSafe Systems使用传感器和分析来跟踪牛的运动和健康状况,并帮助农民应对疾病的检测和预防。 农业物联网可以带来一系列好处。它可以通过自动化过程(例如打开远程农业设备)来提高农业工人的生产率,这也降低了差旅成本。还可以为牲畜提供响应速度更快的医疗保健服务,并且可以通过无线传感器跟踪其健康指标。物联网以及随附的分析解决方案可以揭示对作物季节计划的新见解,提高食品安全性并减轻作物歉收风险。 运输中的物联网用例 随着物联网继续连接我们周围的世界,一些最激动人心的数字化转型正在运输行业中出现。我们已经看到城市和州正在试行和部署基于IoT的技术,这些技术将运输基础设施,公共交通系统,道路,高速公路,标牌和路灯连接到车辆以及介于两者之间的所有内容。这些连接在一起有望创造出简化的运输方式,同时提高安全性和可持续性。 未来,人工智能和机器学习将在交通运输领域变得越来越重要,从而可以实现更自动化,更具预测性的分析和更好的决策制定。AI和ML可以预测何时部署应急车辆,拖车,扫雪机等,从而提高道路和高速公路的安全性和效率。例如,通过汇总和分析当前和历史天气,小气候和交通数据,运输机构可以提前将撒盐的卡车部署到经常结冰的道路上。随后,他们可以预测何时在道路的超局部区域可能出现雾气并警告驾驶员。 这些类型的预测性决策,由人工智能和人工智能驱动,使得交通运输在减少干扰的情况下运行,降低成本,确保更安全的出行。 【云栖号在线课堂】每天都有产品技术专家分享!课程地址:https://yqh.aliyun.com/zhibo 立即加入社群,与专家面对面,及时了解课程最新动态!【云栖号在线课堂 社群】https://c.tb.cn/F3.Z8gvnK 原文发布时间:2020-04-13本文作者:物联网IoT996本文来自:“今日头条”,了解相关信息可以关注“今日头条”

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册