一、主要的需求介绍

主要的需求是,在发布公司官网上的文章同时,需要实现公司官网文章发布成功的同时,也需要将该文章推送到微信公众号上,在公司的公众号上也发布同样的文章,从而可以避免一篇文章需要在不同地点发布两次的繁琐步骤。

二、主要应用的技术

需要用到mybatis来自动生成实体类,sql语句等。后文会展示该功能涉及到的表,大家可以根据需求进行参考修改。

三、需要的依赖

<dependency>
            <groupId>commons-httpclient</groupId>
            <artifactId>commons-httpclient</artifactId>
            <version>3.1</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.78</version>
        </dependency>

四、主要代码

工具类

(1).用于获取微信公众号的access_token以及调用一些主要的微信公众号api
/**
 * 微信公众号新增以及获取永久素材工具类
 * Create by ql on 2022/12/29 13:14
 */
@Component
public class WxUploadMediaApiUtil {
    Logger logger = Logger.getLogger(WxUploadMediaApiUtil.class);
    @Value("${wechat.appId}")
    private String appId;
    @Value("${wechat.appSecret}")
    private String appSecret;

    @Autowired
    OfficialWxTokenRepository officialWxTokenRepository;
    // 获取公众号的access_token(get请求)
    private static final String ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
    // 素材上传(post请求)
    private static final String UPLOAD_MEDIA = "https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=%s&type=%s";
    // 文章正文插图的上传
    private static final String UPLOAD_ILLUSTRATION = "https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=%s";

    /**
     * 通用接口获取token凭证
     *
     * @return
     */
    public String getAccessToken() {
        //首先对所需要的变量进行初始化
        CloseableHttpClient client = null;
        CloseableHttpResponse response = null;
        String Url = String.format(ACCESS_TOKEN, appId, appSecret);
        try {
            //创建客户端连接对象
            client = HttpClients.createDefault();
            //构建Get请求对象
            HttpGet get = new HttpGet(Url);
            //设置超时时间,其中connectionRequestTimout(从连接池获取连接的超时时间)、connetionTimeout(客户端和服务器建立连接的超时时间)、socketTimeout(客户端从服务器读取数据的超时时间),单位都是毫秒
            RequestConfig config = RequestConfig.custom().setConnectTimeout(10000).setConnectionRequestTimeout(3000)
                    .setSocketTimeout(20000).build();
            get.setConfig(config);
            //获取返回对象
            response = client.execute(get);
            //整理返回值
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity);
            JSONObject json = JSON.parseObject(result);
            //将字符串中所需的access_token放入数据库中
            OfficialWxToken officialWxToken = new OfficialWxToken();
            //插入数据时,是否删除为0:未删除
            officialWxToken.setIsDelete(0);
            //将上述获取的token存入
            officialWxToken.setAccessToken(json.getString("access_token"));
            //保存创建时间
            officialWxToken.setCreateSecond(String.valueOf(System.currentTimeMillis() / 1000));
            //将token落库
            officialWxTokenRepository.insert(officialWxToken);
            return json.getString("access_token");
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            // 关闭连接和流
            try {
                if (client != null) {
                    client.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 上传图片到微信公众号永久素材库中
     * 只支持图片,要求为10M以下,支持bmp/png/jpeg/jpg/gif格式
     *
     * @return
     * @throws IOException
     */

    public JSONObject uploadMediaImage(File file) throws Exception {
        //拼接路径
        //初始化变量
        //类型为图片
        String type = "image";
        //获取token
        String accessToken = null;
        //首先获取所有未被删除的token,将id倒序后,获取最大id所对应的access_token
        OfficialWxTokenExample officialWxTokenExample = new OfficialWxTokenExample();
        officialWxTokenExample.createCriteria().andIsDeleteEqualTo(0).andCreateSecondGreaterThan(String.valueOf(System.currentTimeMillis() - 7200 * 1000));
        officialWxTokenExample.setOrderByClause("id DESC");
        List<OfficialWxToken> officialWxTokenList = officialWxTokenRepository.selectByExample(officialWxTokenExample);
        //判断是否存在该数据
        if (officialWxTokenList == null || officialWxTokenList.size() == 0) {
            logger.info("数据不存在或者微信token超过有效期,正在重新重新获取");
            //重新生成一个access_token,直接调用自定义的工具类中的获取token方法
            accessToken = getAccessToken();
        } else {
            //如果数据库中存在该数据,将数据库查询出来的最新一条的accessToken赋值给相应的参数
            accessToken = officialWxTokenList.get(0).getAccessToken();
        }
        String uploadUrl = String.format(UPLOAD_MEDIA, accessToken, type);

        CloseableHttpClient httpClient = HttpClients.createDefault();
        String result = "";
        try {
            HttpPost httpPost = new HttpPost(uploadUrl);
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
            //上传多媒体文件
            builder.addBinaryBody("media", file);
            HttpEntity entity = builder.build();
            httpPost.setEntity(entity);
            // 执行提交
            HttpResponse response = httpClient.execute(httpPost);
            HttpEntity responseEntity = response.getEntity();
            result = EntityUtils.toString(responseEntity, Charset.forName("UTF-8"));
            JSONObject json = JSON.parseObject(result);
            return json;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 在微信文章正文中插入图片的第三方接口
     * 本接口所上传的图片不占用公众号的素材库中图片数量的100000个的限制。图片仅支持jpg/png格式,大小必须在1MB以下
     * @param file
     * @return
     * @throws Exception
     */
    public String uploadIllustration(File file) throws Exception {
        //拼接路径
        //初始化变量
        //获取token
        String accessToken = null;
        //首先获取所有未被删除的token,将id倒序后,获取最大id所对应的access_token
        OfficialWxTokenExample officialWxTokenExample = new OfficialWxTokenExample();
        officialWxTokenExample.createCriteria().andIsDeleteEqualTo(0).andCreateSecondGreaterThan(String.valueOf(System.currentTimeMillis() - 7200 * 1000));
        officialWxTokenExample.setOrderByClause("id DESC");
        List<OfficialWxToken> officialWxTokenList = officialWxTokenRepository.selectByExample(officialWxTokenExample);
        //判断是否存在该数据
        if (officialWxTokenList == null || officialWxTokenList.size() == 0) {
            logger.info("数据不存在或者微信token超过有效期,正在重新重新获取");
            //重新生成一个access_token,直接调用自定义的工具类中的获取token方法
            accessToken = getAccessToken();
        } else {
            //如果数据库中存在该数据,将数据库查询出来的最新一条的accessToken赋值给相应的参数
            accessToken = officialWxTokenList.get(0).getAccessToken();
        }
        String uploadUrl = String.format(UPLOAD_ILLUSTRATION, accessToken);

        CloseableHttpClient httpClient = HttpClients.createDefault();
        String result = "";
        try {
            HttpPost httpPost = new HttpPost(uploadUrl);
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
            //上传多媒体文件
            builder.addBinaryBody("media", file);
            HttpEntity entity = builder.build();
            httpPost.setEntity(entity);
            // 执行提交
            HttpResponse response = httpClient.execute(httpPost);
            HttpEntity responseEntity = response.getEntity();
            result = EntityUtils.toString(responseEntity, Charset.forName("UTF-8"));
            JSONObject json = JSON.parseObject(result);
            return json.getString("url");
        } catch (IOException e) {
            e.printStackTrace();
            return "出现IO错误,未能获取url";
        } catch (Exception e) {
            e.printStackTrace();
            return "出现未知错误,未能获取url";
        } finally {
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
(2).设置图片上传的格式工具类
@Component
public class FileUtil {
    public static final String lineSeparator = "\r\n";


    private static String ipConfig;

    private static String host;

    private static String dir;

    private static String nasUrl;

    @Value("${file.ipConfig}")
    public void setIpConfig(String ipConfig) {
        FileUtil.ipConfig = ipConfig;
    }
    @Value("${file.host}")
    public void setHost(String host) {
        FileUtil.host = host;
    }
    @Value("${file.dir}")
    public void setDir(String dir) {
        FileUtil.dir = dir;
    }
    @Value("${file.nasUrl}")
    public void setNasUrl(String nasUrl) {
        FileUtil.nasUrl = nasUrl;
    }
/**
     * 存储官网上的图片,图片重命名
     * @param file
     * @param folderName 文件夹名称
     * @return
     */
    public static String saveOfficialPicture(MultipartFile file, String folderName) {
        // 附件重命名
        String currentTime = DateUtil.getDateStr(DateUtil.getCurrentDate(), "yyyyMMddHHmmssSSS");
        String fileName = currentTime + "_" + file.getOriginalFilename();
        // 保存上传的文件到文件夹
        try {
            File targetFile = new File(nasUrl + folderName);
            targetFile.setWritable(true, false);
            // 判断文件夹是否已经存在
            if (!targetFile.exists()) {
                targetFile.mkdirs();
            }

            FileOutputStream outputStream = new FileOutputStream(nasUrl + folderName + fileName);
            outputStream.write(file.getBytes());
            outputStream.flush();
            outputStream.close();

        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException(1, null, "上传文件失败!" + e.getMessage());
        }
        return ipConfig + host + dir + folderName + fileName;
    }
}
(3).将MultipartFile类型转换为File类型的工具类

业务上测试需要通过postman上传图片,postman发送的文件类型为MultipartFile,而微信需要的是File类型,因此需要转换

/**
 * Create by ql on 2023/1/12 13:45
 */
public class MultipartFileToFileUtil {
    /**
     * 将MultipartFile转File
      * @param file
     * @return
     * @throws Exception
     */
    public static File multipartFileToFile(MultipartFile file) throws Exception {
        File toFile = null;
        if (file.equals("") || file.getSize() <= 0) {
            file = null;
        } else {
            InputStream ins = null;
            ins = file.getInputStream();
            toFile = new File(file.getOriginalFilename());
            inputStreamToFile(ins, toFile);
            ins.close();
        }
        return toFile;
    }

    /**
     * 获取流文件
     * @param ins
     * @param file
     */
    private static void inputStreamToFile(InputStream ins, File file) {
        try {
            OutputStream os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            ins.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 删除本地临时文件
     * @param file
     */
    public static void deleteTempFile(File file) {
        if (file != null) {
            File del = new File(file.toURI());
            del.delete();
        }
    }
}

控制层代码

@RestController
public class WxArticleController extends BaseController {
    @Autowired
    WxUploadMediaApiUtil wxUploadMediaApiUtil;
    @Autowired
    private WxArticleService wxArticleService;

    /**
     * 进行access_token新增操作
     *
     * @return
     */
    @RequestMapping(value = "/admin/api/official/wx/token", method = RequestMethod.POST)
    public TransResult getWxAccessToken() {
        //初始化响应参数
        BaseResponseDTO baseResponseDTO = new BaseResponseDTO();
        TransResult transResult = new TransResult();
        try {
            //直接调用自定义的工具类中的获取token方法
            wxUploadMediaApiUtil.getAccessToken();
            //此时变成功生成token,并且token落库了,无需再有其他操作
            baseResponseDTO.success();
            transResult.success(baseResponseDTO);
        } catch (Exception e) {
            logger.info(e.getMessage());
            baseResponseDTO.fail(e.getMessage());
        }
        return transResult;
    }


    /**
     * 发布新闻时,上传图片到素材库的接口
     *
     * @return
     */
    @RequestMapping(value = "/admin/api/official/article/image/save", method = RequestMethod.POST)
    public TransResult uploadeMedia(@RequestParam("file") MultipartFile multipartFile) {
        // 初始化响应参数
        ErpOfficialArticleResponseDTO erpOfficialArticleResponseDTO = new ErpOfficialArticleResponseDTO();
        TransResult transResult = new TransResult();
        try {
            //初始化参数
            File file = null;
            try {
                //将MultipartFile转为File
                file = MultipartFileToFileUtil.multipartFileToFile(multipartFile);
                JSONObject jsonObject = wxArticleService.uploadMediaImage(file);
                erpOfficialArticleResponseDTO.setStringContent(jsonObject.getString("media_id"));
                transResult.success(erpOfficialArticleResponseDTO);
            } catch (Exception e) {
                e.printStackTrace();
                transResult.setMessage("上传失败,请检查文件格式再次尝试");
                return transResult;
            } finally {
                deleteTempFile(file);
            }
        } catch (Exception e) {
            erpOfficialArticleResponseDTO.fail(e.getMessage());
            transResult.success(erpOfficialArticleResponseDTO);
        }

        return transResult;
    }

    /**
     * 上传正文内的插图
     *
     * @param file
     * @return
     */
    @RequestMapping(value = "/admin/api/official/article/illustration/save", method = RequestMethod.POST)
    public TransResult saveIllustration(@RequestParam("file") MultipartFile file) {
        //初始化相应参数
        ErpOfficialArticleResponseDTO officialArticleResponseDTO = new ErpOfficialArticleResponseDTO();
        TransResult transResult = new TransResult();
        try {
            Integer illustrationId = wxArticleService.saveArticleIllustration(file);
            officialArticleResponseDTO.setIntegerContent(illustrationId);
            transResult.success(officialArticleResponseDTO);
        } catch (Exception e) {
            officialArticleResponseDTO.fail(e.getMessage());
            transResult.failure(e.getMessage());
        }
        return transResult;
    }

    /**
     * 点击已经上传的图片,会显示图片的唯一表示码
     * @param illustrationId
     * @return
     */
    @RequestMapping(value = "/admin/api/official/article/illustration/select",method = RequestMethod.GET)
    public TransResult selectIllustration(Integer illustrationId){
        // 初始化响应参数
        ErpOfficialArticleResponseDTO erpOfficialArticleResponseDTO = new ErpOfficialArticleResponseDTO();
        TransResult transResult = new TransResult();
        try{
            String identifier = wxArticleService.selectIllustration(illustrationId);
            erpOfficialArticleResponseDTO.setStringContent(identifier);
            transResult.success(erpOfficialArticleResponseDTO);
        }catch (Exception e){
            erpOfficialArticleResponseDTO.fail(e.getMessage());
            transResult.success(erpOfficialArticleResponseDTO);
        }
        return transResult;
    }

    /**
     * 发布新闻的接口(此时将文章发送到微信公众号草稿箱中,同时将成功发送到草稿箱中的该文章进行发布)
     *
     * @param wxArticleRequestDTO
     * @param request
     * @return
     */
    @RequestMapping(value = "/admin/api/official/article/info/save", method = RequestMethod.POST)
    public TransResult saveArticle(@RequestBody WxArticleRequestDTO wxArticleRequestDTO, HttpServletRequest request) {
        //初始化响应参数
        ErpOfficialArticleResponseDTO erpOfficialArticleResponseDTO = new ErpOfficialArticleResponseDTO();
        TransResult transResult = new TransResult();
        // 从session中取pruser
        PrUser loginUser = getLoginUserFromSession(request);
        try {
            String titleId = wxArticleService.saveArticleInfo(wxArticleRequestDTO, loginUser);
            erpOfficialArticleResponseDTO.success();
            erpOfficialArticleResponseDTO.setStringContent("发布成功," + titleId);
            transResult.success(erpOfficialArticleResponseDTO);
        } catch (Exception e) {
            logger.info(e.getMessage());
            erpOfficialArticleResponseDTO.fail(e.getMessage());
            transResult.success(erpOfficialArticleResponseDTO);
        }
        return transResult;
    }

    /**
     * 轮询微信公众号文章发布的状态
     *
     * @param publishId
     * @return
     */
    @RequestMapping(value = "/admin/api/official/article/status/query", method = RequestMethod.GET)
    public TransResult queryArticleStatus(String publishId) {
        //初始化响应参数
        ErpOfficialArticleResponseDTO erpOfficialArticleResponseDTO = new ErpOfficialArticleResponseDTO();
        TransResult transResult = new TransResult();
        try {
            String status = wxArticleService.queryArticleStatus(publishId);
            erpOfficialArticleResponseDTO.success();
            erpOfficialArticleResponseDTO.setStringContent(status);
            transResult.success(erpOfficialArticleResponseDTO);
        } catch (Exception e) {
            logger.info(e.getMessage());
            erpOfficialArticleResponseDTO.fail(e.getMessage());
            transResult.success(erpOfficialArticleResponseDTO);
        }
        return transResult;
    }

    /**
     * 将草稿箱中的草稿进行编辑操作
     *
     * @param index
     * @param wxArticleRequestDTO
     * @param request
     * @return
     */
    @RequestMapping(value = "/admin/api/official/article/info/update", method = RequestMethod.POST)
    public TransResult updateArticleInfo(Integer index, @RequestBody WxArticleRequestDTO wxArticleRequestDTO, HttpServletRequest request) {
        //初始化响应参数
        ErpOfficialArticleResponseDTO erpOfficialArticleResponseDTO = new ErpOfficialArticleResponseDTO();
        TransResult transResult = new TransResult();
        // 从session中取pruser
        PrUser loginUser = getLoginUserFromSession(request);
        try {
            wxArticleService.updateArticleInfo(index, wxArticleRequestDTO, loginUser);
            erpOfficialArticleResponseDTO.success();
            transResult.success(erpOfficialArticleResponseDTO);
        } catch (Exception e) {
            logger.info(e.getMessage());
            erpOfficialArticleResponseDTO.fail(e.getMessage());
            transResult.success(erpOfficialArticleResponseDTO);
        }
        return transResult;
    }

    /**
     * 删除发布的新闻
     *
     * @param titleId
     * @return
     */
    @RequestMapping(value = "/admin/api/official/article/info/delete", method = RequestMethod.POST)
    public TransResult deleteArticleInfo(String titleId, HttpServletRequest request) {
        // 初始化响应参数
        ErpOfficialArticleResponseDTO erpOfficialArticleResponseDTO = new ErpOfficialArticleResponseDTO();
        TransResult transResult = new TransResult();
        // 从session中取pruser
        PrUser loginUser = getLoginUserFromSession(request);
        try {
            wxArticleService.deleteArticleInfo(titleId, loginUser);
            erpOfficialArticleResponseDTO.success();
            transResult.success(erpOfficialArticleResponseDTO);
        } catch (Exception e) {
            erpOfficialArticleResponseDTO.fail(e.getMessage());
            transResult.success(erpOfficialArticleResponseDTO);
        }
        return transResult;
    }
}

业务逻辑层代码

@Repository
public interface WxArticleService {
    
    /**
     * 将图片上传到微信永久素材库
     * @param file
     * @return
     */
    JSONObject uploadMediaImage(File file);
    /**
     * 发布新闻,同时将文章推送到微信公众号草稿箱进行发布
     * @param wxArticleRequestDTO
     * @param prUser
     * @return
     */
    String saveArticleInfo(WxArticleRequestDTO wxArticleRequestDTO, PrUser prUser);

    /**
     * 查询微信公众号文章发布的状态
     * @param publishId
     * @return
     */
    String queryArticleStatus(String publishId);

    /**
     * 将草已经发布的文章进行编辑操作
     * @param index 要更新的文章在图文消息中的位置(多图文消息时,此字段才有意义),第一篇为0
     * @param wxArticleRequestDTO
     * @param prUser
     */
    void updateArticleInfo(Integer index, WxArticleRequestDTO wxArticleRequestDTO, PrUser prUser);

    /**
     * 删除发布的新闻
     * @param titleId
     */
    void deleteArticleInfo(String titleId,PrUser prUser);

    /**
     * 上传文章内容的插图,返回该插图所在表的主键id
     * @param file
     * @return
     */
    Integer saveArticleIllustration(MultipartFile file);

    /**
     * 点击备选的插图,会返回插图的唯一标识码
     * @param illustrationId
     * @return
     */
    String selectIllustration(Integer illustrationId);
}

4.业务逻辑层的实现类

@Service
public class WxArticleServiceImpl extends BaseServiceImpl implements WxArticleService {
    @Autowired
    WxUploadMediaApiUtil wxUploadMediaApiUtil;
    @Autowired
    OfficialWxTokenRepository officialWxTokenRepository;
    @Autowired
    OfficialArticleImageRepository officialArticleImageRepository;
    @Autowired
    OfficialPressReleaseRepository officialPressReleaseRepository;
    @Autowired
    OfficialArticleIllustrationRepository officialArticleIllustrationRepository;

    // 图片永久素材上传(post请求)
    private static final String UPLOAD_MEDIA = "https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=%s&type=%s";
    // 发布草稿箱中的草稿(post请求)
    private static final String ADD_DRAFT = "https://api.weixin.qq.com/cgi-bin/draft/add?access_token=%s";
    // 发布接口(post请求)
    private static final String PUBLISH_SUBMIT = "https://api.weixin.qq.com/cgi-bin/freepublish/submit?access_token=%s";
    // 发布状态轮询接口(post请求)
    private static final String PUBLISH_STATUS = "https://api.weixin.qq.com/cgi-bin/freepublish/get?access_token=%s";
    // 修改草稿接口(post请求)
    private static final String UPDATE_DRAFT = "https://api.weixin.qq.com/cgi-bin/draft/update?access_token=%s";
    // 删除发布接口(post请求)注意:调用该接口后,操作不可逆,请谨慎调用
    private static final String PUBLISH_DELETE = "https://api.weixin.qq.com/cgi-bin/freepublish/delete?access_token=%s";




    @Override
    public JSONObject uploadMediaImage(File file) {
        try {
            //上传素材
            JSONObject jsonObject = wxUploadMediaApiUtil.uploadMediaImage(file);
            if (jsonObject != null) {
                if (jsonObject.get("media_id") != null) {
                    logger.info(jsonObject.get("media_id").toString());
                    logger.info("上传图片到永久素材成功");
                    return jsonObject;
                } else {
                    logger.info("上传图片到永久素材失败");
                }
            }
        } catch (Exception e) {
            logger.info("程序异常---" + e);
        } finally {
            logger.info("结束上传图片到永久素材---------------------");
        }
        return new JSONObject();

    }


    /**
     * 发布新闻,同时将文章推送到微信公众号草稿箱后,再进行发布
     *
     * @param wxArticleRequestDTO
     * @param prUser
     * @return
     */
    @Transactional
    @Override
    public String saveArticleInfo(WxArticleRequestDTO wxArticleRequestDTO, PrUser prUser) {
        //入参非空判断
        if (wxArticleRequestDTO == null) {
            logger.info("官网发布/保存草稿失败,入参为空");
            throw new ServiceException(1, null, "官网发布/保存草稿失败,入参为空");
        }
        //新增的时候,先判断是否有该条新闻
        OfficialPressReleaseExample officialPressReleaseExample = new OfficialPressReleaseExample();
        officialPressReleaseExample.createCriteria().andIsDeleteEqualTo(0).andTitleEqualTo(wxArticleRequestDTO.getTitle());
        List<OfficialPressRelease> officialPressReleaseList = officialPressReleaseRepository.selectByExample(officialPressReleaseExample);
        if (!officialPressReleaseList.isEmpty()){
            logger.info("文章已存在,请勿重复上传");
            throw new ServiceException(1,null,"文章已存在,请勿重复上传");
        }
        //再进行官网首页新闻的发布
        OfficialPressRelease officialPressRelease = new OfficialPressRelease();
        //保存文章的id目的是通过这个id来查询指定文章
        officialPressRelease.setTitleId(AESToolUtil.getMsgEncode("title", wxArticleRequestDTO.getTitle()));
        //保存文章的标题
        officialPressRelease.setTitle(wxArticleRequestDTO.getTitle());
        //保存文章的作者
        officialPressRelease.setAuthor(wxArticleRequestDTO.getAuthor());
        //保存文章的摘要
        officialPressRelease.setDigest(wxArticleRequestDTO.getDigest());
        //保存文章的正文(正文中需要添加图片,因此需要做一个替换后,再存为正文)
        //先去official_article_illustration表中查找所需的数据
        OfficialArticleIllustrationExample officialArticleIllustrationExample = new OfficialArticleIllustrationExample();
        officialArticleIllustrationExample.createCriteria().andIdEqualTo(wxArticleRequestDTO.getIllustrationId());
        List<OfficialArticleIllustration> officialArticleIllustrationList = officialArticleIllustrationRepository.selectByExample(officialArticleIllustrationExample);
        //将正文中的标识码替换为图片url路径
        String content = wxArticleRequestDTO.getContent();
        String revisedContent = content.replaceAll(officialArticleIllustrationList.get(0).getIdentifier(), officialArticleIllustrationList.get(0).getOfficialUrl());
        officialPressRelease.setContent(revisedContent);
        //保存文章的封面图id
        officialPressRelease.setImageId(wxArticleRequestDTO.getImageId());
        officialPressRelease.setIsDelete(0);
        officialPressRelease.setCreatedUser(prUser.getRealName() + "发布新闻操作");
        officialPressRelease.setCreatedTime(DateUtil.getCurrentDate());
        officialPressRelease.setModifiedUser(prUser.getRealName() + "发布新闻操作");
        officialPressRelease.setModifiedTime(DateUtil.getCurrentDate());
        //将数据保存到数据库
        try {
            officialPressReleaseRepository.insertSelective(officialPressRelease);
        } catch (Exception e) {
            logger.info("上传信息保存失败,数据库发生异常,请联系管理员!");
            throw new ServiceException(1, null, "上传信息保存失败,数据库发生异常,请联系管理员!");
        }
        //第二步就是将该新闻发布到微信公众号的草稿箱中
        //首先需要将DTO的字符串类型转换成json字符串类型
        //先需要获取到永久素材的media_id,去表中查询
        OfficialArticleImageExample officialArticleImageExample = new OfficialArticleImageExample();
        officialArticleImageExample.createCriteria().andIdEqualTo(wxArticleRequestDTO.getImageId());
        //去official_article_image表中查询,并将对应数据放入list集合中
        List<OfficialArticleImage> officialArticleImageList = new ArrayList<OfficialArticleImage>();
        try {
            officialArticleImageList = officialArticleImageRepository.selectByExample(officialArticleImageExample);
        } catch (Exception e) {
            logger.info("查询素材库media_id失败,数据库发生异常,请联系管理员!");
            throw new ServiceException(1, null, "查询素材库media_id失败,数据库发生异常,请联系管理员!");
        }
        //获取official_wx_token表里的access_token
        //先进行变量的初始化
        String accessToken = null;
        //首先获取所有未被删除的token,将id倒序后,获取最大id所对应的access_token
        OfficialWxTokenExample officialWxTokenExample = new OfficialWxTokenExample();
        OfficialWxTokenExample.Criteria criteria = officialWxTokenExample.createCriteria();
        criteria.andIsDeleteEqualTo(0).andCreateSecondGreaterThan(String.valueOf(System.currentTimeMillis() - 7200 * 1000));
        officialWxTokenExample.setOrderByClause("id DESC");
        List<OfficialWxToken> officialWxTokenList = officialWxTokenRepository.selectByExample(officialWxTokenExample);
        //判断是否存在该数据
        if (officialWxTokenList == null||officialWxTokenList.size()==0) {
            logger.info("数据不存在或者微信token超过有效期,正在重新重新获取");
            //重新生成一个access_token,直接调用自定义的工具类中的获取token方法
            accessToken = wxUploadMediaApiUtil.getAccessToken();
        } else {
            //如果数据库中存在该数据,将数据库查询出来的最新一条的accessToken赋值给相应的参数
            accessToken = officialWxTokenList.get(0).getAccessToken();
        }
        //拼接请求的路径
        String url = String.format(ADD_DRAFT, accessToken);
        //开始调用微信公众号的api:发布草稿
        CloseableHttpClient client = null;
        CloseableHttpResponse response = null;
        String mediaId = null;
        try {
            // 创建客户端连接对象
            client = HttpClients.createDefault();
            // 构建Post请求对象
            HttpPost post = new HttpPost(url);
            // 设置传送的内容类型是json格式
            post.setHeader("Content-Type", "application/json;charset=utf-8");
            // 接收的内容类型也是json格式
            post.setHeader("Accept", "application/json;charset=utf-8");
            // 设置超时时间,其中connectionRequestTimout(从连接池获取连接的超时时间)、connetionTimeout(客户端和服务器建立连接的超时时间)、socketTimeout(客户端从服务器读取数据的超时时间),单位都是毫秒
            RequestConfig config = RequestConfig.custom().setConnectTimeout(10000).setConnectionRequestTimeout(3000).setSocketTimeout(20000).build();
            post.setConfig(config);
            // 准备数据
            JSONObject json = new JSONObject();
            json.put("title", wxArticleRequestDTO.getTitle());
            json.put("author", wxArticleRequestDTO.getAuthor());
            json.put("digest", wxArticleRequestDTO.getDigest());
            //做正文路径替换
            String revisedArticle = content.replaceAll(officialArticleIllustrationList.get(0).getIdentifier(), officialArticleIllustrationList.get(0).getWxUrl());
            json.put("content", revisedArticle);
            json.put("thumb_media_id", wxArticleRequestDTO.getThumbMediaId());
            //0为默认不打开文章的评论,1为打开评论
            json.put("need_open_comment", 0);
            //0为默认所有人可评论,1粉丝才可评论
            json.put("only_fans_can_comment", 0);
            // 设置请求体
            String article = "{ \"articles\":[ "+json+"]}";
            post.setEntity(new StringEntity(article, "UTF-8"));
            // 获取返回对象
            response = client.execute(post);
            // 整理返回值
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity);
            //转换为json格式
            JSONObject json1 = JSON.parseObject(result);
            //获取json中的media_id
            mediaId = json1.getString("media_id");
        } catch (SocketTimeoutException e) {
            e.printStackTrace();
            throw new RuntimeException("获取token出现连接/超时异常");
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("获取token时执行内部代码时出现异常");
        } finally {
            try {
                if (client != null) {
                    client.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //将mediaId存入到数据库中
        OfficialPressRelease officialPressRelease1 = new OfficialPressRelease();
        officialPressRelease1.setMediaId(mediaId);
        OfficialPressReleaseExample officialPressReleaseExample1 = new OfficialPressReleaseExample();
        officialPressReleaseExample1.createCriteria().andTitleEqualTo(wxArticleRequestDTO.getTitle());
        officialPressReleaseRepository.updateByExampleSelective(officialPressRelease1, officialPressReleaseExample1);
        List<OfficialPressRelease> officialPressReleaseList1 = officialPressReleaseRepository.selectByExample(officialPressReleaseExample1);
        //将成功保存到微信草稿箱的文章进行发布(调用微信公众号的api:发布接口)
        //进行变量初始化
        String publishId = null;
        //拼接请求的路径
        String submitUrl = String.format(PUBLISH_SUBMIT, accessToken);
        try {
            // 创建客户端连接对象
            client = HttpClients.createDefault();
            // 构建Post请求对象
            HttpPost post = new HttpPost(submitUrl);
            // 设置传送的内容类型是json格式
            post.setHeader("Content-Type", "application/json;charset=utf-8");
            // 接收的内容类型也是json格式
            post.setHeader("Accept", "application/json;charset=utf-8");
            // 设置超时时间,其中connectionRequestTimout(从连接池获取连接的超时时间)、connetionTimeout(客户端和服务器建立连接的超时时间)、socketTimeout(客户端从服务器读取数据的超时时间),单位都是毫秒
            RequestConfig config = RequestConfig.custom().setConnectTimeout(10000).setConnectionRequestTimeout(3000).setSocketTimeout(20000).build();
            post.setConfig(config);
            // 准备数据
            JSONObject json = new JSONObject();
            json.put("media_id", mediaId);
            // 设置请求体
            post.setEntity(new StringEntity(json.toString(), "UTF-8"));
            // 获取返回对象
            response = client.execute(post);
            // 整理返回值
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity);
            //转换为JSON格式
            JSONObject json2 = JSON.parseObject(result);
            //获取文章发布以后返回的publish_id
            publishId = json2.getString("publish_id");
        } catch (SocketTimeoutException e) {
            e.printStackTrace();
            throw new RuntimeException("获取token出现连接/超时异常");
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("获取token时执行内部代码时出现异常");
        } finally {
            try {
                if (client != null) {
                    client.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //将publish_id存入数据库中
        OfficialPressRelease officialPressRelease2 = new OfficialPressRelease();
        officialPressRelease2.setPublishId(publishId);
        officialPressReleaseRepository.updateByExampleSelective(officialPressRelease2,officialPressReleaseExample1);
        List<OfficialPressRelease> officialPressReleaseList2 = officialPressReleaseRepository.selectByExample(officialPressReleaseExample1);
        return officialPressRelease.getTitleId();
    }

    /**
     * 查询微信公众号文章发布的状态
     * @param publishId
     * @return
     */
    @Override
    public String queryArticleStatus(String publishId) {
        //进行非空判断
        if (publishId == null){
            logger.info("查询状态失败,没有输入发布文章的任务id");
            throw new ServiceException(1,null,"查询状态失败,没有输入发布文章的任务id");
        }
        //将需要的参数进行初始化
        String accessToken = null;
        //获取数据库里的access_token
        //首先获取所有未被删除的token,将id倒序后,获取最大id所对应的access_token
        OfficialWxTokenExample officialWxTokenExample = new OfficialWxTokenExample();
        OfficialWxTokenExample.Criteria criteria = officialWxTokenExample.createCriteria();
        criteria.andIsDeleteEqualTo(0).andCreateSecondGreaterThan(String.valueOf(System.currentTimeMillis() - 7200 * 1000));
        officialWxTokenExample.setOrderByClause("id DESC");
        List<OfficialWxToken> officialWxTokenList = officialWxTokenRepository.selectByExample(officialWxTokenExample);
        //判断是否存在该数据
        if (officialWxTokenList == null||officialWxTokenList.size()==0) {
            logger.info("数据不存在或者微信token超过有效期,正在重新重新获取");
            //重新生成一个access_token,直接调用自定义的工具类中的获取token方法
            accessToken = wxUploadMediaApiUtil.getAccessToken();
        } else {
            //如果数据库中存在该数据,将数据库查询出来的最新一条的accessToken赋值给相应的参数
            accessToken = officialWxTokenList.get(0).getAccessToken();
        }
        //初始化变量
        //拼接请求的路径
        String url = String.format(PUBLISH_STATUS, accessToken);
        //调用微信公众号api:发布状态轮询接口
        CloseableHttpClient client = null;
        CloseableHttpResponse response = null;
        Integer publishStatus = null;
        String articleId = null;
        try {
            // 创建客户端连接对象
            client = HttpClients.createDefault();
            // 构建Post请求对象
            HttpPost post = new HttpPost(url);
            // 设置传送的内容类型是json格式
            post.setHeader("Content-Type", "application/json;charset=utf-8");
            // 接收的内容类型也是json格式
            post.setHeader("Accept", "application/json;charset=utf-8");
            // 设置超时时间,其中connectionRequestTimout(从连接池获取连接的超时时间)、connetionTimeout(客户端和服务器建立连接的超时时间)、socketTimeout(客户端从服务器读取数据的超时时间),单位都是毫秒
            RequestConfig config = RequestConfig.custom().setConnectTimeout(10000).setConnectionRequestTimeout(3000).setSocketTimeout(20000).build();
            post.setConfig(config);
            // 准备数据
            JSONObject json = new JSONObject();
            json.put("publish_id", publishId);
            // 设置请求体
            post.setEntity(new StringEntity(json.toString(), "UTF-8"));
            // 获取返回对象
            response = client.execute(post);
            // 整理返回值
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity);
            //转换为json格式
            JSONObject json1 = JSON.parseObject(result);
            //获取json中的publish_status
            publishStatus = json1.getInteger("publish_status");
            //发布成功后(也就是publish_status为0时)会返回article_id,根据该id进行删除公众号文章的操作,因此需要存入数据库
            if (publishStatus == 0){
                //将article_id落库
                //修改根据publish_id查询出来的数据
                OfficialPressReleaseExample officialPressReleaseExample = new OfficialPressReleaseExample();
                officialPressReleaseExample.createCriteria().andPublishIdEqualTo(publishId);
                //添加需要修改的字段
                OfficialPressRelease officialPressRelease = new OfficialPressRelease();
                officialPressRelease.setArticleId(json1.getString("article_id"));
                //将数据库中的信息进行修改
                officialPressReleaseRepository.updateByExampleSelective(officialPressRelease, officialPressReleaseExample);
            }
        } catch (SocketTimeoutException e) {
            e.printStackTrace();
            throw new RuntimeException("获取token出现连接/超时异常");
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("获取token时执行内部代码时出现异常");
        } finally {
            try {
                if (client != null) {
                    client.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //初始化一个变量,用于表示发布状态
        String status = null;
        if (publishStatus == 0){
            status = "发布成功";
        }else if (publishStatus == 1){
            status = "正在发布中";
        }else if (publishStatus == 2){
            status = "发布失败,原创审核不通过";
        }
        //返回发布状态status
        return status;
    }

    /**
     * 将已发布的文章进行编辑操作
     * @param index 要更新的文章在图文消息中的位置(多图文消息时,此字段才有意义),第一篇为0
     * @param wxArticleRequestDTO
     * @param prUser
     */
    @Override
    public void updateArticleInfo(Integer index, WxArticleRequestDTO wxArticleRequestDTO, PrUser prUser) {
        //做非空判断
        if (wxArticleRequestDTO == null){
            logger.info("编辑内容不能为空");
            throw new ServiceException(1,null,"编辑内容不能为空");
        }
        if (prUser == null){
            logger.info("操作人不能为空");
            throw new ServiceException(1,null,"操作人不能为空");
        }

        //先进行官网内显示的文章的修改
        OfficialPressRelease officialPressRelease = new OfficialPressRelease();
        //保存文章的标题
        officialPressRelease.setTitle(wxArticleRequestDTO.getTitle());
        //保存文章的作者
        officialPressRelease.setAuthor(wxArticleRequestDTO.getAuthor());
        //保存文章的摘要
        officialPressRelease.setDigest(wxArticleRequestDTO.getDigest());
        //保存文章的正文
        officialPressRelease.setContent(wxArticleRequestDTO.getContent());
        //保存文章的封面图id
        officialPressRelease.setImageId(wxArticleRequestDTO.getImageId());
        officialPressRelease.setCreatedUser(prUser.getRealName() + "编辑修改新闻操作");
        officialPressRelease.setCreatedTime(DateUtil.getCurrentDate());
        officialPressRelease.setModifiedUser(prUser.getRealName() + "编辑修改新闻操作");
        officialPressRelease.setModifiedTime(DateUtil.getCurrentDate());
        //查找需要编辑的对象
        OfficialPressReleaseExample officialPressReleaseExample = new OfficialPressReleaseExample();
        officialPressReleaseExample.createCriteria().andTitleIdEqualTo(wxArticleRequestDTO.getTitleId()).andIsDeleteEqualTo(0);
        //微信端删除文章需要article_id,因此需要去数据库中查找对应的信息
        List<OfficialPressRelease> officialPressReleaseList = officialPressReleaseRepository.selectByExample(officialPressReleaseExample);
        if (officialPressReleaseList.isEmpty() || officialPressReleaseList.get(0).getIsDelete() == 1) {
            logger.info("删除失败,文章不存在或者已经被删除!");
            throw new ServiceException(1, null, "文章不存在或者已经被删除!");
        }
        //进行数据库的操作,选择性修改内容
        officialPressReleaseRepository.updateByExampleSelective(officialPressRelease, officialPressReleaseExample);
        //如果微信公众号上的文章已经发布成功,那么会将发送成功前的草稿从草稿箱中删除,因此,编辑官网保存的时候,微信公众号需要经历的步骤为:
        //1.先将已经发布的文章从微信公众号上面删除
        //2.新建一个草稿,作为发布的前提,这个草稿的内容为当前上述编辑步骤里面的内容
        //3.将成功创建的这个草稿进行发布
        //首先是第一步。删除
        String accessToken = null;
        //获取数据库里的access_token
        //首先获取所有未被删除的token,将id倒序后,获取最大id所对应的access_token
        OfficialWxTokenExample officialWxTokenExample = new OfficialWxTokenExample();
        OfficialWxTokenExample.Criteria criteria = officialWxTokenExample.createCriteria();
        criteria.andIsDeleteEqualTo(0).andCreateSecondGreaterThan(String.valueOf(System.currentTimeMillis() - 7200 * 1000));
        officialWxTokenExample.setOrderByClause("id DESC");
        List<OfficialWxToken> officialWxTokenList = officialWxTokenRepository.selectByExample(officialWxTokenExample);
        //判断是否存在该数据
        if (officialWxTokenList == null||officialWxTokenList.size()==0) {
            logger.info("数据不存在或者微信token超过有效期,正在重新重新获取");
            //重新生成一个access_token,直接调用自定义的工具类中的获取token方法
            accessToken = wxUploadMediaApiUtil.getAccessToken();
        } else {
            //如果数据库中存在该数据,将数据库查询出来的最新一条的accessToken赋值给相应的参数
            accessToken = officialWxTokenList.get(0).getAccessToken();
        }

        //初始化变量:路径
        String url = String.format(PUBLISH_DELETE, accessToken);
        Integer errcode = null;
        //调用微信公众号api:删除发布接口
        CloseableHttpClient client = null;
        CloseableHttpResponse response = null;
        try {
            // 创建客户端连接对象
            client = HttpClients.createDefault();
            // 构建Post请求对象
            HttpPost post = new HttpPost(url);
            // 设置传送的内容类型是json格式
            post.setHeader("Content-Type", "application/json;charset=utf-8");
            // 接收的内容类型也是json格式
            post.setHeader("Accept", "application/json;charset=utf-8");
            // 设置超时时间,其中connectionRequestTimout(从连接池获取连接的超时时间)、connetionTimeout(客户端和服务器建立连接的超时时间)、socketTimeout(客户端从服务器读取数据的超时时间),单位都是毫秒
            RequestConfig config = RequestConfig.custom().setConnectTimeout(10000).setConnectionRequestTimeout(3000).setSocketTimeout(20000).build();
            post.setConfig(config);
            // 准备数据
            JSONObject json = new JSONObject();
            //传入需要删除新闻的article_id
            json.put("article_id", officialPressReleaseList.get(0).getArticleId());
            // 设置请求体
            post.setEntity(new StringEntity(json.toString(), "UTF-8"));
            // 获取返回对象
            response = client.execute(post);
            // 整理返回值
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity);
            //转换为json格式
            JSONObject json1 = JSON.parseObject(result);
            //获取json中的errcode
            errcode = json1.getInteger("errcode");
        } catch (SocketTimeoutException e) {
            e.printStackTrace();
            throw new RuntimeException("获取token出现连接/超时异常");
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("获取token时执行内部代码时出现异常");
        } finally {
            try {
                if (client != null) {
                    client.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //判断微信公众号文章是否删除成功(当不为0时)
        if (errcode != 0){
            logger.info("微信公众号删除新闻失败,请联系管理员");
            throw new ServiceException(1,null,"微信公众号删除新闻失败,请联系管理员");
        }
        //拼接请求的路径
        String draftUrl = String.format(ADD_DRAFT, accessToken);
        //2.开始调用微信公众号的api:发布草稿
        String mediaId = null;
        try {
            // 创建客户端连接对象
            client = HttpClients.createDefault();
            // 构建Post请求对象
            HttpPost post = new HttpPost(draftUrl);
            // 设置传送的内容类型是json格式
            post.setHeader("Content-Type", "application/json;charset=utf-8");
            // 接收的内容类型也是json格式
            post.setHeader("Accept", "application/json;charset=utf-8");
            // 设置超时时间,其中connectionRequestTimout(从连接池获取连接的超时时间)、connetionTimeout(客户端和服务器建立连接的超时时间)、socketTimeout(客户端从服务器读取数据的超时时间),单位都是毫秒
            RequestConfig config = RequestConfig.custom().setConnectTimeout(10000).setConnectionRequestTimeout(3000).setSocketTimeout(20000).build();
            post.setConfig(config);
            // 准备数据
            JSONObject json = new JSONObject();
            json.put("title", wxArticleRequestDTO.getTitle());
            json.put("author", wxArticleRequestDTO.getAuthor());
            json.put("digest", wxArticleRequestDTO.getDigest());
            json.put("content", wxArticleRequestDTO.getContent());
            json.put("thumb_media_id", wxArticleRequestDTO.getThumbMediaId());
            //0为默认不打开文章的评论,1为打开评论
            json.put("need_open_comment", 0);
            //0为默认所有人可评论,1粉丝才可评论
            json.put("only_fans_can_comment", 0);
            // 设置请求体
            String article = "{ \"articles\":[ "+json+"]}";
            post.setEntity(new StringEntity(article, "UTF-8"));
            // 获取返回对象
            response = client.execute(post);
            // 整理返回值
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity);
            //转换为json格式
            JSONObject json1 = JSON.parseObject(result);
            //获取json中的media_id
            mediaId = json1.getString("media_id");
        } catch (SocketTimeoutException e) {
            e.printStackTrace();
            throw new RuntimeException("获取token出现连接/超时异常");
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("获取token时执行内部代码时出现异常");
        } finally {
            try {
                if (client != null) {
                    client.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //将mediaId存入到数据库中
        OfficialPressRelease officialPressRelease1 = new OfficialPressRelease();
        officialPressRelease1.setMediaId(mediaId);
        officialPressReleaseRepository.updateByExampleSelective(officialPressRelease1, officialPressReleaseExample);
        //3.进行发布文章接口
        //进行变量初始化
        String publishId = null;
        //拼接请求的路径
        String submitUrl = String.format(PUBLISH_SUBMIT, accessToken);
        try {
            // 创建客户端连接对象
            client = HttpClients.createDefault();
            // 构建Post请求对象
            HttpPost post = new HttpPost(submitUrl);
            // 设置传送的内容类型是json格式
            post.setHeader("Content-Type", "application/json;charset=utf-8");
            // 接收的内容类型也是json格式
            post.setHeader("Accept", "application/json;charset=utf-8");
            // 设置超时时间,其中connectionRequestTimout(从连接池获取连接的超时时间)、connetionTimeout(客户端和服务器建立连接的超时时间)、socketTimeout(客户端从服务器读取数据的超时时间),单位都是毫秒
            RequestConfig config = RequestConfig.custom().setConnectTimeout(10000).setConnectionRequestTimeout(3000).setSocketTimeout(20000).build();
            post.setConfig(config);
            // 准备数据
            JSONObject json = new JSONObject();
            json.put("media_id", mediaId);
            // 设置请求体
            post.setEntity(new StringEntity(json.toString(), "UTF-8"));
            // 获取返回对象
            response = client.execute(post);
            // 整理返回值
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity);
            //转换为JSON格式
            JSONObject json2 = JSON.parseObject(result);
            //获取文章发布以后返回的publish_id
            publishId = json2.getString("publish_id");
            //将publish_id存入数据库中
            OfficialPressRelease officialPressRelease2 = new OfficialPressRelease();
            officialPressRelease2.setPublishId(publishId);
            officialPressReleaseRepository.updateByExampleSelective(officialPressRelease2,officialPressReleaseExample);
        } catch (SocketTimeoutException e) {
            e.printStackTrace();
            throw new RuntimeException("获取token出现连接/超时异常");
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("获取token时执行内部代码时出现异常");
        } finally {
            try {
                if (client != null) {
                    client.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 删除发布的新闻
     * @param titleId
     * @param prUser
     */
    @Override
    public void deleteArticleInfo(String titleId,PrUser prUser) {
        //将数据库的信息进行删除操作(在首页进行删除)
        // 入参判断
        if (titleId == null) {
            logger.info("删除失败,新闻id不能为空!");
            throw new ServiceException(1, null, "删除失败,新闻id不能为空!");
        }
        // 根据新闻id查询对应的文章
        OfficialPressReleaseExample officialPressReleaseExample = new OfficialPressReleaseExample();
        officialPressReleaseExample.createCriteria().andTitleIdEqualTo(titleId).andIsDeleteEqualTo(0);
        //初始化接参的list集合
        List<OfficialPressRelease> officialPressReleaseList = new ArrayList<OfficialPressRelease>();
        try {
            officialPressReleaseList = officialPressReleaseRepository.selectByExample(officialPressReleaseExample);
        } catch (Exception e) {
            logger.info("删除失败,数据库发生异常,请联系管理员!");
            throw new ServiceException(1, null, "删除失败,数据库发生异常,请联系管理员!");
        }
        if (officialPressReleaseList.isEmpty() || officialPressReleaseList.get(0).getIsDelete() == 1) {
            logger.info("删除失败,文章不存在或者已经被删除!");
            throw new ServiceException(1, null, "文章不存在或者已经被删除!");
        }
        // 变更为删除状态
        OfficialPressRelease officialPressRelease = new OfficialPressRelease();
        officialPressRelease.setIsDelete(1);
        officialPressRelease.setModifiedUser(prUser.getRealName()+"新闻文章的删除操作");
        officialPressRelease.setModifiedTime(DateUtil.getCurrentDate());
        try {
            officialPressReleaseRepository.updateByExampleSelective(officialPressRelease,officialPressReleaseExample);
        } catch (Exception e) {
            logger.info("删除失败,数据库发生异常,请联系管理员!");
            throw new ServiceException(1, null, "删除失败,数据库发生异常,请联系管理员!");
        }

        //再进行微信公众号的文章删除操作
        //将需要的参数进行初始化
        String accessToken = null;
        //获取数据库里的access_token
        //首先获取所有未被删除的token,将id倒序后,获取最大id所对应的access_token
        OfficialWxTokenExample officialWxTokenExample = new OfficialWxTokenExample();
        OfficialWxTokenExample.Criteria criteria = officialWxTokenExample.createCriteria();
        criteria.andIsDeleteEqualTo(0).andCreateSecondGreaterThan(String.valueOf(System.currentTimeMillis() - 7200 * 1000));
        officialWxTokenExample.setOrderByClause("id DESC");
        List<OfficialWxToken> officialWxTokenList = officialWxTokenRepository.selectByExample(officialWxTokenExample);
        //判断是否存在该数据
        if (officialWxTokenList == null||officialWxTokenList.size()==0) {
            logger.info("数据不存在或者微信token超过有效期,正在重新重新获取");
            //重新生成一个access_token,直接调用自定义的工具类中的获取token方法
            accessToken = wxUploadMediaApiUtil.getAccessToken();
        } else {
            //如果数据库中存在该数据,将数据库查询出来的最新一条的accessToken赋值给相应的参数
            accessToken = officialWxTokenList.get(0).getAccessToken();
        }
        //初始化变量:路径
        String url = String.format(PUBLISH_DELETE, accessToken);
        Integer errcode = null;
        //调用微信公众号api:删除发布接口
        CloseableHttpClient client = null;
        CloseableHttpResponse response = null;
        try {
            // 创建客户端连接对象
            client = HttpClients.createDefault();
            // 构建Post请求对象
            HttpPost post = new HttpPost(url);
            // 设置传送的内容类型是json格式
            post.setHeader("Content-Type", "application/json;charset=utf-8");
            // 接收的内容类型也是json格式
            post.setHeader("Accept", "application/json;charset=utf-8");
            // 设置超时时间,其中connectionRequestTimout(从连接池获取连接的超时时间)、connetionTimeout(客户端和服务器建立连接的超时时间)、socketTimeout(客户端从服务器读取数据的超时时间),单位都是毫秒
            RequestConfig config = RequestConfig.custom().setConnectTimeout(10000).setConnectionRequestTimeout(3000).setSocketTimeout(20000).build();
            post.setConfig(config);
            // 准备数据
            JSONObject json = new JSONObject();
            //传入需要删除新闻的article_id
            json.put("article_id", officialPressReleaseList.get(0).getArticleId());
            // 设置请求体
            post.setEntity(new StringEntity(json.toString(), "UTF-8"));
            // 获取返回对象
            response = client.execute(post);
            // 整理返回值
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity);
            //转换为json格式
            JSONObject json1 = JSON.parseObject(result);
            //获取json中的errcode
            errcode = json1.getInteger("errcode");
        } catch (SocketTimeoutException e) {
            e.printStackTrace();
            throw new RuntimeException("获取token出现连接/超时异常");
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("获取token时执行内部代码时出现异常");
        } finally {
            try {
                if (client != null) {
                    client.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //判断微信公众号文章是否删除成功(当不为0时)
        if (errcode != 0){
            logger.info("微信公众号删除新闻失败,请联系管理员");
            throw new ServiceException(1,null,"微信公众号删除新闻失败,请联系管理员");
        }
    }
  /**
     * 上传文章内容的插图后,会将插图的id返回
     * @param multipartFile
     * @return
     */
    @Override
    public Integer saveArticleIllustration(MultipartFile multipartFile) {
        //先做非空判断
        if (multipartFile == null || multipartFile.getSize() == 0) {
            logger.info("插图不能为空");
            throw new ServiceException(1, null, "上传的插图为空");
        }
        //初始化返回参数
        Integer illustrationId = null;
        //先进行官网的插图上传
        OfficialArticleIllustration officialArticleIllustration = new OfficialArticleIllustration();
        //统一插图存放的文件夹名称
        String illustrationName = "articleIllustration/";
        String officialUrl = FileUtil.saveOfficialPicture(multipartFile, illustrationName);
        //入库保存插图的官网url
        officialArticleIllustration.setOfficialUrl(officialUrl);
        officialArticleIllustration.setCreatedTime(DateUtil.getCurrentDate());
        officialArticleIllustration.setModifiedTime(DateUtil.getCurrentDate());
        officialArticleIllustration.setIsDelete(0);
        try {
            officialArticleIllustrationRepository.insert(officialArticleIllustration);
        } catch (Exception e) {
            logger.info("上传插图失败,数据库发生异常,请联系管理员!");
            throw new ServiceException(1, null, "上传插图失败,数据库发生异常,请联系管理员!");
        }
        //再进行微信公众号的插图上传
        //需要先将MultipartFile类型的文件转换为File类型
        //初始化参数
        File file = null;
        try {
            //将MultipartFile转为File
            file = MultipartFileToFileUtil.multipartFileToFile(multipartFile);
            //将转换好的文件发送到微信
            String wxUrl = wxUploadMediaApiUtil.uploadIllustration(file);
            //将微信接口返回的url更新到数据库
            OfficialArticleIllustrationExample officialArticleIllustrationExample = new OfficialArticleIllustrationExample();
            officialArticleIllustrationExample.createCriteria().andOfficialUrlEqualTo(officialUrl);
            officialArticleIllustration.setWxUrl(wxUrl);
            //为该插图存入一个唯一标识码
            officialArticleIllustration.setIdentifier(UUID.randomUUID().toString());
            officialArticleIllustrationRepository.updateByExampleSelective(officialArticleIllustration, officialArticleIllustrationExample);
            //查找这个插图的主键id,
            List<OfficialArticleIllustration> officialArticleIllustrationList = officialArticleIllustrationRepository.selectByExample(officialArticleIllustrationExample);
            illustrationId = officialArticleIllustrationList.get(0).getId();
        }catch (Exception e) {
            e.printStackTrace();
        } finally {
            deleteTempFile(file);
        }
        //将插图的id返回
        return illustrationId;
    }

    /**
     * 点击备选的插图,会返回插图的唯一标识码
     * @param illustrationId
     * @return
     */
    @Override
    public String selectIllustration(Integer illustrationId) {
        //入参非空判断
        if (illustrationId == null){
            logger.info("出现错误,未能成功选择插图");
            throw new ServiceException(1, null,"出现错误,未能成功选择插图" );
        }
        //初始化返回的参数
        String identifier = null;
        //通过illustrationId去查询对应的数据
        OfficialArticleIllustrationExample officialArticleIllustrationExample = new OfficialArticleIllustrationExample();
        officialArticleIllustrationExample.createCriteria().andIdEqualTo(illustrationId);
        List<OfficialArticleIllustration> officialArticleIllustrationList = officialArticleIllustrationRepository.selectByExample(officialArticleIllustrationExample);
        identifier = officialArticleIllustrationList.get(0).getIdentifier();
        return identifier;
    }
}

五、数据库

微信接口 关注公众号 java 微信公众号接口调用_json


微信接口 关注公众号 java 微信公众号接口调用_Powered by 金山文档_02


微信接口 关注公众号 java 微信公众号接口调用_ci_03


微信接口 关注公众号 java 微信公众号接口调用_微信接口 关注公众号 java_04