【黑马头条】-day04自媒体文章审核-阿里云接口-敏感词分析DFA-图像识别OCR-异步调用MQ
文章目录
- day4学习内容
- 自媒体文章自动审核
- 今日内容
- 1 自媒体文章自动审核
- 1.1 审核流程
- 1.2 内容安全第三方接口
- 1.3 引入阿里云内容安全接口
- 1.3.1 添加依赖
- 1.3.2 导入aliyun模块
- 1.3.3 注入Bean测试
- 2 app端文章保存接口
- 2.1 表结构说明
- 2.2 分布式id
- 2.2.1 分布式id-技术选型
- 2.2.2 雪花算法
- 2.2.3 配置雪花算法
- 2.3 保存app端文章-思路分析
- 2.4 实现接口
- 2.4.1 实现步骤
- 2.4.2 定义feign接口
- 2.4.2.1 导入feign远程调用依赖
- 2.4.2.2 定义文章端远程接口
- 2.4.2.3 导入ArticleDto
- 2.4.3 实现feign接口
- 2.4.4 创建mapper
- 2.4.5 为AparticleConfig设置默认参数
- 2.4.6 在ApArticleService的实现类ApArticleServiceImpl中实现方法
- 2.4.7 启动ArticleApplication
- 3 自媒体文章审核实现
- 3.1 创建审核接口
- 3.2 实现审核接口
- 3.3 启动类扫描feign
- 3.4 测试
- 4 自媒体调用文章微服务feign远程调用服务降级
- 4.1 feign远程调用服务降级处理的逻辑
- 4.2 编写降级逻辑
- 4.3 指定IArticleClient接口指向Feign降级逻辑
- 4.4 加载feign降级逻辑
- 4.5 配置降级策略
- 4.6 测试
- 5 文章审核异步调用
- 5.1 在自动审核的方法加上@Async注解
- 5.2 在文章发布后调用自动审核方法
- 5.3 在启动类中添加注解开启异步调用
- 5.4 综合测试
- 5.5 使用rabbit MQ来完成异步调用
- 5.5.1 引入依赖
- 5.5.2 为微服务配置MQ
- 5.5.3 改造方法,创建监听队列
- 5.5.4 序列化MQ消息
- 5.5.5 加上mq后的综合测试
- 6 自管理敏感词过滤
- 6.1 DFA实现原理
- 6.2 DFA检索过程
- 6.3 实现步骤
- 6.3.1 创建敏感词表
- 6.3.2 将wm_sensitive对应的实体类和mapper导入
- 6.3.3 在阿里云接口前自行进行审查
- 6.3.4 测试
- 7 图片文字敏感词过滤
- 7.1 文字图片识别
- 7.2 Tesseract-OCR
- 7.3 Tess4j案例
- 7.3.1 导入依赖
- 7.3.2 将训练好的分类器放入资源中
- 7.3.3 demo
- 7.3.4 结果
- 7.4 图片文字敏感词过滤实现
- 7.4.1 创建工具类
- 7.4.2 工具类被其他微服务使用
- 7.4.3 在微服务中配置
- 7.4.4 添加实现
- 8 静态文件生成
- 8.1 实现思路
- 8.1.1 生成minio接口和实现,并且异步调用
- 8.1.2 修改saveArticle逻辑
- 8.1.3 开启异步调用
- 8.1.4 测试
day4学习内容
自媒体文章自动审核
今日内容
1 自媒体文章自动审核
1.1 审核流程
1.2 内容安全第三方接口
1.3 引入阿里云内容安全接口
1.3.1 添加依赖
在heima-leadnews-common包下引入依赖
<dependency><groupId>com.aliyun</groupId><artifactId>aliyun-java-sdk-core</artifactId><version>4.1.1</version>
</dependency>
<dependency><groupId>com.aliyun</groupId><artifactId>aliyun-java-sdk-green</artifactId><version>3.6.6</version>
</dependency>
<dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><version>2.0.9</version>
</dependency>
<dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>2.8.3</version>
</dependency>
1.3.2 导入aliyun模块
放入heima-leadnews-common模块下的com.heima.common
哪个微服务使用,就在哪个微服务的nacos中配置
在heima-leadnews-wemedia中的nacos配置中心添加以下配置:
aliyun:accessKeyId: LTAI5tCWHCcfvqQzu8k2oKmXsecret: auoKUFsghimbfVQHpy7gtRyBkoR4vc
#aliyun.scenes=porn,terrorism,ad,qrcode,live,logoscenes: terrorism
1.3.3 注入Bean测试
在resource中META-INF的spring-factories中自动配置
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.heima.common.exception.ExceptionCatch,\com.heima.common.aliyun.GreenTextScan,\com.heima.common.aliyun.GreenImageScan
在测试类中进行测试
@SpringBootTest(classes = WemediaApplication.class)
@RunWith(SpringRunner.class)
public class AliyunTest {@Autowiredprivate GreenTextScan greenTextScan;@Autowiredprivate GreenImageScan greenImageScan;@Autowiredprivate FileStorageService fileStorageService;@Testpublic void testScanText() throws Exception {Map map = greenTextScan.greeTextScan("我是一个好人,冰毒");System.out.println(map);}@Testpublic void testScanImage() throws Exception {byte[] bytes = fileStorageService.downLoadFile("http://192.168.200.130:9000/leadnews/2021/04/26/ef3cbe458db249f7bd6fb4339e593e55.jpg");Map map = greenImageScan.imageScan(Arrays.asList(bytes));System.out.println(map);}
}
2 app端文章保存接口
2.1 表结构说明
2.2 分布式id
2.2.1 分布式id-技术选型
2.2.2 雪花算法
2.2.3 配置雪花算法
第一:在实体类中的id上加入如下配置,指定类型为id_worker
@TableId(value = "id",type = IdType.ID_WORKER)
private Long id;
第二:在application.yml文件中配置数据中心id和机器id
在文章的微服务的nacos配置中leadnews-article中添加
spring:datasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/leadnews_article?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=falseusername: rootpassword: 123sjbsjb# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:mapper-locations: classpath*:mapper/*.xml# 设置别名包扫描路径,通过该属性可以给包中的类注册别名type-aliases-package: com.heima.model.article.pojos#雪花算法global-config:datacenter-id: 1workerId: 1
minio:accessKey: miniosecretKey: minio123bucket: leadnewsendpoint: http://192.168.204.129:9000readPath: http://192.168.204.129:9000
2.3 保存app端文章-思路分析
2.4 实现接口
2.4.1 实现步骤
2.4.2 定义feign接口
2.4.2.1 导入feign远程调用依赖
在heima-leadnews-feign-api的pom.xml中导入依赖
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.4.2.2 定义文章端远程接口
heima-leadnews-feign-api定义com.heima.apis.article.IArticleClient接口
@FeignClient(value = "leadnews-article")
@FeignClient指定文章远程调用接口名称
@FeignClient(value = "leadnews-article")
public interface IArticleClient {@PostMapping("/api/v1/article/save")public ResponseResult saveArticle(@RequestBody ArticleDto dto) ;
}
2.4.2.3 导入ArticleDto
在heima-leadnews-model模块下com.heima.model.article.dto中导入ArticleDto类
@Data
public class ArticleDto extends ApArticle {/*** 文章内容*/private String content;
}
2.4.3 实现feign接口
在heima-leadnews-service模块下的heima-leadnews-article模块下创建com.heima.article.feign.ArticleClient类
@RestController
public class ArticleClient implements IArticleClient {@Autowiredprivate ApArticleService apArticleService;@PostMapping("/api/v1/article/save")@Overridepublic ResponseResult saveArticle(@RequestBody ArticleDto dto) {return apArticleService.saveArticle(dto);}
}
2.4.4 创建mapper
在heima-leadnews-service模块下的heima-leadnews-article模块下创建com.heima.article.mapper.ApArticleConfigMapper接口
@Mapper
public interface ApArticleConfigMapper extends BaseMapper<ApArticleConfig> {
}
2.4.5 为AparticleConfig设置默认参数
添加@NoArgsConstructor
public ApArticleConfig(Long articleId) {this.articleId = articleId;this.isDelete = false;this.isDown = false;this.isForward = true;this.isComment = true;
}
添加有参构造
2.4.6 在ApArticleService的实现类ApArticleServiceImpl中实现方法
ApArticleService接口
public interface ApArticleService extends IService<ApArticle>{/*** 加载文章列表* @param dto* @param type 1 加载更多 2 加载最新* @return*/public ResponseResult load(ArticleHomeDto dto, Short type);/*** 保存文章* @param dto* @return*/public ResponseResult saveArticle(ArticleHomeDto dto);
}
实现类,实现saveArticle方法
@Autowired
private ApArticleConfigMapper apArticleConfigMapper;
@Autowired
private ApArticleContentMapper apArticleContentMapper;
/*** 保存文章* @param dto* @return*/
@Override
public ResponseResult saveArticle(ArticleDto dto) {//1.参数检查if(dto == null){return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);}ApArticle apArticle = new ApArticle();//org.springframework.beansBeanUtils.copyProperties(dto, apArticle);//2.判断是否存在idif(dto.getId() == null) {//2.1 不存在id ,新增 文章、内容、配置save(apArticle);//2.1.2 保存文章配置ApArticleConfig apArticleConfig = new ApArticleConfig(apArticle.getId());apArticleConfigMapper.insert(apArticleConfig);//2.1.3 保存文章内容ApArticleContent apArticleContent = new ApArticleContent();apArticleContent.setArticleId(apArticle.getId());apArticleContent.setContent(dto.getContent());apArticleContentMapper.insert(apArticleContent);}else {//2.2 存在id,更新 文章、内容//2.2.1 更新文章updateById(apArticle);//2.2.2 更新文章内容ApArticleContent apArticleContent = apArticleContentMapper.selectOne(Wrappers.<ApArticleContent>lambdaQuery().eq(ApArticleContent::getArticleId, dto.getId()));apArticleContent.setContent(dto.getContent());apArticleContentMapper.updateById(apArticleContent);}//3.返回结果 文章的idreturn ResponseResult.okResult(apArticle.getId());
}
2.4.7 启动ArticleApplication
刚刚是新增,如果是修改。
就会在json中传入id
成功修改
3 自媒体文章审核实现
3.1 创建审核接口
在heima-leadnews-service中heima-leadnews-wemedia中的service新增WmNewAutoScanService接口
public interface WmNewAutoScanService {/*** 自动审核媒体文章*/public void autoScanMediaNews(Integer id);
}
3.2 实现审核接口
@Service
@Slf4j
@Transactional
public class WmNewAutoScanServiceImpl implements WmNewAutoScanService {@Autowiredprivate WmNewsMapper wmNewsMapper;@Qualifier("com.heima.apis.article.IArticleClient")@Autowiredprivate IArticleClient iArticleClient;@Autowiredprivate WmChannelMapper wmChannelMapper;@Autowiredprivate WmUserMapper wmUserMapper;@Overridepublic void autoScanMediaNews(Integer id) {//1.查询自媒体文章WmNews wmNews = wmNewsMapper.selectById(id);if (wmNews == null) {throw new RuntimeException("自媒体文章不存在");}if(wmNews.getStatus().equals(WmNews.Status.SUBMIT.getCode())){Map<String,List<String>> scanMaterialsList = extractImageAndContent(wmNews);//2.调用阿里云接口审核文本内容List<String> contentTexts =scanMaterialsList.get("contentTexts");boolean isTextScan =true;if(!isTextScan)return;//3.调用阿里云接口审核图片内容List<String> imagesUrls =scanMaterialsList.get("imagesUrls");boolean isImageScan =true;if(!isImageScan)return;if(isTextScan && isImageScan) {//审核通过wmNews.setStatus((short) 9);wmNews.setReason("审核通过");}}//4.审核成功保存app端的相关文章数据ArticleDto dto=new ArticleDto();BeanUtils.copyProperties(wmNews,dto);//布局dto.setLayout(wmNews.getType());//频道dto.setChannelId(wmNews.getChannelId());//频道名称WmChannel wmChannel = wmChannelMapper.selectById(wmNews.getChannelId());if(wmChannel!=null){dto.setChannelName(wmChannel.getName());}//作者dto.setAuthorId(Long.valueOf(wmNews.getUserId()));//作者名称WmUser wmUser= wmUserMapper.selectById(wmNews.getUserId());if(wmUser!=null){dto.setAuthorName(wmUser.getName());}//设置文章idif(wmNews.getArticleId()!=null){dto.setId(wmNews.getArticleId());}dto.setCreatedTime(new Date());ResponseResult responseResult = iArticleClient.saveArticle(dto);if(responseResult.getCode().equals(200)){//保存成功wmNews.setArticleId((Long)responseResult.getData());wmNewsMapper.updateById(wmNews);}else{//保存失败throw new RuntimeException("保存app端文章失败");}}private Map<String,List<String>> extractImageAndContent(WmNews wmNews) {//提取文章内容String content = wmNews.getContent();List<String> imagesUrls =new ArrayList<>();List<String> contentTexts =new ArrayList<>();Map<String,List<String>> scanMaterialsList =new HashMap<>();List<Map> maps = JSON.parseArray(content, Map.class);//提取文章图片for (Map map : maps) {if(map.get("type").equals("image")){String imgUrl = (String) map.get("value");imagesUrls.add(imgUrl);}if(map.get("type").equals("text")){String text = (String) map.get("value");contentTexts.add(text);}}scanMaterialsList.put("imagesUrls",imagesUrls);scanMaterialsList.put("contentTexts",contentTexts);return scanMaterialsList;}
}
3.3 启动类扫描feign
调用Feign远程接口时,要在启动类中加入@EnableFeignClients(basePackages = “com.heima.apis”)来对feign的api进行扫描,同时也要引入feign-api模块的依赖
<dependency><groupId>com.heima</groupId><artifactId>heima-leadnews-feign-api</artifactId>
</dependency>
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan("com.heima.wemedia.mapper")
@EnableFeignClients(basePackages = "com.heima.apis")
public class WemediaApplication {public static void main(String[] args) {SpringApplication.run(WemediaApplication.class,args);}@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}
}
3.4 测试
转到WmNewAutoScanService接口中,ctrl+shift+T创建测试类
@SpringBootTest(classes = WemediaApplication.class)
@RunWith(SpringRunner.class)
class WmNewAutoScanServiceTest {@Autowiredprivate WmNewAutoScanService wmNewAutoScanService;@Testvoid autoScanMediaNews() {wmNewAutoScanService.autoScanMediaNews(6236);}
}
4 自媒体调用文章微服务feign远程调用服务降级
4.1 feign远程调用服务降级处理的逻辑
4.2 编写降级逻辑
在heima-leadnews-feign-api模块下编写降级逻辑com.heima.apis.article.fallback.IArticleClientFallback类,实现IArticleClient接口
@Component
public class IArticleClientFallback implements IArticleClient {@Overridepublic ResponseResult saveArticle(ArticleDto dto) {return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"获取数据失败");}
}
4.3 指定IArticleClient接口指向Feign降级逻辑
@FeignClient(value = "leadnews-article",fallback = IArticleClientFallback.class)
@FeignClient(value = "leadnews-article",fallback = IArticleClientFallback.class)
public interface IArticleClient {@PostMapping("/api/v1/article/save")public ResponseResult saveArticle(@RequestBody ArticleDto dto) ;
}
4.4 加载feign降级逻辑
因为IArticleClientFallback是在com.heima.apis.article.fallback包下,并不能被spring通过@Component直接加载
因此需要在使用的微服务中加载feign
如使用的微服务是heima-leadnews-wemedia,所以要在com.heima.wemedia.config下创建InitConfig类加载feign降级策略
@Configuration
@ComponentScan("com.heima.apis.article.fallback")
public class InitConfig {
}
4.5 配置降级策略
要么在bootstrap中开启,要么在nacos中实现热更新
这里采用nacos热更新
feign:# 开启feign对hystrix熔断降级的支持hystrix:enabled: true# 修改调用超时时间client:config:default:connectTimeout: 2000readTimeout: 2000
4.6 测试
当前设置超时2s进行降级,测试一下
在com.heima.article.service.impl.ApArticleServiceImpl类中的saveArticle方法添加睡眠3秒进行测试
@Override
public ResponseResult saveArticle(ArticleDto dto) {try {Thread.sleep(3000);} catch (InterruptedException e) {throw new RuntimeException(e);}//1.参数检查if(dto == null){
这次审核6239
@SpringBootTest(classes = WemediaApplication.class)
@RunWith(SpringRunner.class)
class WmNewAutoScanServiceTest {@Autowiredprivate WmNewAutoScanService wmNewAutoScanService;@Testvoid autoScanMediaNews() {wmNewAutoScanService.autoScanMediaNews(6239);}
}
5 文章审核异步调用
5.1 在自动审核的方法加上@Async注解
Springboot集成异步线程调用
@Override
@Async//表明这是一个异步方法
public void autoScanMediaNews(Integer id) {try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}
5.2 在文章发布后调用自动审核方法
//5.审核文章
wmNewAutoScanService.autoScanMediaNews(wmNews.getId());
@Autowired
private WmNewAutoScanService wmNewAutoScanService;
@Override
public ResponseResult submitNews(WmNewsDto wmNewsDto) {// 0.参数检查if(wmNewsDto == null||wmNewsDto.getContent()==null){return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);}//1. 保存或修改文章WmNews wmNews = new WmNews();BeanUtils.copyProperties(wmNewsDto,wmNews);//1.1 封面if(wmNewsDto.getImages()!=null&& wmNewsDto.getImages().size()>0){String imageStr = StringUtils.join(wmNewsDto.getImages(), ",");wmNews.setImages(imageStr);}//1.2 如果封面为自动-1,则需要手动设置封面规则if(wmNewsDto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)){wmNews.setType(null);}saveOrUpdateWmNews(wmNews);//2.判断是否为草稿,如果为草稿结束当前方法if(wmNews.getStatus().equals(WmNews.Status.NORMAL.getCode())){return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);}//3.不是草稿,保存文章内容与图片素材的关系//3.1 获取文章内容的图片素材List<String> imageList=extractUrlInfo(wmNewsDto.getContent());saveRelativeInfoForContent(imageList,wmNews.getId());//4.不是草稿,保存文章封面图片与图片素材的关系saveRelativeInfoForCover(wmNewsDto,wmNews,imageList);//5.审核文章wmNewAutoScanService.autoScanMediaNews(wmNews.getId());return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}
5.3 在启动类中添加注解开启异步调用
在自媒体引导类中使用@EnableAsync注解开启异步调用
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan("com.heima.wemedia.mapper")
@EnableFeignClients(basePackages = "com.heima.apis")
@EnableAsync//开启异步
public class WemediaApplication {public static void main(String[] args) {SpringApplication.run(WemediaApplication.class,args);}@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}
}
5.4 综合测试
5.5 使用rabbit MQ来完成异步调用
我的异步调用只要在启动类中加入@EnableAsync就报错,迫不得已采用rabbitMQ
5.5.1 引入依赖
在heima-leadnews-service中引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId>
</dependency>
5.5.2 为微服务配置MQ
在heima-leadnews-article和wemedia的配置文件中添加配置
spring:rabbitmq:host: 192.168.204.129port: 5672virtual-host: /username: itcastpassword: 123321
5.5.3 改造方法,创建监听队列
修改heima-leadnews-wemedia下的com.heima.wemedia.service.impl.WmNewAutoScanServiceImpl类中的autoScanMediaNews方法
@Autowired
private RabbitTemplate rabbitTemplate;
@Override
public void autoScanMediaNews(Integer id) {//1.查询自媒体文章WmNews wmNews = wmNewsMapper.selectById(id);if (wmNews == null) {throw new RuntimeException("自媒体文章不存在");}if(wmNews.getStatus().equals(WmNews.Status.SUBMIT.getCode())){Map<String,List<String>> scanMaterialsList = extractImageAndContent(wmNews);//2.调用阿里云接口审核文本内容List<String> contentTexts =scanMaterialsList.get("contentTexts");boolean isTextScan =true;if(!isTextScan)return;//3.调用阿里云接口审核图片内容List<String> imagesUrls =scanMaterialsList.get("imagesUrls");boolean isImageScan =true;if(!isImageScan)return;if(isTextScan && isImageScan) {//审核通过wmNews.setStatus((short) 9);wmNews.setReason("审核通过");}}//4.审核成功保存app端的相关文章数据ArticleDto dto=new ArticleDto();BeanUtils.copyProperties(wmNews,dto);//布局dto.setLayout(wmNews.getType());//频道dto.setChannelId(wmNews.getChannelId());//频道名称WmChannel wmChannel = wmChannelMapper.selectById(wmNews.getChannelId());if(wmChannel!=null){dto.setChannelName(wmChannel.getName());}//作者dto.setAuthorId(Long.valueOf(wmNews.getUserId()));//作者名称WmUser wmUser= wmUserMapper.selectById(wmNews.getUserId());if(wmUser!=null){dto.setAuthorName(wmUser.getName());}//设置文章idif(wmNews.getArticleId()!=null){dto.setId(wmNews.getArticleId());}dto.setCreatedTime(new Date());//2.rabbitmq异步处理Map<String,Object> map=new HashMap<>();map.put("dto",dto);map.put("wmNewsId",id);rabbitTemplate.convertAndSend("article.queue", map);/*ResponseResult responseResult = iArticleClient.saveArticle(dto);if(responseResult.getCode().equals(200)){//保存成功wmNews.setArticleId((Long)responseResult.getData());wmNewsMapper.updateById(wmNews);}else{//保存失败log.error("保存app端文章失败,responseResult: {}", responseResult);throw new RuntimeException("保存app端文章失败");}*/
}
rabbitTemplate.convertAndSend("article.queue", map);
发送到article.queue队列
在heima-leadnews-article模块下创建com.heima.article.mq.ArticleMessageConsumer消费者监听类监听article.queue
@Slf4j
@Component
public class ArticleMessageConsumer {@Autowiredprivate IArticleClient iArticleClient;@Autowiredprivate RabbitTemplate rabbitTemplate;@RabbitListener(bindings =@QueueBinding(value=@Queue(name="article.queue"),exchange=@Exchange(name="article.direct",type= ExchangeTypes.FANOUT)))public void processMessage(Map<String,Object> map) {ObjectMapper objectMapper = new ObjectMapper();Object dto = map.get("dto");Integer id= (Integer) map.get("wmNewsId");LinkedHashMap<String, Object> linkedHashMap = (LinkedHashMap<String, Object>) dto;ArticleDto articleDto = objectMapper.convertValue(linkedHashMap, ArticleDto.class);// 异步处理文章数据ResponseResult responseResult = iArticleClient.saveArticle(articleDto);if(responseResult.getCode().equals(200)){WmNews wmNews = new WmNews();BeanUtils.copyProperties(dto, wmNews);wmNews.setArticleId((Long)responseResult.getData());Map<String,Object> params = new HashMap<>();params.put("id", id);params.put("wmNews", wmNews);params.put("articleId",(Long)responseResult.getData());rabbitTemplate.convertAndSend("wmNews.queue", params);log.info("发送params成功,param: {}", params);}else{//保存失败log.error("保存app端文章失败,responseResult: {}", responseResult);throw new RuntimeException("保存app端文章失败");}}
}
将ResponseResult responseResult = iArticleClient.saveArticle(articleDto);
回填的id发到wmNews.queue
在heima-leadnews-wemedia模块下创建com.heima.wemedia.mq.ReceiveWmNewsId消费者监听类监听wmNews.queue
@Component
@Slf4j
public class ReceiveWmNewsId {@Autowiredprivate WmNewsMapper wmNewsMapper;@RabbitListener(bindings =@QueueBinding(value=@Queue(name="wmNews.queue"),exchange=@Exchange(name="wmNews.direct",type= ExchangeTypes.FANOUT)))public void processMessage(Map<String,Object> map) {ObjectMapper objectMapper = new ObjectMapper();Integer id= (Integer)map.get("id");Object wmNews= map.get("wmNews");Long articleId= (Long)map.get("articleId");LinkedHashMap<String, Object> linkedHashMap = (LinkedHashMap<String, Object>) wmNews;WmNews articleDto = objectMapper.convertValue(linkedHashMap, WmNews.class);WmNews oldwmNews = wmNewsMapper.selectById(id);BeanUtils.copyProperties(wmNews,oldwmNews);oldwmNews.setStatus((short) 9);oldwmNews.setReason("审核通过");oldwmNews.setArticleId(articleId);int i = wmNewsMapper.updateById(oldwmNews);if(i == 0){log.error("更新自媒体文章失败,wmNews: {}", oldwmNews);throw new RuntimeException("更新自媒体文章失败");}}
}
5.5.4 序列化MQ消息
在heima-leadnews-article和wemedia的启动类中添加序列化器
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan("com.heima.wemedia.mapper")
@EnableFeignClients(basePackages = "com.heima.apis")
public class WemediaApplication {public static void main(String[] args) {SpringApplication.run(WemediaApplication.class,args);}@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}@Beanpublic MessageConverter messageConverter(){return new Jackson2JsonMessageConverter();}@Beanpublic RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory, MessageConverter messageConverter) {RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);rabbitTemplate.setMessageConverter(messageConverter);return rabbitTemplate;}
}
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan("com.heima.article.mapper")
public class ArticleApplication {public static void main(String[] args) {SpringApplication.run(ArticleApplication.class,args);}@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}@Beanpublic MessageConverter messageConverter(){return new Jackson2JsonMessageConverter();}@Beanpublic RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory, MessageConverter messageConverter) {RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);rabbitTemplate.setMessageConverter(messageConverter);return rabbitTemplate;}
}
5.5.5 加上mq后的综合测试
测试通过在MQ上也检测到消息
6 自管理敏感词过滤
6.1 DFA实现原理
6.2 DFA检索过程
6.3 实现步骤
6.3.1 创建敏感词表
在leadnews-wemedia数据库中到入wm_sensitive.sql
6.3.2 将wm_sensitive对应的实体类和mapper导入
@Data
@TableName("wm_sensitive")
public class WmSensitive implements Serializable {private static final long serialVersionUID = 1L;/*** 主键*/@TableId(value = "id", type = IdType.AUTO)private Integer id;/*** 敏感词*/@TableField("sensitives")private String sensitives;/*** 创建时间*/@TableField("created_time")private Date createdTime;
}
@Mapper
public interface WmSensitiveMapper extends BaseMapper<WmSensitive> {
}
6.3.3 在阿里云接口前自行进行审查
boolean isSensitive= handleSensitiveWords(contentTexts,wmNews);
if(wmNews.getStatus().equals(WmNews.Status.SUBMIT.getCode())){Map<String,List<String>> scanMaterialsList = extractImageAndContent(wmNews);//2.调用阿里云接口审核文本内容List<String> contentTexts =scanMaterialsList.get("contentTexts");//2.1 敏感词过滤boolean isSensitive= handleSensitiveWords(contentTexts,wmNews);boolean isTextScan =true;if(!isTextScan)return;//3.调用阿里云接口审核图片内容List<String> imagesUrls =scanMaterialsList.get("imagesUrls");boolean isImageScan =true;
@Autowired
private WmSensitiveMapper wmSensitiveMapper;
private boolean handleSensitiveWords(List<String> contentTexts, WmNews wmNews) {boolean isSensitive = true;//1.获取所有敏感词List<WmSensitive> wmSensitiveList = wmSensitiveMapper.selectList(Wrappers.<WmSensitive>lambdaQuery().select(WmSensitive::getSensitives));List<String> collect = wmSensitiveList.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());//2.初始化敏感词库SensitiveWordUtil.initMap(collect);//3.遍历文章内容查看是否包含敏感词for(String contentText:contentTexts){Map<String, Integer> map = SensitiveWordUtil.matchWords(contentText);if(map.size()>0){//4.如果包含敏感词,修改文章状态wmNews.setStatus((short) 2);wmNews.setReason("文章内容包含敏感词");wmNewsMapper.updateById(wmNews);isSensitive = false;break;}}return isSensitive;
}
6.3.4 测试
7 图片文字敏感词过滤
7.1 文字图片识别
7.2 Tesseract-OCR
7.3 Tess4j案例
7.3.1 导入依赖
在heima-leadnews-test模块下的tess4j-demo的模块下导入依赖
<dependency><groupId>net.sourceforge.tess4j</groupId><artifactId>tess4j</artifactId><version>4.1.1</version>
</dependency>
7.3.2 将训练好的分类器放入资源中
7.3.3 demo
在tess4j-demo的Applcation中
public class Application {/*** 识别图片中的文字* @param args*/public static void main(String[] args) {// 1.创建Tesseract对象Tesseract tesseract = new Tesseract();// 2.设置训练库的位置tesseract.setDatapath("D:\\Code\\JavaCode\\HeimaToutiao\\heima-leadnews\\heima-leadnews-test\\tess4j-demo\\src\\main\\resources\\tessdata");// 3.设置识别语言tesseract.setLanguage("chi_sim");// 4.设置识别图片File file = new File("D:\\Code\\JavaCode\\HeimaToutiao\\heima-leadnews\\heima-leadnews-test\\tess4j-demo\\src\\main\\resources\\testdata\\testImage.png");// 5.识别图片try {String result = tesseract.doOCR(file);System.out.println(result.replace("\\n|\\r", ""));} catch (TesseractException e) {e.printStackTrace();}}
}
7.3.4 结果
7.4 图片文字敏感词过滤实现
7.4.1 创建工具类
在heima-leadnews-common中创建com.heima.common.tess4j.Tess4jClient工具类,封装tess4j
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "tess4j")
public class Tess4jClient {private String dataPath;private String language;public String doOCR(BufferedImage image) throws TesseractException {//创建Tesseract对象ITesseract tesseract = new Tesseract();//设置字体库路径tesseract.setDatapath(dataPath);//中文识别tesseract.setLanguage(language);//执行ocr识别String result = tesseract.doOCR(image);//替换回车和tal键 使结果为一行result = result.replaceAll("\\r|\\n", "-").replaceAll(" ", "");return result;}}
7.4.2 工具类被其他微服务使用
想让工具类被其他微服务使用就要拷贝全路径,在当前的resource中的META-INF的spring.factories中添加配置
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.heima.common.exception.ExceptionCatch,\com.heima.common.aliyun.GreenTextScan,\com.heima.common.aliyun.GreenImageScan,\com.heima.common.tess4j.Tess4jClient
7.4.3 在微服务中配置
在heima-leadnews-wemedia中的resource的boostrap.yml中进行配置
tess4j:data-path: D:\Code\JavaCode\HeimaToutiao\heima-leadnews\heima-leadnews-test\tess4j-demo\src\main\resources\tessdatalanguage: chi_sim
7.4.4 添加实现
在WmNewsAutoScanServiceImpl中的handleImageScan方法上添加如下代码
try {for (String image : images) {byte[] bytes = fileStorageService.downLoadFile(image);//图片识别文字审核---begin-----//从byte[]转换为butteredImageByteArrayInputStream in = new ByteArrayInputStream(bytes);BufferedImage imageFile = ImageIO.read(in);//识别图片的文字String result = tess4jClient.doOCR(imageFile);//审核是否包含自管理的敏感词boolean isSensitive = handleSensitiveScan(result, wmNews);if(!isSensitive){return isSensitive;}//图片识别文字审核---end-----imageList.add(bytes);}
}catch (Exception e){e.printStackTrace();
}
8 静态文件生成
8.1 实现思路
我们在保存/修改文章时就应该同时异步的的生成静态文件,生成静态文件上传到minio中
8.1.1 生成minio接口和实现,并且异步调用
在com.heima.article.service.ArticleFreemarkerService接口
生成静态文件,上传到minio中
public interface ArticleFreemarkerService {/*** 生成静态化页面* @param apArticle* @param content*/public void buildArticleToMinio(ApArticle apArticle,String content);
}
@Service
@Slf4j
@Transactional
public class ArticleFreemarkerServiceImpl implements ArticleFreemarkerService {@Autowiredprivate ApArticleContentMapper apArticleContentMapper;@Autowiredprivate Configuration configuration;@Autowiredprivate FileStorageService fileStorageService;@Autowiredprivate ApArticleService apArticleService;/*** 生成静态化页面* @param apArticle* @param content*/@Async@Overridepublic void buildArticleToMinio(ApArticle apArticle, String content) {if(StringUtils.isNotBlank(content)){//1.文章内容通过freemarker生成静态html页面Template template = null;//2 输出流StringWriter writer = new StringWriter();try {template = configuration.getTemplate("article.ftl");//2.1 创建模型Map<String,Object> contentDataModel=new HashMap();//content是固定的,因为article.ftl中有<#if content??>${content}</#if>//因为apArticleContent.getContent()获取的是字符串,所以需要转换成对象contentDataModel.put("content", JSONArray.parseArray(content));//2.2 合成方法template.process(contentDataModel,writer);} catch (Exception e) {throw new RuntimeException(e);}//3.把静态页面上传到minio//3.1 文件流InputStream inputStream = new ByteArrayInputStream(writer.toString().getBytes());String path = fileStorageService.uploadHtmlFile("",apArticle.getId()+".html",inputStream);//4.把静态页面的路径保存到数据库apArticleService.update(Wrappers.<ApArticle>lambdaUpdate().eq(ApArticle::getId,apArticle.getId()).set(ApArticle::getStaticUrl,path));}}
}
8.1.2 修改saveArticle逻辑
修改com.heima.article.service.impl.ApArticleServiceImpl的saveArticle方法,添加buildArticleToMinio
articleFreemarkerService.buildArticleToMinio(apArticle, dto.getContent());
@Autowiredprivate ApArticleConfigMapper apArticleConfigMapper;@Autowiredprivate ApArticleContentMapper apArticleContentMapper;@Autowiredprivate ArticleFreemarkerService articleFreemarkerService;/*** 保存文章* @param dto* @return*/@Overridepublic ResponseResult saveArticle(ArticleDto dto) {//1.参数检查if(dto == null){return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);}ApArticle apArticle = new ApArticle();//org.springframework.beansBeanUtils.copyProperties(dto, apArticle);//2.判断是否存在idif(dto.getId() == null) {//2.1 不存在id ,新增 文章、内容、配置save(apArticle);//2.1.2 保存文章配置ApArticleConfig apArticleConfig = new ApArticleConfig(apArticle.getId());apArticleConfigMapper.insert(apArticleConfig);//2.1.3 保存文章内容ApArticleContent apArticleContent = new ApArticleContent();apArticleContent.setArticleId(apArticle.getId());apArticleContent.setContent(dto.getContent());apArticleContentMapper.insert(apArticleContent);}else {//2.2 存在id,更新 文章、内容//2.2.1 更新文章updateById(apArticle);//2.2.2 更新文章内容ApArticleContent apArticleContent = apArticleContentMapper.selectOne(Wrappers.<ApArticleContent>lambdaQuery().eq(ApArticleContent::getArticleId, dto.getId()));apArticleContent.setContent(dto.getContent());apArticleContentMapper.updateById(apArticleContent);}//异步调用 生成静态文件上传到minio中articleFreemarkerService.buildArticleToMinio(apArticle, dto.getContent());//3.返回结果 文章的idreturn ResponseResult.okResult(apArticle.getId());}
}
8.1.3 开启异步调用
引导类加上@EnableAsyn
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan("com.heima.article.mapper")
@EnableAsync
public class ArticleApplication {public static void main(String[] args) {SpringApplication.run(ArticleApplication.class,args);}@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}@Beanpublic MessageConverter messageConverter(){return new Jackson2JsonMessageConverter();}@Beanpublic RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory, MessageConverter messageConverter) {RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);rabbitTemplate.setMessageConverter(messageConverter);return rabbitTemplate;}
}
8.1.4 测试
查看minio有没有生成
生成成功,查看数据库,有html生成,说明功能成功
相关文章:
【黑马头条】-day04自媒体文章审核-阿里云接口-敏感词分析DFA-图像识别OCR-异步调用MQ
文章目录 day4学习内容自媒体文章自动审核今日内容 1 自媒体文章自动审核1.1 审核流程1.2 内容安全第三方接口1.3 引入阿里云内容安全接口1.3.1 添加依赖1.3.2 导入aliyun模块1.3.3 注入Bean测试 2 app端文章保存接口2.1 表结构说明2.2 分布式id2.2.1 分布式id-技术选型2.2.2 雪…...
新能源充电桩站场AI视频智能分析烟火检测方案及技术特点分析
新能源汽车充电起火的原因多种多样,涉及技术、设备、操作等多个方面。从技术层面来看,新能源汽车的电池管理系统可能存在缺陷,导致电池在充电过程中出现过热、短路等问题,从而引发火灾。在设备方面,充电桩的设计和生产…...
springboot集成logback-spring.xml文件
彩色日志日志分debug和error文件输出,方便开发人员运维日志限制最大保管天数日志限制总量大小占用量GB日志限制单个文件大小MB日志显示最大保留天数屏蔽没用的日志 <?xml version"1.0" encoding"UTF-8"?> <!--~ Copyright (c) 2020…...
centos7 安装 nginx
一、yum 方式安装 1.安装yum工具 sudo yum install yum-utils 2. 安装epel yum install epel-release 3.安装nginx: yum install nginx 4.查看版本 nginx -v 5.设置开机自启动 systemctl enable nginx nginx 常用命令: 1)启动nginx …...
29. UE5 RPG应用GamplayAbility
前面几篇文章,总算把GE给更新完了,GE的基础应用也算讲清楚了。接下来,我们将更新GA的相应的课程了,首先,这一篇先对GA做一个简单的介绍,然后实现一下如何实现给角色应用一个GA。 简介 GamplayAbility 简称…...
http和https的区别!
HTTP 明文传输,数据都是未加密的,安全性较差,HTTPS(SSLHTTP) 数据传输过程是加密的,安全性较好。 使用 HTTPS 协议需要到 CA(Certificate Authority,数字证书认证机构) …...
使用AOP实现打印日志
首先创建annotation.SystemLog类: package com.gjh.annotation;import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;Target(ElementType.METHOD…...
2024年新算法-冠豪猪优化算法(CPO),CPO-RF-Adaboost,CPO优化随机森林RF-Adaboost回归预测-附代码
冠豪猪优化算法(CPO)是一种基于自然界中猪群觅食行为启发的优化算法。该算法模拟了猪群在寻找食物时的集群行为,通过一系列的迭代过程来优化目标函数,以寻找最优解。在这个算法中,猪被分为几个群体,每个群体…...
浅谈高阶智能驾驶-NOA领航辅助的技术与发展
浅谈高阶智能驾驶-NOA领航辅助的技术与发展 附赠自动驾驶学习资料和量产经验:链接 2019年在国内首次试驾特斯拉NOA领航辅助驾驶的时候,当时兴奋的觉得未来已来;2020年在试驾蔚来NOP领航辅助驾驶的时候,顿时不敢小看国内新势力了;现在如果哪家…...
大模型 智能体 智能玩具 智能音箱 构建教程 wukong-robot
视频演示 10:27 一、背景 继上文《ChatGPT+小爱音响能擦出什么火花?》可以看出大伙对AI+硬件的结合十分感兴趣,但上文是针对市场智能音响的AI植入,底层是通过轮询拦截,算是hack兼容,虽然官方有提供开发者接口,也免不了有许多局限性(比如得通过特定指令唤醒),不利于我…...
Clickhouse-表引擎探索之MergeTree
引言 前文曾说过,Clickhouse是一个强大的数据库Clickhouse-一个潜力无限的大数据分析数据库系统 其中一个强大的点就在于支持各类表引擎以用于不同的业务场景。 MergeTree MergeTree系列的引擎被设计用于插入极大量的数据到一张表当中。数据可以以数据片段的形式一…...
网络电视盒子哪个好?小编分享电视盒子品牌排行榜
电视盒子使用频率高,功能丰富,价格划算,是我们日常不可或缺的部分,小编经常会被问到与电视盒子相关的问题,考虑到很多朋友并不了解网络电视盒子哪个好,这次我来分享业内权威电视盒子品牌排行榜,…...
开源模型应用落地-baichuan2模型小试-入门篇(三)
一、前言 相信您已经学会了如何在Windows环境下以最低成本、无需GPU的情况下运行baichuan2大模型。现在,让我们进一步探索如何在Linux环境下,并且拥有GPU的情况下运行baichuan2大模型,以提升性能和效率。 二、术语 2.1. CentOS CentOS是一种基于Linux的自由开源操作…...
景联文科技高质量大模型训练数据汇总!
3月25日,2024年中国发展高层论坛年会上,国家数据局局长刘烈宏在“释放数据要素价值,助力可持续发展”的演讲中表示,中国10亿参数规模以上的大模型数量已超100个。 当前,国内AI大模型发展仍面临诸多困境。其中ÿ…...
【python】正则表达式
文章目录 正则表达式对象re.RegexObjectre.MatchObject符号说明匹配基础匹配?=、?<=、?!、?<!字符类re模块编译正则表达式compile 函数匹配字符串re.matchre.searchre.findall...
学习vue3第十二节(组件的使用与类型)
1、组件的作用用途 目的: 提高代码的复用度,和便于维护,通过封装将复杂的功能代码拆分为更小的模块,方便管理, 当我们需要实现相同的功能时,我们只需要复用已经封装好的组件,而不需要重新编写相…...
flume配置文件后不能跟注释!!
先总结:Flume配置文件后面,不能跟注释,可以单起一行写注释 报错代码: [ERROR - org.apache.flume.SinkRunner$PollingRunner.run(SinkRunner.java:158)] Unable to deliver event. Exception follows. org.apache.flume.EventDel…...
【docker】Dockerfile自定义镜像
📝个人主页:五敷有你 🔥系列专栏:中间件 ⛺️稳中求进,晒太阳 1.Dockerfile自定义镜像 常见的镜像在DockerHub就能找到,但是我们自己写的项目就必须自己构建镜像了。 而要自定义镜像,就…...
webpack项目打包console git分支、打包时间等信息 exec
相关链接 MDN toLocaleString child_process Node.js strftime 格式 代码 buildinfo.js const { execSync, exec } require("child_process"); // exec: 在 Windows 执行 bat 和 cmd 脚本// execSync 同步 // exec 异步// exec 使用方法 // exec(git show -s,…...
Linux centos7离线搭建FTP
1、下载、安装ftp 下载ftp安装包,可以从rpm下载站搜索合适的版本,使用wget命令下载。 wget https://mirrors.aliyun.com/centos/7/os/x86_64/Packages/vsftpd-3.0.2-28.el7.x86_64.rpm 安装: rpm -ivh vsftpd-3.0.2-28.el7.x86_64.rpm 2…...
关于GPT-SoVITS语音合成的效果展示(西游之西天送葬团)
目录 使用效果总结合成效果展示 使用效果总结 使用的是2024年03月21日22点28分更新的版本。 使用起来很方便,从它“自带界面”这点就能看出,易于使用也是目的之一,而且从训练到推理的每个步骤都能在界面中完成。 集成了多个实用工具&#…...
如何安装OceanBase的OBD
选择一:借助 all-in-one 安装包安装 OBD(推荐) OceanBase 社区版的all-in-one安装包是一个集成了多种工具的一键式安装包。它包含了数据库软件本身,以及OBD、OBProxy、OBClient,自4.1版本起,还额外加入了O…...
Unity 读写Excel打包后无法运行可能的解决方案
读写Excel打包后无法运行可能的解决方案 💡.适用于NPOI、EPPlus。 💡.下载 资源包👈,解压后把dll放到Assets目录中再重新打包即可。...
算法沉淀 —— 深度搜索(dfs)
算法沉淀 —— 深度搜索(dfs) 一、计算布尔二叉树的值二、求根节点到叶节点数字之和三、二叉树剪枝四、验证二叉搜索树五、二叉搜索树中第K小的元素 一、计算布尔二叉树的值 【题目链接】:2331. 计算布尔二叉树的值 【题目】: …...
#设计模式#3.1用做松鼠桂鱼来理解抽象工厂(对象创建型模式)
概念:xx工厂,xx产品 区分 工厂是动作,产品是结果(菜品) 概念:抽象xx,具体xx 区分 抽象产品:“中式菜品” 具体产品:“麻婆豆腐”、“宫保鸡丁” 抽象工厂:“…...
adb基本命令
下载安装 adb 概述: ADB 全称为 Android Debug Bridge,起到调试桥的作用,是一个客户端-服务器端程序。其中客户端是用来操作的电脑,服务端是 Android 设备。 下载地址: Windows版本:https://dl.google.com/android/repository/pl…...
小工具实战-Python实现小工具输出字符串大小写转换、字符串统计、编解码、MD5加密
小工具实战-Python实现小工具输出字符串大小写转换、字符串统计、编解码、MD5加密 学习建议字符串大小写转换实现思路部分代码 字符串统计实现思路部分代码: 字符串编解码实现思路部分代码 字符串MD5加密实现思路部分代码 小工具整体设计设计思路工具完整代码实现输…...
MySQL进阶-----索引的语法与SQL性能分析
目录 前言 一、索引语法 1.SQL语法 2.案例演示 二、SQL性能分析 三、慢查询日志 1.开启日志 2.测试样例 四、profile详情 1.开启profile 2.profile测试SQL语句 五、explain详情 1.语法结构 2.执行顺序示例(id) 3.执行性能示例(type) 前言 本…...
Ansible剧本playbooks详解
一、playbook简介 playbook是ansible用于配置,部署和管理托管主机剧本,通过playbook的详细描述,执行其中一系列tasks,playbook字面意思是剧本,现实中由演员按剧本表演,在ansible中由计算机进行安装&#x…...
vue3封装Element导航菜单
1. 导航外层布局 AsideView.vue <template><el-menu:default-active"defaultActive"class"my-menu":collapse"isCollapse":collapse-transition"false"open"handleOpen"close"handleClose"><menu…...
河南省汝州文明建设门户网站/口碑营销什么意思
本文将开始分析TAUB0预分频的代码,其他已发布的代码分析可参看以下链接 一、系统时钟初始化R_SYSTEM_ClockInit(); 二、定时器初始化R_SYSTEM_TimerInit(); 三、UART初始化R_UART_Init(); 四、ADCA0初始化R_ADCA0_Init(); 五、PWMD初始化 六、TAUB0初始化 七、TAUJ0…...
汕头网站建设运营团队/网站优化服务
这篇文章主要介绍了关于mac下brew安装php及扩展,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下Mac HomeBrew [2018-03-31]起弃用homebrew/php,php版本改名(如:php70 > php7.0),无法像以前…...
婺源网站建设/百度经验怎么赚钱
soft 温柔的,和蔼的,宽厚的,温和的 英语释义:not forceful, loud, or easily noticed soft形容人的时候,多指性情温和的、宽厚的、心肠软的、婉转的; soft形容物的时候,可指事物的表面的柔软…...
做网站好处/今日最火的新闻
pandas DataFrame 数据转化为 列表 list的方法 大家好,我叫亓官劼(q guān ji ),在CSDN中记录学习的点滴历程,时光荏苒,未来可期,加油~博客地址为:亓官劼的博客 本文原创为亓官劼&am…...
创业商机网农村/百度官方优化指南
今天又用到了:hover这个伪类选择器,一个小问题搞了我好久,就是关于:hover选择的问题, 先看下css代码 .box:hover span {height: 150px;}接下来是HTML代码 <div class box><span></span> </div&g…...
建设b2c商城网站定/百度自助建站官网
第七章 开发向导 7.1 和ITK 的关系 大部分的elastix代码是基于ITK的。使用ITK意味着可以测试基类(图片类,存储分配)。自然ITK支持的图片格式elastix也支持。C源码可以在多种操作系统上使用多种编译器(最新版本VS2010࿰…...