用户冻结/解冻使用管理员在后台系统对用户的惩罚措施。对于发布不当言论或者违法违规内容的用户,可以暂时、永久禁止其登录,评论,发布动态、
后台中解冻/冻结,就是将用户状态写入数据库中
APP端用户在进行登录,评论,发布动态时检测Redis中冻结状态

//用户冻结
@PostMapping("/users/freeze")
public ResponseEntity freeze(@RequestBody Map params) {Map map = managerService.userFreeze(params);return ResponseEntity.ok(map);
}
//用户冻结
public Map userFreeze(Map params) {Integer freezingTime = (Integer) params.get("freezingTime");Long userId = (Long) params.get("userId");int days = 0;if (freezingTime == 1) {days = 3;}if (freezingTime == 2) {days = 7;}if (freezingTime == 3) {days = -1;}String value = JSON.toJSONString(params);redisTemplate.opsForValue().set(Constants.FREEZE_USER+userId,value,days, TimeUnit.MINUTES);Map map = new HashMap();map.put("message","冻结成功");return map;
}
//用户解冻
@PostMapping("/users/unfreeze")
public ResponseEntity unfreeze(@RequestBody Map params) {Map map = managerService.userUnfreeze(params);return ResponseEntity.ok(map);
}
//用户解冻
public Map userUnfreeze(Map params) {Long userId = (Long) params.get("userId");String reasonsForThawing = (String) params.get("reasonsForThawing");redisTemplate.delete(Constants.FREEZE_USER+userId);Map map = new HashMap();map.put("message","解冻成功");return map;
}
添加字段
//用户状态,1为正常,2为冻结
@TableField(exist = false)
private String userStatus = "1";
public ResponseEntity findById(Long userId) {UserInfo info = userInfoApi.findById(userId);if(redisTemplate.hasKey(Constants.FREEZE_USER+info.getId())) {info.setUserStatus("2");}return ResponseEntity.ok(info);
}
@Service
public class UserFreezeService {@Autowiredprivate RedisTemplate redisTemplate;public void checkUserStatus(Integer state,Long userId) {String value = redisTemplate.opsForValue().get(Constants.FREEZE_USER + userId);if(!StringUtils.isEmpty(value)) {Map map = JSON.parseObject(value, Map.class);Integer freezingRange = (Integer) map.get("freezingRange");if(freezingRange == state) {throw new BusinessException(ErrorResult.builder().errMessage("您的账号被冻结!").build());}}}
}
后台系统首页中,显示各种统计数据,比如:累计用户数、新增用户数、登录次数等内容。
1、探花系统将用户操作日志写入RabbitMQ
2、管理后台获取最新消息,构造日志数据存入数据库
3、加入统计表,定时统计

1、探花系统将用户操作日志写入RabbitMQ
2、管理后台获取最新消息,构造日志数据存入数据库
探花交友所需的第三方服务组件,已经以Docker-Compose准备好了。仅仅需要进入相关目录,以命令形式启动运行即可
#进入目录
cd /root/docker-file/rmq/
#创建容器并启动
docker-compose up –d
#查看容器
docker ps -a
服务地址:192.168.136.160:5672
管理后台:http://192.168.136.160:15672/
探花项目间使用RabbitMQ收发消息,这里采用topic类型消息
日志消息key规则:log.xxx

package com.tanhua.model.domain;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Log {/*** id*/private Long id;/*** 用户id*/private Long userId;/*** 操作时间*/private String logTime;/*** 操作类型,* 0101为登录,0102为注册,* 0201为发动态,0202为浏览动态,0203为动态点赞,0204为动态喜欢,0205为评论,0206为动态取消点赞,0207为动态取消喜欢,* 0301为发小视频,0302为小视频点赞,0303为小视频取消点赞,0304为小视频评论*/private String type;/*** 登陆地点*/private String place;/*** 登陆设备*/private String equipment;public Log(Long userId, String logTime, String type) {this.userId = userId;this.logTime = logTime;this.type = type;}
}
package com.tanhua.model.domain;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.Date;@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Analysis{private Long id;/*** 日期*/private Date recordDate;/*** 新注册用户数*/private Integer numRegistered = 0;/*** 活跃用户数*/private Integer numActive = 0;/*** 登陆次数*/private Integer numLogin = 0;/*** 次日留存用户数*/private Integer numRetention1d = 0;private Date created;
}
@Autowired
private AmqpTemplate amqpTemplate;
public void login() {……… //构造Map集合 Map msg = new HashMap<>(); msg.put(“userId”, UserHolder.getUserId().toString()); msg.put(“date", System.currentTimeMillis()); msg.put("type", "0101",); String message = JSON.toJSONString(msg); //发送消息try { amqpTemplate.convertSendAndReceive("tanhua.log.exchange","log.user",message); }catch (Exception e) {e.printStackTrace();} ………
}
@Component
public class LogListener {@Autowiredprivate LogMapper logMapper;@RabbitListener(bindings = @QueueBinding(value = @Queue(value = "tanhua.log.queue",durable = "true"),exchange = @Exchange(value = "tanhua.log.exchange",type = ExchangeTypes.TOPIC),key = {"log.*"}))public void listenCreate(String message) throws Exception {try {Map map = JSON.parseObject(message);//1、获取数据Long userId = (Long) map.get("userId");String date = (String) map.get("date");String objId = (String) map.get("objId");String type = (String) map.get("type");//2、保存到数据库Log log = new Log(userId,date,type);logMapper.insert(log);} catch (Exception e) {e.printStackTrace();}}
}
package com.tanhua.server.service;import com.alibaba.fastjson.JSON;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;@Service
public class MqMessageService {@Autowiredprivate AmqpTemplate amqpTemplate;//发送日志消息public void sendLogService(Long userId,String type,String key,String busId) {try {Map map = new HashMap();map.put("userId",userId.toString());map.put("type",type);map.put("logTime",new SimpleDateFormat("yyyy-MM-dd").format(new Date()));map.put("busId",busId);String message = JSON.toJSONString(map);amqpTemplate.convertAndSend("tanhua.log.exchange","log."+key,message);} catch (AmqpException e) {e.printStackTrace();}}//发送动态审核消息public void sendAudiService(String movementId) {try {amqpTemplate.convertAndSend("tanhua.audit.exchange","audit.movement",movementId);} catch (AmqpException e) {e.printStackTrace();}}
}
项目中大量方法需要改造,加入消息处理。
不易维护且存在耦合
解决方法:使用AOP + 自定义注解
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogConfig {//动态获取方法参数,支持SpringELString objId() default "";//路由的keyString key();//日志类型String type();
}
@Component
@Aspect
public class LogAspect {@Autowiredprivate AmqpTemplate amqpTemplate;@Before(value="execution(* com.tanhua.server.service.*.*(..)) && @annotation(config)")public void checkUserState(JoinPoint pjp , LogConfig config) throws Throwable {//解析SpringEL获取动态参数MethodSignature signature = (MethodSignature) pjp.getSignature();String objId = parse(config.objId(), signature.getParameterNames(), pjp.getArgs());//构造Map集合Map msg = new HashMap<>();msg.put("userId", UserHolder.getUserId());msg.put("date", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));msg.put("objId", objId);msg.put("type", config.type());String message = JSON.toJSONString(msg);//发送消息try {amqpTemplate.convertSendAndReceive("tanhua.log.exchange","log."+config.key(),message);}catch (Exception e) {e.printStackTrace();}}public String parse(String expression, String[] paraNames,Object [] paras) {if(StringUtils.isEmpty(expression)) return "";StandardEvaluationContext context = new StandardEvaluationContext();for(int i=0;icontext.setVariable(paraNames[i], paras[i]);}Expression exp = new SpelExpressionParser().parseExpression(expression);Object value = exp.getValue(context);return value == null ? "" : value.toString();}
}
//根据id查询
@LogConfig(type = "0202",key = "movement",objId = "#movementId")
public MovementsVo findById(String movementId) {//1、调用api根据id查询动态详情Movement movement = movementApi.findById(movementId);//2、转化vo对象if(movement != null) {UserInfo userInfo = userInfoApi.findById(movement.getUserId());return MovementsVo.init(userInfo,movement);}else {return null;}
}
在实际项目开发中,除了Web应用、SOA服务外,还有一类不可缺少的,那就是定时任务调度。定时任务的场景可以说非常广泛:
某些网站会定时发送优惠邮件;
银行系统还款日信用卡催收款;
某些应用的生日祝福短信等。
那究竟何为定时任务调度,一句话概括就是:基于给定的时间点、给定的时间间隔、自动执行的任务
@SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
@MapperScan("com.tanhua.admin.mapper")
@EnableScheduling //开启定时任务支持
public class AdminServerApplication {public static void main(String[] args) {SpringApplication.run(AdminServerApplication.class,args);}
}
@Component
public class AnalysisTask {/*** 配置时间规则*/@Scheduled( cron = "0/20 * * * * ? ")public void analysis() throws ParseException {//业务逻辑String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());System.out.println("当前时间:"+time);}
}
对于定时任务,我们使用的时候主要是注重两个方面,一个是定时任务的业务,另一个就是Cron表达式。
**Cron 表达式支持到六个域 **
| 名称 | 是否必须 | 允许值 | 特殊字符 |
|---|---|---|---|
| 秒 | 是 | 0-59 | , - * / |
| 分 | 是 | 0-59 | , - * / |
| 时 | 是 | 0-23 | , - * / |
| 日 | 是 | 1-31 | , - * ? / L W C |
| 月 | 是 | 1-12 或 JAN-DEC | , - * / |
| 周 | 是 | 1-7 或 SUN-SAT | , - * ? / L C # |
月份和星期的名称是不区分大小写的。FRI 和 fri 是一样的。 域之间有空格分隔
@Component
public class AnalysisTask {@Autowiredprivate AnalysisService analysisService;/*** 配置时间规则*/@Scheduled( cron = "0/20 * * * * ? ")public void analysis() throws ParseException {//业务逻辑String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());System.out.println("开始统计:"+time);//调logService完成日志统计analysisService.analysis();System.out.println("结束统计");}
}
/*** 定时统计日志数据到统计表中* 1、查询tb_log表中的数 (每日注册用户数,每日登陆用户,活跃的用户数据,次日留存的用户)* 2、构造AnalysisByDay对象* 3、完成统计数据的更新或者保存*/
public void analysis() throws ParseException {String todayStr = new SimpleDateFormat("yyyy-MM-dd").format(new Date());String yestodayStr = DateUtil.yesterday().toString("yyyy-MM-dd"); //工具类//1、统计每日注册用户数Integer numRegistered = logMapper.queryByTypeAndLogTime("0102",todayStr);//2、统计每日登陆用户Integer numLogin = logMapper.queryByTypeAndLogTime("0101",todayStr);//3、统计活跃的用户数Integer numActive = logMapper.queryByLogTime(todayStr);//4、统计次日留存的用户数Integer numRetention1d = logMapper.queryNumRetention1d(todayStr, yestodayStr);//5、根据当前时间查询AnalysisByDay数据QueryWrapper qw = new QueryWrapper<>();Date todatDate = new SimpleDateFormat("yyyy-MM-dd").parse(todayStr);qw.eq("record_date", todatDate);Analysis analysis = analysisMapper.selectOne(qw);if(analysis == null) {//7、如果不存在,保存analysis = new Analysis();analysis.setRecordDate(todatDate);analysis.setNumRegistered(numRegistered);analysis.setNumLogin(numLogin);analysis.setNumActive(numActive);analysis.setNumRetention1d(numRetention1d);analysis.setCreated(new Date());analysisMapper.insert(analysis);}else{//8、如果存在,更新analysis.setNumRegistered(numRegistered);analysis.setNumLogin(numLogin);analysis.setNumActive(numActive);analysis.setNumRetention1d(numRetention1d);analysisMapper.updateById(analysis);}}
public interface LogMapper extends BaseMapper {@Select("SELECT COUNT(DISTINCT user_id) FROM tb_log WHERE TYPE=#{type} AND log_time=#{logTime}")Integer queryByTypeAndLogTime(@Param("type") String type, @Param("logTime") String logTime); //根据操作时间和类型@Select("SELECT COUNT(DISTINCT user_id) FROM tb_log WHERE log_time=#{logTime}")Integer queryByLogTime(String logTime); //展示记录时间查询@Select("SELECT COUNT(DISTINCT user_id) FROM tb_log WHERE log_time=#{today} AND user_id IN (\n " +" SELECT user_id FROM tb_log WHERE TYPE=\"0102\" AND log_time=#{yestoday} \n " +")")Integer queryNumRetention1d(@Param("today") String today,@Param("yestoday") String yestoday); //查询次日留存
}
为了方便操作,可以通过以下单元测试方法。保存若干操作数据
package com.tanhua.manager.test;import com.tanhua.manager.domain.Log;
import com.tanhua.manager.mapper.LogMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.util.Random;@RunWith(SpringRunner.class)
@SpringBootTest
public class LogTest {@Autowiredprivate LogMapper logMapper;private String logTime = "";//模拟登录数据public void testInsertLoginLog() {for (int i = 0; i < 5; i++) {Log log = new Log();log.setUserId((long)(i+1));log.setLogTime(logTime);log.setType("0101");logMapper.insert(log);}}//模拟注册数据public void testInsertRegistLog() {for (int i = 0; i < 10; i++) {Log log = new Log();log.setUserId((long)(i+1));log.setLogTime(logTime);log.setType("0102");logMapper.insert(log);}}//模拟其他操作public void testInsertOtherLog() {String[] types = new String[]{"0201","0202","0203","0204","0205","0206","0207","0301","0302","0303","0304"};for (int i = 0; i < 10; i++) {Log log = new Log();log.setUserId((long)(i+1));log.setLogTime(logTime);int index = new Random().nextInt(10);log.setType(types[index]);logMapper.insert(log);}}@Testpublic void generData() {testInsertLoginLog();testInsertRegistLog();testInsertOtherLog();}
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class AnalysisSummaryVo {/*** 累计用户数*/private Long cumulativeUsers;/*** 过去30天活跃用户数*/private Long activePassMonth;/*** 过去7天活跃用户*/private Long activePassWeek;/*** 今日新增用户数量*/private Long newUsersToday;/*** 今日新增用户涨跌率,单位百分数,正数为涨,负数为跌*/private BigDecimal newUsersTodayRate;/*** 今日登录次数*/private Long loginTimesToday;/*** 今日登录次数涨跌率,单位百分数,正数为涨,负数为跌*/private BigDecimal loginTimesTodayRate;/*** 今日活跃用户数量*/private Long activeUsersToday;/*** 今日活跃用户涨跌率,单位百分数,正数为涨,负数为跌*/private BigDecimal activeUsersTodayRate;
}
@RestController
@RequestMapping("/dashboard")
public class DashboardController {@Autowiredprivate AnalysisService analysisService;/*** 概要统计信息*/@GetMapping("/dashboard/summary")public AnalysisSummaryVo getSummary() {AnalysisSummaryVo analysisSummaryVo = new AnalysisSummaryVo();DateTime dateTime = DateUtil.parseDate("2020-09-08");//累计用户数analysisSummaryVo.setCumulativeUsers(Long.valueOf(1000));//过去30天活跃用户analysisSummaryVo.setActivePassMonth(this.analysisService.queryActiveUserCount(dateTime, -30));//过去7天活跃用户analysisSummaryVo.setActivePassWeek(this.analysisService.queryActiveUserCount(dateTime, -7));//今日活跃用户analysisSummaryVo.setActiveUsersToday(this.analysisService.queryActiveUserCount(dateTime, 0));//今日新增用户analysisSummaryVo.setNewUsersToday(this.analysisService.queryRegisterUserCount(dateTime, 0));//今日新增用户涨跌率,单位百分数,正数为涨,负数为跌analysisSummaryVo.setNewUsersTodayRate(computeRate(analysisSummaryVo.getNewUsersToday(),this.analysisService.queryRegisterUserCount(dateTime, -1)));//今日登录次数analysisSummaryVo.setLoginTimesToday(this.analysisService.queryLoginUserCount(dateTime, 0));//今日登录次数涨跌率,单位百分数,正数为涨,负数为跌analysisSummaryVo.setLoginTimesTodayRate(computeRate(analysisSummaryVo.getLoginTimesToday(),this.analysisService.queryLoginUserCount(dateTime, -1)));return analysisSummaryVo;}private static BigDecimal computeRate(Long current, Long last) {BigDecimal result;if (last == 0) {// 当上一期计数为零时,此时环比增长为倍数增长result = new BigDecimal((current - last) * 100);} else {result = BigDecimal.valueOf((current - last) * 100).divide(BigDecimal.valueOf(last), 2, BigDecimal.ROUND_HALF_DOWN);}return result;}private static String offsetDay(Date date,int offSet) {return DateUtil.offsetDay(date,offSet).toDateStr();}
}
/*** 查询活跃用户的数量*/
public Long queryActiveUserCount(DateTime today, int offset) {return this.queryUserCount(today, offset, "num_active");
}/*** 查询注册用户的数量*/
public Long queryRegisterUserCount(DateTime today, int offset) {return this.queryUserCount(today, offset, "num_registered");
}/*** 查询登录用户的数量*/
public Long queryLoginUserCount(DateTime today, int offset) {return this.queryUserCount(today, offset, "num_login");
}private Long queryAnalysisCount(String column,String today,String offset){return analysisMapper.sumAnalysisData(column,leDate,dtDate);
}
public interface AnalysisMapper extends BaseMapper {@Select("select sum(${column}) from tb_analysis where record_date > #{leDate} and record_date < #{gtDate}")Long sumAnalysisData(@Param("column") String column, @Param("leDate") String leDate, @Param("gtDate") String gtDate);
}
内容安全是识别服务,支持对图片、视频、文本、语音等对象进行多样化场景检测,有效降低内容违规风险。
目前很多平台都支持内容检测,如阿里云、腾讯云、百度AI、网易云等国内大型互联网公司都对外提供了API。
按照性能和收费来看,探花交友项目使用的就是阿里云的内容安全接口,使用到了图片和文本的审核。
1,前往阿里云官网注册账号
2,打开云盾内容安全产品试用页面,单击立即开通,正式开通服务

3,在AccessKey管理页面管理您的AccessKeyID和AccessKeySecret

文本垃圾内容检测:点击访问
文本垃圾内容Java SDK: 点击访问


图片垃圾内容Java SDK: https://help.aliyun.com/document_detail/53424.html?spm=a2c4g.11186623.6.715.c8f69b12ey35j4
@Data
@ConfigurationProperties("tanhua.green")
public class GreenProperties {/*** 账号*/String accessKeyID;/*** 密钥*/String accessKeySecret;/*** 场景*/String scenes;
}
package com.tanhua.autoconfig.template;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.green.model.v20180509.ImageSyncScanRequest;
import com.aliyuncs.green.model.v20180509.TextScanRequest;
import com.aliyuncs.http.FormatType;
import com.aliyuncs.http.HttpResponse;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.tanhua.autoconfig.properties.GreenProperties;
import lombok.extern.slf4j.Slf4j;import java.util.*;/*** @author: itheima* @create: 2021-05-31 00:46*/
@Slf4j
public class AliyunGreenTemplate {private IAcsClient client;private GreenProperties greenProperties;public AliyunGreenTemplate(GreenProperties greenProperties) {this.greenProperties = greenProperties;try {IClientProfile profile = DefaultProfile.getProfile("cn-shanghai", greenProperties.getAccessKeyID(), greenProperties.getAccessKeySecret());DefaultProfile.addEndpoint("cn-shanghai", "cn-shanghai", "Green", "green.cn-shanghai.aliyuncs.com");client = new DefaultAcsClient(profile);} catch (Exception e) {e.printStackTrace();log.error("Green配置缺失,请补充!");}}/*** 阿里云文本内容检查** @param content* @return map key - suggestion内容* pass:文本正常,可以直接放行,* review:文本需要进一步人工审核,* block:文本违规,可以直接删除或者限制公开* value - 通过,或 出错原因* @throws Exception*/public Map greenTextScan(String content) throws Exception {TextScanRequest textScanRequest = new TextScanRequest();textScanRequest.setAcceptFormat(FormatType.JSON); // 指定api返回格式textScanRequest.setHttpContentType(FormatType.JSON);textScanRequest.setMethod(MethodType.POST); // 指定请求方法textScanRequest.setEncoding("UTF-8");textScanRequest.setRegionId("cn-shanghai");List
@Bean
@ConditionalOnProperty(prefix = "tanhua.green",value = "enable", havingValue = "true")
public AliyunGreenTemplate aliyunGreenTemplate(GreenProperties properties) {return new AliyunGreenTemplate(properties);
}
tanhua:green:enable: trueaccessKeyID: LTAI4GKgob9vZ53k2SZdyAC7accessKeySecret: LHLBvXmILRoyw0niRSBuXBZewQ30lascenes: porn,terrorism #色情,暴力
@Autowiredprivate AliyunGreenTemplate template;@Testpublic void test() throws Exception {
// Long data = analysisMapper.sumAnalysisData("num_registered", "2020-09-14", "2020-09-18");
// System.out.println(data);
// Map map = template.greenTextScan("本校小额贷款,安全、快捷、方便、无抵押,随机随贷,当天放款,上门服务");
// map.forEach((k,v)-> System.out.println(k +"--" + v));List list = new ArrayList<>();list.add("http://images.china.cn/site1000/2018-03/17/dfd4002e-f965-4e7c-9e04-6b72c601d952.jpg");Map map = template.imageScan(list);System.out.println("------------");map.forEach((k,v)-> System.out.println(k +"--" + v));}
为了解决程序间耦合关系,这里采用RabbitMQ + 阿里云完成内容审核
用户发布动态,保存到数据库
发送RabbitMQ消息
管理后台监听消息,对内容(文本、图片审核)
更新动态的状态

public void publishMovement(Movement movement, MultipartFile[] imageContent) throws IOException {//1、判断发布动态的内容是否存在if(StringUtils.isEmpty(movement.getTextContent())) {throw new BusinessException(ErrorResult.contentError());}//2、获取当前登录的用户idLong userId = UserHolder.getUserId();//3、将文件内容上传到阿里云OSS,获取请求地址List medias = new ArrayList<>();for (MultipartFile multipartFile : imageContent) {String upload = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());medias.add(upload);}//4、将数据封装到Movement对象movement.setUserId(userId);movement.setMedias(medias);//5、调用API完成发布动态String movementId = movementApi.publish(movement);try {amqpTemplate.convertSendAndReceive("tanhua.audit.exchange","audit.movement",movementId);}catch (Exception e) {e.printStackTrace();}}
@Component
public class MovementListener {@DubboReferenceprivate MovementApi movementApi;@Autowiredprivate AliyunGreenTemplate aliyunGreenTemplate;@RabbitListener(bindings = @QueueBinding(value = @Queue(value = "tanhua.audit.queue",durable = "true"),exchange = @Exchange(value = "tanhua.audit.exchange",type = ExchangeTypes.TOPIC),key = {"audit.movement"}))public void listenCreate(String movementId) throws Exception {try {//1、根据动态id查询动态Movement movement = movementApi.findById(movementId);//对于RocketMQ消息有可能出现重复,解决方法判断 (幂等性)Integer state = 0;if(movement != null && movement.getState() == 0) {Map textScan = aliyunGreenTemplate.greenTextScan(movement.getTextContent());Map imageScan = aliyunGreenTemplate.imageScan(movement.getMedias());if(textScan != null && imageScan != null) {String textSuggestion = textScan.get("suggestion");String imageSuggestion = imageScan.get("suggestion");if ("block".equals(textSuggestion) || "block".equals(textSuggestion)){state = 2;}else if("pass".equals(textSuggestion) || "pass".equals(textSuggestion)) {state = 1;}}}movementApi.update(movementId,state);} catch (Exception e) {e.printStackTrace();}}
}
@Override
public void update(String movementId, Integer state) {Query query = Query.query(Criteria.where("id").in(new ObjectId(movementId)));Update update = Update.update("state", state);mongoTemplate.updateFirst(query,update,Movement.class);
}