【黑马头条】-day08平台管理-用户敏感词管理-自媒体文章人工审核


文章目录


平台管理

1 前端静态资源导入

将admin-web放入项目web文件夹中

在这里插入图片描述

1.1 配置heimi-leadnews-admin.conf

在nginx的conf目录下的leadnews.conf目录下创建heimi-leadnews-admin.conf

nginx监听端口8803,添加service_6001路径后转发到heima-admin-gateway的端口51603,通过Nacos路由到对应的heima-leadnews-admin微服务完成访问。

静态资源存放在D:/Code/JavaCode/HeimaToutiao/web/admin-web/展示其目录下的index.html

upstream  heima-admin-gateway{
    server localhost:51603;
}

server {
	listen 8803;
	location / {
		root D:/Code/JavaCode/HeimaToutiao/web/admin-web/;
		index index.html;
	}
	
	location ~/service_6001/(.*) {
		proxy_pass http://heima-admin-gateway/$1;
		proxy_set_header HOST $host;  # 不改变源请求头的值
		proxy_pass_request_body on;  #开启获取请求体
		proxy_pass_request_headers on;  #开启获取请求头
		proxy_set_header X-Real-IP $remote_addr;   # 记录真实发出请求的客户端IP
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  #记录代理信息
	}
}

1.2 配置nginx.conf

在nginx.conf中引入

#user  nobody;
worker_processes  1;

events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
	# 引入自定义配置文件
	include leadnews.conf/*.conf;
}

2 管理员微服务的搭建

2.1 创建管理员微服务

在heima-leadnews-service下创建模块heima-leadnews-admin

在这里插入图片描述

2.2 创建admin表

添加leadnews_admin表到mysql中

在这里插入图片描述

2.3 导入表实体类

在heima-leadnews-model模块下创建com.heima.model.admin.pojos包

导入两个两个实体类AdUserh和ApUserRealname类

在这里插入图片描述

2.4 创建对应实体类的mapper

创建com.heima.admin.mapper.AdUsermapper的mapper接口

@Mapper
public interface AdUsermapper extends BaseMapper<AdUser> {
}

2.5 创建启动类

创建com.heima.admin.AdminApplication启动类

@SpringBootApplication
@EnableDiscoveryClient
@MapperScan("com.heima.admin.mapper")
public class AdminApplication {
    public static void main(String[] args) {
        SpringApplication.run(AdminApplication.class, args);
    }
}

2.6 创建配置文件bootstrap.yml

server:
  port: 51805
spring:
  application:
    name: leadnews-admin
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.204.129:8848
      config:
        server-addr: 192.168.204.129:8848
        file-extension: yml

2.7 在nacos中配置数据库等

关于数据库的等等都需要在Nacos的配置中心进行配置

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/leadnews_admin?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false
    username: root
    password: 123sjbsjb
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  # 设置别名包扫描路径,通过该属性可以给包中的类注册别名
  type-aliases-package: com.heima.model.admin.pojos

minio:
  accessKey: minio
  secretKey: minio123
  bucket: leadnews
  endpoint: http://192.168.204.129:9000
  readPath: http://192.168.204.129:9000

3 登录

3.1 接口定义

接口地址:/login/in

请求方式:POST

请求数据类型:application/json

响应数据类型:*/*

接口描述:

请求示例:

{
	"name": "",
	"password": ""
}

3.2 定义接收的Dto类

heima-leadnews-model模块下的com.heima.model.admin.pojos.dtos包下创建AdUserDto类

@Data
public class AdUserDto {
    private String name;
    private String password;
}

3.3 Controller层

在heima-leadnews-admin模块下创建com.heima.admin.controller.v1.AdUserLoginController类

@RestController
@RequestMapping("/login")
public class AdUserLoginController {
    @Autowired
    private AdUserService adUserService;
    @PostMapping("/in")
    public ResponseResult login(@RequestBody(required=false) AdUserDto dto) {
        return adUserService.login(dto);
    }
}

3.4 Service

接口

public interface AdUserService extends IService<AdUser> {
    /**
     * 登录功能
     * @param dto
     * @return
     */
    public ResponseResult login(AdUserDto dto);
}

实现

@Service
@Transactional
@Slf4j
public class AdUserServiceImpl extends ServiceImpl<AdUsermapper, AdUser> implements AdUserService {
    @Override
    public ResponseResult login(AdUserDto dto) {
        //1.正常登录 用户名、密码
        if(StringUtils.isNotBlank(dto.getName()) && StringUtils.isNotBlank(dto.getPassword())) {
            //1.1 查询用户信息,根据手机号查询用户信息
            AdUser dbUser = getOne(Wrappers.<AdUser>lambdaQuery().eq(AdUser::getName, dto.getName()));
            if(dbUser == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.AP_USER_DATA_NOT_EXIST, "用户不存在");
            }
            //1.2 比对密码
            String salt = dbUser.getSalt();
            String password = dto.getPassword();
            String pwd = DigestUtils.md5DigestAsHex((password + salt).getBytes());
            if(!pwd.equals(dbUser.getPassword())) {
                return ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_PASSWORD_ERROR, "密码错误");
            }
            //1.3 没问题的话,返回数据,生成jwt
            String token = AppJwtUtil.getToken(dbUser.getId().longValue());
            Map<String,Object> map=new HashMap<>();
            map.put("token",token);
            //清空敏感信息,填入需要的信息
            AdUser user = new AdUser();
            user.setId(dbUser.getId());
            user.setName(dbUser.getName());
            user.setNickname(dbUser.getNickname());
            user.setImage(dbUser.getImage());
            user.setPhone(dbUser.getPhone());
            user.setStatus(dbUser.getStatus());
            user.setEmail(dbUser.getEmail());
            user.setLoginTime(dbUser.getLoginTime());
            user.setCreatedTime(dbUser.getCreatedTime());
            map.put("user",user);
            return ResponseResult.okResult(map);
        }else{
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "用户名或密码为空");
        }
    }
}

3.5 测试

启动,Nacos的服务管理中有leadnews-admin

发送POST请求

在这里插入图片描述

访问成功

4 admin网关

4.1 添加依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
     <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
    </dependency>
</dependencies>

4.2 添加网关

在heima-leadnews-gateway模块下创建heima-leadnews-admin-gateway模块

创建com.heima.admin.gateway.util.AppJwtUtil类,用于JWT令牌生成

public class AppJwtUtil {

    // TOKEN的有效期一天(S)
    private static final int TOKEN_TIME_OUT = 3_600;
    // 加密KEY
    private static final String TOKEN_ENCRY_KEY = "MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjY";
    // 最小刷新间隔(S)
    private static final int REFRESH_TIME = 300;

    // 生产ID
    public static String getToken(Long id){
        Map<String, Object> claimMaps = new HashMap<>();
        claimMaps.put("id",id);
        long currentTime = System.currentTimeMillis();
        return Jwts.builder()
                .setId(UUID.randomUUID().toString())
                .setIssuedAt(new Date(currentTime))  //签发时间
                .setSubject("system")  //说明
                .setIssuer("heima") //签发者信息
                .setAudience("app")  //接收用户
                .compressWith(CompressionCodecs.GZIP)  //数据压缩方式
                .signWith(SignatureAlgorithm.HS512, generalKey()) //加密方式
                .setExpiration(new Date(currentTime + TOKEN_TIME_OUT * 1000))  //过期时间戳
                .addClaims(claimMaps) //cla信息
                .compact();
    }

    /**
     * 获取token中的claims信息
     *
     * @param token
     * @return
     */
    private static Jws<Claims> getJws(String token) {
            return Jwts.parser()
                    .setSigningKey(generalKey())
                    .parseClaimsJws(token);
    }

    /**
     * 获取payload body信息
     *
     * @param token
     * @return
     */
    public static Claims getClaimsBody(String token) {
        try {
            return getJws(token).getBody();
        }catch (ExpiredJwtException e){
            return null;
        }
    }

    /**
     * 获取hearder body信息
     *
     * @param token
     * @return
     */
    public static JwsHeader getHeaderBody(String token) {
        return getJws(token).getHeader();
    }

    /**
     * 是否过期
     *
     * @param claims
     * @return -1:有效,0:有效,1:过期,2:过期
     */
    public static int verifyToken(Claims claims) {
        if(claims==null){
            return 1;
        }
        try {
            claims.getExpiration()
                    .before(new Date());
            // 需要自动刷新TOKEN
            if((claims.getExpiration().getTime()-System.currentTimeMillis())>REFRESH_TIME*1000){
                return -1;
            }else {
                return 0;
            }
        } catch (ExpiredJwtException ex) {
            return 1;
        }catch (Exception e){
            return 2;
        }
    }

    /**
     * 由字符串生成加密key
     *
     * @return
     */
    public static SecretKey generalKey() {
        byte[] encodedKey = Base64.getEncoder().encode(TOKEN_ENCRY_KEY.getBytes());
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }

    public static void main(String[] args) {
       /* Map map = new HashMap();
        map.put("id","11");*/
        System.out.println(AppJwtUtil.getToken(1102L));
        Jws<Claims> jws = AppJwtUtil.getJws("eyJhbGciOiJIUzUxMiIsInppcCI6IkdaSVAifQ.H4sIAAAAAAAAADWLQQqEMAwA_5KzhURNt_qb1KZYQSi0wi6Lf9942NsMw3zh6AVW2DYmDGl2WabkZgreCaM6VXzhFBfJMcMARTqsxIG9Z888QLui3e3Tup5Pb81013KKmVzJTGo11nf9n8v4nMUaEY73DzTabjmDAAAA.4SuqQ42IGqCgBai6qd4RaVpVxTlZIWC826QA9kLvt9d-yVUw82gU47HDaSfOzgAcloZedYNNpUcd18Ne8vvjQA");
        Claims claims = jws.getBody();
        System.out.println(claims.get("id"));

    }

}

创建过滤器com.heima.admin.gateway.fliter.AuthorizeFilter类,由于token的验证

@Component
@Slf4j
public class AuthorizeFilter implements Ordered, GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //1.获取Request对象和Response对象
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        //2.判断当前请求是否为登录请求,如果是,直接放行
        if (request.getURI().getPath().contains("/login")) {
            //放行
            return chain.filter(exchange);
        }
        //3.获取当前请求的token信息
        String token = request.getHeaders().getFirst("token");
        //4.判断token是否存在
        if(StringUtils.isBlank(token)) {
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        //5.判断token是否有效
        //5.1 解析token
        try{
            Claims body = AppJwtUtil.getClaimsBody(token);
            //5.2 判断token是否有效
            int result = AppJwtUtil.verifyToken(body);
            if(result == 1||result == 2) {
                //5.3 token过期
                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                return response.setComplete();
            }
            //获取用户信息
            Integer userId = (Integer) body.get("id");
            //将用户信息放入到header中
            ServerHttpRequest serverHttpRequest = request.mutate().headers(httpHeaders -> {
                httpHeaders.add("userId", userId + "");
            }).build();
            //重置请求
            exchange.mutate().request(serverHttpRequest);
        }catch (Exception e) {
            e.printStackTrace();
            //5.4 token无效
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        //6.放行
        return chain.filter(exchange);
    }

    /**
     * 过滤器的执行顺序,返回值越小,执行优先级越高
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }
}

4.3 创建启动类

创建com.heima.admin.gateway.AdminGatewayApplication启动类

@SpringBootApplication
@EnableDiscoveryClient
public class AdminGatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(AdminGatewayApplication.class, args);

    }
}

4.4 创建配置文件bootstrap.yml

server:
  port: 51603
spring:
  application:
    name: leadnews-admin-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.204.129:8848
      config:
        server-addr: 192.168.204.129:8848
        file-extension: yml

4.5 在nacos中配置

新建nacos配置,配置拦截路径及转发路径

在这里插入图片描述

spring:
  cloud:
    gateway:
      globalcors:
        add-to-simple-url-handler-mapping: true
        corsConfigurations:
          '[/**]':
            allowedHeaders: "*"
            allowedOrigins: "*"
            allowedMethods:
              - GET
              - POST
              - DELETE
              - PUT
              - OPTION
      routes:
        # 平台管理
        - id: admin
          uri: lb://leadnews-admin
          predicates:
            - Path=/admin/**
          filters:
            - StripPrefix= 1

4.6 测试

访问http://localhost:51603/admin/login/in

在这里插入图片描述

测试成功

4.7 前后端联调

启动nginx

访问localhost:8803

在这里插入图片描述

成功登录

5 频道管理

5.1 保存频道

频道发起保存请求的http://localhost:8803/service_6001/wemedia/api/v1/channel/save

说明网关需要拦截wemedia并且转发到相应的feign调用

接口地址:/api/v1/channel/save

请求方式:POST

请求数据类型:application/json

请求参数:

参数名称参数说明in是否必须数据类型schema
adChanneladChannelbodytrueAdChannelAdChannel
  createdTimefalsestring(date-time)
  descriptionfalsestring
  idfalseinteger(int32)
  isDefaultfalseboolean
  namefalsestring
  ordfalseinteger(int32)
  statusfalseboolean

5.1.1 实体类AdChannel

在heima-leadnews-model模块下创建com.heima.model.admin.pojos.AdChannel类,因为接收对象与com.heima.model.wemedia.pojos.WmChannel一模一样,所以直接继承过来

public class AdChannel extends WmChannel {

}

5.1.2 修改admin的Nacos网关配置

因为保存请求的地址http://localhost:8803/service_6001/wemedia/api/v1/channel/save

网关需要拦截wemedia并且把它发送到相应的heima-leadnew-wemedia的微服务中。所以需要修改leadnews-admin-gateway的nacos配置

spring:
  cloud:
    gateway:
      globalcors:
        add-to-simple-url-handler-mapping: true
        corsConfigurations:
          '[/**]':
            allowedHeaders: "*"
            allowedOrigins: "*"
            allowedMethods:
              - GET
              - POST
              - DELETE
              - PUT
              - OPTION
      routes:
        # 管理端管理
        - id: admin
          uri: lb://leadnews-admin
          predicates:
            - Path=/admin/**
          filters:
            - StripPrefix= 1
        # 自媒体微服务
        - id: leadnews-wemedia
          uri: lb://leadnews-wemedia
          predicates:
            - Path=/wemedia/**
          filters:
            - StripPrefix= 1

5.1.3 完善自媒体服务中WmChannelController

    @PostMapping("/save")
    public ResponseResult save(@RequestBody AdChannel channel){
        WmChannel wmChannel = new WmChannel();
        BeanUtils.copyProperties(channel,wmChannel);
        if(wmChannel.getIsDefault()==null){
            wmChannel.setIsDefault(true);
        }
        if(wmChannel.getOrd()==null){
            wmChannel.setOrd(1);
        }
        if(wmChannel.getCreatedTime()==null){
            wmChannel.setCreatedTime(new Date());
        }
        return ResponseResult.okResult(wmChannelService.save(wmChannel));
    }

5.1.4 测试

在这里插入图片描述

查看leadnews_wemedia数据库中wm_channel表

在这里插入图片描述

码农探花已经加入。

5.2 频道名称模糊分页查询

接口地址:/api/v1/channel/list

请求方式:POST

请求参数:

参数名称参数说明in是否必须数据类型schema
dtodtobodytrueChannelDtoChannelDto
  name频道名称falsestring
  page当前页trueinteger(int32)
  size每页显示条数trueinteger(int32)

5.2.1 实体类ChannelDto

在heima-leadnews-model模块中创建com.heima.model.admin.dtos.ChannelDto类

@Data
public class ChannelDto {
    private String name;
    private Integer page;
    private Integer size;
}

5.2.3 完善自媒体服务中WmChannelController

@PostMapping("/list")
public ResponseResult findListWithPage(@RequestBody ChannelDto dto){
    return wmChannelService.findListWithPage(dto);
}

5.2.4 Service

接口:

ResponseResult findListWithPage(ChannelDto dto);

实现:

/**
 * 分页查询频道列表
 */
@Override
public ResponseResult findListWithPage(ChannelDto dto) {
    // 1.参数检查
    if(dto == null){
        return ResponseResult.errorResult(400,"参数错误");
    }
    // 2 分页查询
    IPage pageCheck=new Page(dto.getPage(),dto.getSize());
    // 3 按照不同需求查询
    LambdaQueryWrapper<WmChannel> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //3.1 关键字模糊匹配
    if(StringUtils.isNotBlank(dto.getName())){
        lambdaQueryWrapper.like(WmChannel::getName,dto.getName());
    }
    //3.2 排序
    lambdaQueryWrapper.orderByDesc(WmChannel::getCreatedTime);
    pageCheck = page(pageCheck, lambdaQueryWrapper);
    //4. 返回结果
    ResponseResult responseResult = new PageResponseResult(dto.getPage(), dto.getSize(), (int) pageCheck.getTotal());
    responseResult.setData(pageCheck.getRecords());
    return responseResult;
}

5.2.5 测试

在这里插入图片描述

5.3 更新频道

接口地址:/api/v1/channel/update

请求方式:POST

请求参数:

参数名称参数说明in是否必须数据类型schema
adChanneladChannelbodytrueAdChannelAdChannel
  createdTimefalsestring(date-time)
  descriptionfalsestring
  idfalseinteger(int32)
  isDefaultfalseboolean
  namefalsestring
  ordfalseinteger(int32)
  statusfalseboolean

5.3.1 完善自媒体服务中WmChannelController

@PostMapping("/update")
public ResponseResult update(@RequestBody AdChannel channel){
    return wmChannelService.updateChannel(channel);
}

5.3.2 Service

接口

ResponseResult updateChannel(AdChannel channel);

实现

@Override
public ResponseResult updateChannel(AdChannel channel) {
    // 1.参数检查
    if(channel == null){
        return ResponseResult.errorResult(400,"参数错误");
    }
    // 2.更新
    WmChannel wmChannel = new WmChannel();
    BeanUtils.copyProperties(channel,wmChannel);
    updateById(wmChannel);
    return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}

5.3.3 测试

把探花改成烧烤

在这里插入图片描述

查看数据库

在这里插入图片描述

5.4 删除频道

接口地址:/api/v1/channel/del/{id}

请求方式:GET

请求参数:

参数名称参数说明in是否必须数据类型schema
ididpathtrueinteger(int32)

5.4.1 完善自媒体服务中WmChannelController

/**
 * 删除频道
 * @param id
 * @return
 */ 
@GetMapping("/del/{id}")
public ResponseResult del(@PathVariable("id") Integer id){
    return wmChannelService.deleteChannel(id);
}

5.4.2 Service

接口

ResponseResult deleteChannel(Integer id);

实现

@Override
public ResponseResult deleteChannel(Integer id) {
    // 1.参数检查
    if(id == null){
        return ResponseResult.errorResult(400,"参数错误");
    }
    // 2.删除
    removeById(id);
    return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);

5.4.3 测试

把码农烧烤删了去,已经没有了。

在这里插入图片描述

6 敏感词管理

查看list请求http://localhost:8803/service_6001/wemedia/api/v1/sensitive/list

发现还是在wemedia下进行的。所以还是在自媒体微服务里进行管理。

6.1 查询列表

接口地址:/api/v1/sensitive/list

请求方式:POST

请求参数:

参数名称参数说明in是否必须数据类型schema
dtodtobodytrueSensitiveDtoSensitiveDto
  namefalsestring
  page当前页trueinteger(int32)
  size每页显示条数trueinteger(int32)

6.1.1 实体类SensitiveDto

在heima-leadnews-model模块中创建com.heima.model.admin.dtos.SensitiveDto类

@Data
public class SensitiveDto {
    private String name;
    private Integer page;
    private Integer size;
}

6.1.2 WmSensitiveController

在heima-leadnews-wemedia中创建com.heima.wemedia.controller.v1.WmSensitiveController类

@RestController
@RequestMapping("/api/v1/sensitive")
public class WmSensitiveController {
    @Autowired
    private WmSensitiveService wmSensitiveService;
    /**
     * 敏感词列表
     */
    @PostMapping("/list")
    public ResponseResult list(@RequestBody SensitiveDto dto){
        return wmSensitiveService.list(dto);
    }

}

6.1.3 Service

接口

public interface WmSensitiveService {
    public ResponseResult list(SensitiveDto dto);
}

实现

@Service
@Slf4j
@Transactional
public class WmSensitiveServiceImpl extends ServiceImpl<WmSensitiveMapper, WmSensitive>  implements WmSensitiveService {
    @Override
    public ResponseResult list(SensitiveDto dto) {
        // 1.参数检查
        if(dto == null){
            return ResponseResult.errorResult(400,"参数错误");
        }
        // 2 分页查询
        IPage pageCheck=new Page(dto.getPage(),dto.getSize());
        // 3 按照不同需求查询
        LambdaQueryWrapper<WmSensitive> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //3.1 关键字模糊匹配
        if(StringUtils.isNotBlank(dto.getName())){
            lambdaQueryWrapper.like(WmSensitive::getSensitives,dto.getName());
        }
        //3.2 排序
        lambdaQueryWrapper.orderByDesc(WmSensitive::getCreatedTime);
        pageCheck = page(pageCheck, lambdaQueryWrapper);
        //4. 返回结果
        ResponseResult responseResult = new PageResponseResult(dto.getPage(), dto.getSize(), (int) pageCheck.getTotal());
        responseResult.setData(pageCheck.getRecords());
        return responseResult;
    }
}

6.1.4 测试

在这里插入图片描述

成功

6.2 敏感词保存

接口地址:/api/v1/sensitive/save

请求方式:POST

请求参数:

参数名称参数说明in是否必须数据类型schema
adSensitiveadSensitivebodytrueAdSensitiveAdSensitive
  createdTimefalsestring(date-time)
  idfalseinteger(int32)
  sensitivesfalsestring

6.2.1 实体类AdSensitive

在heima-leadnews-model中添加com.heima.model.admin.pojos.AdSensitive类

public class AdSensitive extends WmSensitive {
}

6.2.2 WmSensitiveController

/**
 * 敏感词新增
 */
@PostMapping("/save")
public ResponseResult save(@RequestBody AdSensitive dto){
    return wmSensitiveService.save(dto);
}

6.2.3 Service

接口

ResponseResult save(AdSensitive dto);

实现

@Override
public ResponseResult save(AdSensitive dto) {
    if(dto == null){
        return ResponseResult.errorResult(400,"参数错误");
    }
    WmSensitive wmSensitive = new WmSensitive();
    BeanUtils.copyProperties(dto,wmSensitive);
    save(wmSensitive);
    return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}

6.2.4 测试

在这里插入图片描述

加入敏感词探花

在这里插入图片描述

测试成功

6.3 更新敏感词

接口地址:/api/v1/sensitive/update

请求方式:POST

请求参数:

参数名称参数说明in是否必须数据类型schema
adSensitiveadSensitivebodytrueAdSensitiveAdSensitive
  createdTimefalsestring(date-time)
  idfalseinteger(int32)
  sensitivesfalsestring

6.3.1 WmSensitiveController

/**
 * 敏感词修改
 */
@PostMapping("/update")
public ResponseResult update(@RequestBody AdSensitive dto){
    return wmSensitiveService.update(dto);
}

6.3.2 Service

接口

ResponseResult update(AdSensitive dto);

实现

@Override
public ResponseResult update(AdSensitive dto) {
    if(dto == null){
        return ResponseResult.errorResult(400,"参数错误");
    }
    WmSensitive wmSensitive = new WmSensitive();
    BeanUtils.copyProperties(dto,wmSensitive);
    updateById(wmSensitive);
    return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}

6.3.3 测试

把探花改成烧烤

在这里插入图片描述

6.4 删除敏感词

接口地址:/api/v1/sensitive/del/{id}

请求方式:DELETE

请求参数:

参数名称参数说明in是否必须数据类型schema
ididpathtrueinteger(int32)

6.4.1 WmSensitiveController

/**
 * 敏感词删除
 */
@DeleteMapping("/del/{id}")
public ResponseResult delete(@PathVariable("id") Integer id){
    return wmSensitiveService.delete(id);
}

6.4.2 Service

接口

ResponseResult delete(Integer id);

实现

@Override
public ResponseResult delete(Integer id) {
    if(id == null){
        return ResponseResult.errorResult(400,"参数错误");
    }
    removeById(id);
    return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}

6.4.3 测试

把烧烤删了

在这里插入图片描述

7 用户审核

发送的请求url为http://localhost:8803/service_6001/user/api/v1/auth/list,说明需要用网关转发到user

7.0 修改leadnews-admin-gateway的nacos配置

spring:
  cloud:
    gateway:
      globalcors:
        add-to-simple-url-handler-mapping: true
        corsConfigurations:
          '[/**]':
            allowedHeaders: "*"
            allowedOrigins: "*"
            allowedMethods:
              - GET
              - POST
              - DELETE
              - PUT
              - OPTION
      routes:
        # 管理端管理
        - id: admin
          uri: lb://leadnews-admin
          predicates:
            - Path=/admin/**
          filters:
            - StripPrefix= 1
        # 自媒体微服务
        - id: leadnews-wemedia
          uri: lb://leadnews-wemedia
          predicates:
            - Path=/wemedia/**
          filters:
            - StripPrefix= 1
        # 用户微服务
        - id: leadnews-user
          uri: lb://leadnews-user
          predicates:
            - Path=/user/**
          filters:
            - StripPrefix= 1

7.1 查询列表

接口地址:/api/v1/auth/list

请求方式:POST

请求参数:

参数名称参数说明in是否必须数据类型schema
dtodtobodytrueAuthDtoAuthDto
  idfalseinteger(int32)
  msgfalsestring
  page当前页trueinteger(int32)
  size每页显示条数trueinteger(int32)
  statusfalseinteger(int32)

7.1.1 实体类AuthDto

在heima-leadnews-model中创建com.heima.model.admin.dtos.AuthDto实体类

@Data
public class AuthDto{
    private Integer id;
    private String msg;
    private Integer page;
    private Integer size;
    private Integer status;
}

7.1.2 Controller

在heima-leadnews-user中创建com.heima.user.controller.v1.ApUserVerifyController

@RestController
@RequestMapping("/api/v1/auth")
public class ApUserVerifyController {
    @Autowired
    private ApUserRealnameService apUserRealnameService;

    /**
     * 查询列表
     */
    @PostMapping("/list")
    public ResponseResult list(@RequestBody AuthDto dto) {
        return apUserRealnameService.findlist(dto);
    }

}

7.1.3 Service

接口:

public interface ApUserRealnameService extends IService<ApUserRealname> {
    ResponseResult findlist(AuthDto dto);
}

实现:

@Service
@Transactional
@Slf4j
public class ApUserRealnameServiceImpl extends ServiceImpl<ApRealNamemapper, ApUserRealname> implements ApUserRealnameService {
    @Override
    public ResponseResult findlist(AuthDto dto) {
        if(dto == null) {
            return ResponseResult.errorResult(400, "参数错误");
        }
        // 2 分页查询
        IPage pageCheck=new Page(dto.getPage(),dto.getSize());
        // 3 按照不同需求查询
        LambdaQueryWrapper<ApUserRealname> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //3.1 状态
        if(dto.getStatus()!=null){
            lambdaQueryWrapper.eq(ApUserRealname::getStatus, dto.getStatus());
        }
        //3.2 排序
        lambdaQueryWrapper.orderByDesc(ApUserRealname::getCreatedTime);
        pageCheck = page(pageCheck, lambdaQueryWrapper);
        //4. 返回结果
        ResponseResult responseResult = new PageResponseResult(dto.getPage(), dto.getSize(), (int) pageCheck.getTotal());
        responseResult.setData(pageCheck.getRecords());
        return responseResult;

    }
}

7.1.4 测试

在这里插入图片描述

7.2 审核失败

接口地址:/api/v1/auth/authFail

请求方式:POST

请求参数:

参数名称参数说明in是否必须数据类型schema
dtodtobodytrueAuthDtoAuthDto
  idfalseinteger(int32)
  msgfalsestring
  page当前页trueinteger(int32)
  size每页显示条数trueinteger(int32)
  statusfalseinteger(int32)

7.2.1 Controller

/**
 * 审核失败
 */
@PostMapping("/authFail")
public ResponseResult authFail(@RequestBody AuthDto dto) {
    return apUserRealnameService.authFail(dto);
}

7.2.2 Service

接口:

ResponseResult authFail(AuthDto dto);

实现:

@Override
public ResponseResult authFail(AuthDto dto) {
    if(dto==null || dto.getId()==null){
        return ResponseResult.errorResult(400,"参数错误");
    }
    ApUserRealname apUserRealname = new ApUserRealname();
    BeanUtils.copyProperties(dto, apUserRealname);
    apUserRealname.setStatus((short) 2);
    if(StringUtils.isBlank(dto.getMsg())){
        apUserRealname.setReason("审核失败");
    }else{
        apUserRealname.setReason(dto.getMsg());
    }
    apUserRealname.setUpdatedTime(new Date());
    updateById(apUserRealname);
    return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}

7.2.3 测试

3被驳回,驳回理由,黑马探花黑马烧烤

在这里插入图片描述

在这里插入图片描述

7.3 审核成功

接口地址:/api/v1/auth/authPass

请求方式:POST

请求参数:

参数名称参数说明in是否必须数据类型schema
dtodtobodytrueAuthDtoAuthDto
  idfalseinteger(int32)
  msgfalsestring
  page当前页trueinteger(int32)
  size每页显示条数trueinteger(int32)
  statusfalseinteger(int32)

7.3.1 Controller

在heima-leadnews-user中创建com.heima.user.controller.v1.ApUserVerifyController

/**
 * 审核通过
 */
@PostMapping("/authPass")
public ResponseResult authPass(@RequestBody AuthDto dto) {
    return apUserRealnameService.authPass(dto);
}

7.3.2 Service

接口:

ResponseResult authPass(AuthDto dto);

实现:

@Override
public ResponseResult authPass(AuthDto dto) {
    if(dto==null || dto.getId()==null){
        return ResponseResult.errorResult(400,"参数错误");
    }
    ApUserRealname apUserRealname = new ApUserRealname();
    BeanUtils.copyProperties(dto, apUserRealname);
    apUserRealname.setStatus((short) 9);
    apUserRealname.setUpdatedTime(new Date());
    updateById(apUserRealname);
    return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}

7.3.3 测试

1通过

在这里插入图片描述

8 自媒体文章人工审核

发送的请求url为http://localhost:8803/service_6001/wemedia/api/v1/news/list_vo

8.1 查询文章列表

接口地址:/api/v1/news/list_vo

请求方式:POST

请求参数:

参数名称参数说明in是否必须数据类型schema
dtodtobodytrueNewsAuthDtoNewsAuthDto
  idfalseinteger(int32)
  msgfalsestring
  page当前页trueinteger(int32)
  size每页显示条数trueinteger(int32)
  statusfalseinteger(int32)
  titlefalsestring

8.1.1 实体类NewsAuthDto

在heima-leadnews-model中创建com.heima.model.admin.dtos.NewsAuthDto实体类

@Data
public class NewsAuthDto {
    private Integer id;
    private String msg;
    private Integer page;
    private Integer size;
    private Integer status;
    private String title;
}

8.1.2 Controller

为com.heima.wemedia.controller.v1.WmNewsController添加方法

@PostMapping("/list_vo")
public ResponseResult listVo(@RequestBody NewsAuthDto dto){
    return wmNewsService.listVo(dto);
}

8.1.3 Service

接口:

ResponseResult listVo(NewsAuthDto dto);

实现:

@Override
public ResponseResult listVo(NewsAuthDto dto) {
    if(dto == null){
        return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
    }
    // 2 分页查询
    IPage pageCheck=new Page(dto.getPage(),dto.getSize());
    // 3 按照不同需求查询
    LambdaQueryWrapper<WmNews> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    //3.1 状态
    if(dto.getStatus()!=null){
        lambdaQueryWrapper.eq(WmNews::getStatus, dto.getStatus());
    }
    //3.2 排序
    lambdaQueryWrapper.orderByDesc(WmNews::getCreatedTime);
    pageCheck = page(pageCheck, lambdaQueryWrapper);
    //4. 返回结果
    ResponseResult responseResult = new PageResponseResult(dto.getPage(), dto.getSize(), (int) pageCheck.getTotal());
    responseResult.setData(pageCheck.getRecords());
    return responseResult;
}

8.2 查询文章详情

接口地址:/api/v1/news/one_vo/{id}

请求方式:GET

请求参数:

参数名称参数说明in是否必须数据类型schema
ididpathtrueinteger(int32)

8.2.1 Controller

为com.heima.wemedia.controller.v1.WmNewsController添加方法

@RestController
@RequestMapping("/api/v1/auth")
public class ApUserVerifyController {
    @Autowired
    private ApUserRealnameService apUserRealnameService;

    /**
     * 查询列表
     */
    @PostMapping("/list")
    public ResponseResult list(@RequestBody AuthDto dto) {
        return apUserRealnameService.findlist(dto);
    }

}

8.2.2 Service

接口:

public interface ApUserRealnameService extends IService<ApUserRealname> {
    ResponseResult findlist(AuthDto dto);
}

实现:

@Service
@Transactional
@Slf4j
public class ApUserRealnameServiceImpl extends ServiceImpl<ApRealNamemapper, ApUserRealname> implements ApUserRealnameService {
    @Override
    public ResponseResult findlist(AuthDto dto) {
        if(dto == null) {
            return ResponseResult.errorResult(400, "参数错误");
        }
        // 2 分页查询
        IPage pageCheck=new Page(dto.getPage(),dto.getSize());
        // 3 按照不同需求查询
        LambdaQueryWrapper<ApUserRealname> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //3.1 状态
        if(dto.getStatus()!=null){
            lambdaQueryWrapper.eq(ApUserRealname::getStatus, dto.getStatus());
        }
        //3.2 排序
        lambdaQueryWrapper.orderByDesc(ApUserRealname::getCreatedTime);
        pageCheck = page(pageCheck, lambdaQueryWrapper);
        //4. 返回结果
        ResponseResult responseResult = new PageResponseResult(dto.getPage(), dto.getSize(), (int) pageCheck.getTotal());
        responseResult.setData(pageCheck.getRecords());
        return responseResult;

    }
}

8.3 审核失败

接口地址:/api/v1/news/auth_fail

请求方式:POST

请求参数:

参数名称参数说明in是否必须数据类型schema
dtodtobodytrueNewsAuthDtoNewsAuthDto
  idfalseinteger(int32)
  msgfalsestring
  page当前页trueinteger(int32)
  size每页显示条数trueinteger(int32)
  statusfalseinteger(int32)
  titlefalsestring

8.3.1 Controller

为com.heima.wemedia.controller.v1.WmNewsController添加方法

@PostMapping("/auth_fail")
public ResponseResult authFail(@RequestBody NewsAuthDto dto){
    return wmNewsService.authFailNews(dto);
}

8.3.2 Service

接口:

ResponseResult authFailNews(NewsAuthDto dto);

实现:

@Override
public ResponseResult authFailNews(NewsAuthDto dto) {
    if(dto==null || dto.getId()==null){
        return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
    }
    WmNews wmNews = getById(dto.getId());
    if(wmNews == null){
        return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"文章不存在");
    }
    wmNews.setStatus(WmNews.Status.FAIL.getCode());
    wmNews.setReason(dto.getMsg());
    updateById(wmNews);
    return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}

8.4 审核成功

接口地址:/api/v1/news/auth_pass

请求方式:POST

请求参数:

参数名称参数说明in是否必须数据类型schema
dtodtobodytrueNewsAuthDtoNewsAuthDto
  idfalseinteger(int32)
  msgfalsestring
  page当前页trueinteger(int32)
  size每页显示条数trueinteger(int32)
  statusfalseinteger(int32)
  titlefalsestring

8.4.1 Controller

为com.heima.wemedia.controller.v1.WmNewsController添加方法

@PostMapping("/auth_pass")
public ResponseResult authPass(@RequestBody NewsAuthDto dto){
    return wmNewsService.authPassNews(dto);
}

8.4.2 Service

接口:

ResponseResult authPassNews(NewsAuthDto dto);

实现:

@Autowired
private WmChannelMapper wmChannelMapper;
@Autowired
private WmUserMapper wmUserMapper;
@Autowired
private RabbitTemplate rabbitTemplate;
@Override
public ResponseResult authPassNews(NewsAuthDto dto) {
    if(dto==null || dto.getId()==null){
        return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
    }
    WmNews wmNews = getById(dto.getId());
    if(wmNews == null){
        return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"文章不存在");
    }
    if(wmNews.getStatus().equals(WmNews.Status.PUBLISHED.getCode())){
        return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"无需审核");
    }
    wmNews.setStatus(WmNews.Status.ADMIN_SUCCESS.getCode());
    wmNews.setReason(dto.getMsg());
    //人工审核成功保存app端的相关文章数据
    ArticleDto articleDto=new ArticleDto();
    BeanUtils.copyProperties(wmNews,articleDto);
    //布局
    articleDto.setLayout(wmNews.getType());
    //频道
    articleDto.setChannelId(wmNews.getChannelId());
    //频道名称
    WmChannel wmChannel = wmChannelMapper.selectById(wmNews.getChannelId());
    if(wmChannel!=null){
        articleDto.setChannelName(wmChannel.getName());
    }
    //作者
    articleDto.setAuthorId(Long.valueOf(wmNews.getUserId()));
    //作者名称
    WmUser wmUser= wmUserMapper.selectById(wmNews.getUserId());
    if(wmUser!=null){
        articleDto.setAuthorName(wmUser.getName());
    }
    //设置文章id
    if(wmNews.getArticleId()!=null){
        articleDto.setId(wmNews.getArticleId());
    }
    articleDto.setCreatedTime(new Date());

    //2.rabbitmq异步处理
    Map<String,Object> map=new HashMap<>();
    map.put("dto",articleDto);
    map.put("wmNewsId",dto.getId());
    rabbitTemplate.convertAndSend("article.queue", map);
    return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}

8.4.3 修改自动审核逻辑模拟人工审核

创建完自媒体文章,放入task队列等待审核。修改com.heima.wemedia.service.impl.WmNewAutoScanServiceImpl#autoScanMediaNews的逻辑模拟人工审核。

//模拟人工审核
wmNews.setStatus((short) 3);
if(wmNews.getStatus().equals(WmNews.Status.ADMIN_AUTH.getCode())){
    wmNews.setReason("需要人工审核");
    wmNewsMapper.updateById(wmNews);
}

这时候该条wmNews就无法审核上架,必须前端进行审核通过点击后才行。前台点击后调用authPassNews人工审核成功发送异步调用到mq进行保存。

8.5 综合测试

启动mongodb,es,kafak,zookeeper,redis,mq,minio,nacos

启动所有网关及微服务

先在自媒体端添加一篇文章

在这里插入图片描述

因为8.4.3设置状态为人工审核,因此没进行自动审核。

在这里插入图片描述

查看数据库

在这里插入图片描述

打开管理员网站

在这里插入图片描述

查看文章详情

在这里插入图片描述

驳回就写个理由,直接驳回就好。没什么测试的。

通过则需要加入mq通知文章微服务进行添加。需要测试。

在这里插入图片描述

显示已发布。

在这里插入图片描述

自媒体端已显示成功。

查看用户端。

在这里插入图片描述

用户端也有显示。说明添加app端文章成功。

  • 17
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论
敏感过滤是指在文本中过滤掉一些敏感汇,以避免给人带来不必要的困扰或者麻烦。在Java中实现敏感过滤可以使用正则表达式或者Trie树等算法。这里提供一个简单的Trie树实现敏感过滤的代码示例: ```java import java.util.HashSet; import java.util.Set; public class SensitiveWordsFilter { private TrieNode root; public SensitiveWordsFilter() { root = new TrieNode(); } public void addWord(String word) { TrieNode node = root; for (char c : word.toCharArray()) { if (!node.containsKey(c)) { node.put(c, new TrieNode()); } node = node.get(c); } node.setEnd(); } public Set<String> filter(String text) { Set<String> set = new HashSet<>(); for (int i = 0; i < text.length(); i++) { TrieNode node = root; for (int j = i; j < text.length(); j++) { char c = text.charAt(j); if (!node.containsKey(c)) { break; } node = node.get(c); if (node.isEnd()) { set.add(text.substring(i, j + 1)); } } } return set; } private static class TrieNode { private TrieNode[] children; private boolean isEnd; public TrieNode() { children = new TrieNode[256]; isEnd = false; } public boolean containsKey(char c) { return children[c] != null; } public void put(char c, TrieNode node) { children[c] = node; } public TrieNode get(char c) { return children[c]; } public void setEnd() { isEnd = true; } public boolean isEnd() { return isEnd; } } } ``` 使用示例: ```java SensitiveWordsFilter filter = new SensitiveWordsFilter(); filter.addWord("敏感1"); filter.addWord("敏感2"); Set<String> set = filter.filter("这是一段包含敏感1和敏感2的文本。"); System.out.println(set); // 输出 [敏感1, 敏感2] ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AAA码农宝哥.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值