03-自媒体文章发布
自媒体文章发布
1)自媒体前后端搭建
1.1)后台搭建
①:资料中找到heima-leadnews-wemedia.zip解压
拷贝到heima-leadnews-service工程下,并指定子模块
执行leadnews-wemedia.sql脚本
添加对应的nacos配置
spring:datasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/leadnews_wemedia?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTCusername: rootpassword: root
# 设置Mapper接口所对应的XML文件位置,如果你在Mapper接口中有自定义方法,需要进行该配置
mybatis-plus:mapper-locations: classpath*:mapper/*.xml# 设置别名包扫描路径,通过该属性可以给包中的类注册别名type-aliases-package: com.heima.model.media.pojos
②:资料中找到heima-leadnews-wemedia-gateway.zip解压
拷贝到heima-leadnews-gateway工程下,并指定子模块
添加对应的nacos配置
spring:cloud:gateway:globalcors:cors-configurations:'[/**]': # 匹配所有请求allowedOrigins: "*" #跨域处理 允许所有的域allowedMethods: # 支持的方法- GET- POST- PUT- DELETEroutes:# 平台管理- id: wemediauri: lb://leadnews-wemediapredicates:- Path=/wemedia/**filters:- StripPrefix= 1
③:在资料中找到类文件夹
拷贝wemedia文件夹到heima-leadnews-model模块下的com.heima.model
1.2)前台搭建
通过nginx的虚拟主机功能,使用同一个nginx访问多个项目
搭建步骤:
①:资料中找到wemedia-web.zip解压
②:在nginx中leadnews.conf目录中新增heima-leadnews-wemedia.conf文件
-
网关地址修改(localhost:51602)
-
前端项目目录修改(wemedia-web解压的目录)
-
访问端口修改(8802)
upstream heima-wemedia-gateway{server localhost:51602;
}server {listen 8802;location / {root D:/workspace/wemedia-web/;index index.html;}location ~/wemedia/MEDIA/(.*) {proxy_pass http://heima-wemedia-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; # 记录真实发出请求的客户端IPproxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #记录代理信息}
}
③:启动nginx,启动自媒体微服务和对应网关
④:联调测试登录功能
2)自媒体素材管理
2.1)素材上传
2.2.1)需求分析
图片上传的页面,首先是展示素材信息,可以点击图片上传,弹窗后可以上传图片
2.2.2)素材管理-图片上传-表结构
媒体图文素材信息表wm_material
对应实体类:
package com.heima.model.wemedia.pojos;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;import java.io.Serializable;
import java.util.Date;/*** <p>* 自媒体图文素材信息表* </p>** @author itheima*/
@Data
@TableName("wm_material")
public class WmMaterial implements Serializable {private static final long serialVersionUID = 1L;/*** 主键*/@TableId(value = "id", type = IdType.AUTO)private Integer id;/*** 自媒体用户ID*/@TableField("user_id")private Integer userId;/*** 图片地址*/@TableField("url")private String url;/*** 素材类型0 图片1 视频*/@TableField("type")private Short type;/*** 是否收藏*/@TableField("is_collection")private Short isCollection;/*** 创建时间*/@TableField("created_time")private Date createdTime;}
2.2.3)实现思路
①:前端发送上传图片请求,类型为MultipartFile
②:网关进行token解析后,把解析后的用户信息存储到header中
//获得token解析后中的用户信息
Object userId = claimsBody.get("id");
//在header中添加新的信息
ServerHttpRequest serverHttpRequest = request.mutate().headers(httpHeaders -> {httpHeaders.add("userId", userId + "");
}).build();
//重置header
exchange.mutate().request(serverHttpRequest).build();
③:自媒体微服务使用拦截器获取到header中的的用户信息,并放入到threadlocal中
在heima-leadnews-utils中新增工具类
注意:需要从资料中找出WmUser实体类拷贝到model工程下
package com.heima.utils.thread;import com.heima.model.wemedia.pojos.WmUser;public class WmThreadLocalUtil {private final static ThreadLocal<WmUser> WM_USER_THREAD_LOCAL = new ThreadLocal<>();/*** 添加用户* @param wmUser*/public static void setUser(WmUser wmUser){WM_USER_THREAD_LOCAL.set(wmUser);}/*** 获取用户*/public static WmUser getUser(){return WM_USER_THREAD_LOCAL.get();}/*** 清理用户*/public static void clear(){WM_USER_THREAD_LOCAL.remove();}
}
在heima-leadnews-wemedia中新增拦截器
package com.heima.wemedia.interceptor;import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.thread.WmThreadLocalUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Optional;@Slf4j
public class WmTokenInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//得到header中的信息String userId = request.getHeader("userId");Optional<String> optional = Optional.ofNullable(userId);if(optional.isPresent()){//把用户id存入threadloacl中WmUser wmUser = new WmUser();wmUser.setId(Integer.valueOf(userId));WmThreadLocalUtils.setUser(wmUser);log.info("wmTokenFilter设置用户信息到threadlocal中...");}return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {log.info("清理threadlocal...");WmThreadLocalUtils.clear();}
}
配置使拦截器生效,拦截所有的请求
package com.heima.wemedia.config;import com.heima.wemedia.interceptor.WmTokenInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new WmTokenInterceptor()).addPathPatterns("/**");}
}
④:先把图片上传到minIO中,获取到图片请求的路径——(2.2.5查看具体功能实现)
⑤:把用户id和图片上的路径保存到素材表中——(2.2.5查看具体功能实现)
2.2.4)接口定义
说明 | |
---|---|
接口路径 | /api/v1/material/upload_picture |
请求方式 | POST |
参数 | MultipartFile |
响应结果 | ResponseResult |
MultipartFile :Springmvc指定的文件接收类型
ResponseResult :
成功需要回显图片,返回素材对象
{"host":null,"code":200,"errorMessage":"操作成功","data":{"id":52,"userId":1102,"url":"http://192.168.200.130:9000/leadnews/2021/04/26/a73f5b60c0d84c32bfe175055aaaac40.jpg","type":0,"isCollection":0,"createdTime":"2021-01-20T16:49:48.443+0000"}
}
失败:
- 参数失效
- 文章上传失败
2.2.5)自媒体微服务集成heima-file-starter
①:导入heima-file-starter
<dependencies><dependency><groupId>com.heima</groupId><artifactId>heima-file-starter</artifactId><version>1.0-SNAPSHOT</version></dependency>
</dependencies>
②:在自媒体微服务的配置中心添加以下配置:
minio:accessKey: miniosecretKey: minio123bucket: leadnewsendpoint: http://192.168.200.130:9000readPath: http://192.168.200.130:9000
2.2.6)具体实现
①:创建WmMaterialController
@RestController
@RequestMapping("/api/v1/material")
public class WmMaterialController {@PostMapping("/upload_picture")public ResponseResult uploadPicture(MultipartFile multipartFile){return null;}}
②:mapper
package com.heima.wemedia.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.heima.model.wemedia.pojos.WmMaterial;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface WmMaterialMapper extends BaseMapper<WmMaterial> {
}
③:业务层:
package com.heima.wemedia.service;public interface WmMaterialService extends IService<WmMaterial> {/*** 图片上传* @param multipartFile* @return*/public ResponseResult uploadPicture(MultipartFile multipartFile);}
业务层实现类:
package com.heima.wemedia.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.file.service.FileStorageService;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.utils.thread.WmThreadLocalUtil;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.service.WmMaterialService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;
import java.util.Date;
import java.util.UUID;@Slf4j
@Service
@Transactional
public class WmMaterialServiceImpl extends ServiceImpl<WmMaterialMapper, WmMaterial> implements WmMaterialService {@Autowiredprivate FileStorageService fileStorageService;/*** 图片上传* @param multipartFile* @return*/@Overridepublic ResponseResult uploadPicture(MultipartFile multipartFile) {//1.检查参数if(multipartFile == null || multipartFile.getSize() == 0){return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);}//2.上传图片到minIO中String fileName = UUID.randomUUID().toString().replace("-", "");//aa.jpgString originalFilename = multipartFile.getOriginalFilename();String postfix = originalFilename.substring(originalFilename.lastIndexOf("."));String fileId = null;try {fileId = fileStorageService.uploadImgFile("", fileName + postfix, multipartFile.getInputStream());log.info("上传图片到MinIO中,fileId:{}",fileId);} catch (IOException e) {e.printStackTrace();log.error("WmMaterialServiceImpl-上传文件失败");}//3.保存到数据库中WmMaterial wmMaterial = new WmMaterial();wmMaterial.setUserId(WmThreadLocalUtil.getUser().getId());wmMaterial.setUrl(fileId);wmMaterial.setIsCollection((short)0);wmMaterial.setType((short)0);wmMaterial.setCreatedTime(new Date());save(wmMaterial);//4.返回结果return ResponseResult.okResult(wmMaterial);}}
④:控制器
@RestController
@RequestMapping("/api/v1/material")
public class WmMaterialController {@Autowiredprivate WmMaterialService wmMaterialService;@PostMapping("/upload_picture")public ResponseResult uploadPicture(MultipartFile multipartFile){return wmMaterialService.uploadPicture(multipartFile);}}
⑤:测试
启动自媒体微服务和自媒体网关,使用前端项目进行测试
2.2)素材列表查询
2.2.1)接口定义
说明 | |
---|---|
接口路径 | /api/v1/material/list |
请求方式 | POST |
参数 | WmMaterialDto |
响应结果 | ResponseResult |
WmMaterialDto :
@Data
public class WmMaterialDto extends PageRequestDto {/*** 1 收藏* 0 未收藏*/private Short isCollection;
}
ResponseResult :
{"host":null,"code":200,"errorMessage":"操作成功","data":[{"id":52,"userId":1102,"url":"http://192.168.200.130:9000/leadnews/2021/04/26/ec893175f18c4261af14df14b83cb25f.jpg","type":0,"isCollection":0,"createdTime":"2021-01-20T16:49:48.000+0000"},....],"currentPage":1,"size":20,"total":0
}
2.2.2)功能实现
①:在WmMaterialController类中新增方法
@PostMapping("/list")
public ResponseResult findList(@RequestBody WmMaterialDto dto){return null;
}
②:mapper已定义
③:业务层
在WmMaterialService中新增方法
/*** 素材列表查询* @param dto* @return*/
public ResponseResult findList( WmMaterialDto dto);
实现方法:
/*** 素材列表查询* @param dto* @return*/
@Override
public ResponseResult findList(WmMaterialDto dto) {//1.检查参数dto.checkParam();//2.分页查询IPage page = new Page(dto.getPage(),dto.getSize());LambdaQueryWrapper<WmMaterial> lambdaQueryWrapper = new LambdaQueryWrapper<>();//是否收藏if(dto.getIsCollection() != null && dto.getIsCollection() == 1){lambdaQueryWrapper.eq(WmMaterial::getIsCollection,dto.getIsCollection());}//按照用户查询lambdaQueryWrapper.eq(WmMaterial::getUserId,WmThreadLocalUtil.getUser().getId());//按照时间倒序lambdaQueryWrapper.orderByDesc(WmMaterial::getCreatedTime);page = page(page,lambdaQueryWrapper);//3.结果返回ResponseResult responseResult = new PageResponseResult(dto.getPage(),dto.getSize(),(int)page.getTotal());responseResult.setData(page.getRecords());return responseResult;
}
④:控制器:
@PostMapping("/list")
public ResponseResult findList(@RequestBody WmMaterialDto dto){return wmMaterialService.findList(dto);
}
⑤:在自媒体引导类中天mybatis-plus的分页拦截器
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;
}
3)自媒体文章管理
3.1)查询所有频道
3.1.1)需求分析
3.1.2)表结构
wm_channel 频道信息表
对应实体类:
package com.heima.model.wemedia.pojos;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;import java.io.Serializable;
import java.util.Date;/*** <p>* 频道信息表* </p>** @author itheima*/
@Data
@TableName("wm_channel")
public class WmChannel implements Serializable {private static final long serialVersionUID = 1L;@TableId(value = "id", type = IdType.AUTO)private Integer id;/*** 频道名称*/@TableField("name")private String name;/*** 频道描述*/@TableField("description")private String description;/*** 是否默认频道* 1:默认 true* 0:非默认 false*/@TableField("is_default")private Boolean isDefault;/*** 是否启用* 1:启用 true* 0:禁用 false*/@TableField("status")private Boolean status;/*** 默认排序*/@TableField("ord")private Integer ord;/*** 创建时间*/@TableField("created_time")private Date createdTime;}
3.1.3)接口定义
说明 | |
---|---|
接口路径 | /api/v1/channel/channels |
请求方式 | POST |
参数 | 无 |
响应结果 | ResponseResult |
ResponseResult :
{"host": "null","code": 0,"errorMessage": "操作成功","data": [{"id": 4,"name": "java","description": "java","isDefault": true,"status": false,"ord": 3,"createdTime": "2019-08-16T10:55:41.000+0000"},Object { ... },Object { ... }]
}
3.1.4)功能实现
接口定义:
package com.heima.wemedia.controller.v1;import com.heima.model.common.dtos.ResponseResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/api/v1/channel")
public class WmchannelController {@GetMapping("/channels")public ResponseResult findAll(){return null;}
}
mapper
package com.heima.wemedia.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.heima.model.wemedia.pojos.WmChannel;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface WmChannelMapper extends BaseMapper<WmChannel> {
}
service
package com.heima.wemedia.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmChannel;public interface WmChannelService extends IService<WmChannel> {/*** 查询所有频道* @return*/public ResponseResult findAll();}
实现类
package com.heima.wemedia.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmChannel;
import com.heima.wemedia.mapper.WmChannelMapper;
import com.heima.wemedia.service.WmChannelService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
@Transactional
@Slf4j
public class WmChannelServiceImpl extends ServiceImpl<WmChannelMapper, WmChannel> implements WmChannelService {/*** 查询所有频道* @return*/@Overridepublic ResponseResult findAll() {return ResponseResult.okResult(list());}
}
控制层
package com.heima.wemedia.controller.v1;import com.heima.model.common.dtos.ResponseResult;
import com.heima.wemedia.service.WmChannelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/api/v1/channel")
public class WmchannelController {@Autowiredprivate WmChannelService wmChannelService;@GetMapping("/channels")public ResponseResult findAll(){return wmChannelService.findAll();}
}
3.1.5)测试
3.2)查询自媒体文章
3.2.1)需求说明
3.2.2)表结构分析
wm_news 自媒体文章表
对应实体类:
package com.heima.model.wemedia.pojos;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import org.apache.ibatis.type.Alias;import java.io.Serializable;
import java.util.Date;/*** <p>* 自媒体图文内容信息表* </p>** @author itheima*/
@Data
@TableName("wm_news")
public class WmNews implements Serializable {private static final long serialVersionUID = 1L;/*** 主键*/@TableId(value = "id", type = IdType.AUTO)private Integer id;/*** 自媒体用户ID*/@TableField("user_id")private Integer userId;/*** 标题*/@TableField("title")private String title;/*** 图文内容*/@TableField("content")private String content;/*** 文章布局0 无图文章1 单图文章3 多图文章*/@TableField("type")private Short type;/*** 图文频道ID*/@TableField("channel_id")private Integer channelId;@TableField("labels")private String labels;/*** 创建时间*/@TableField("created_time")private Date createdTime;/*** 提交时间*/@TableField("submited_time")private Date submitedTime;/*** 当前状态0 草稿1 提交(待审核)2 审核失败3 人工审核4 人工审核通过8 审核通过(待发布)9 已发布*/@TableField("status")private Short status;/*** 定时发布时间,不定时则为空*/@TableField("publish_time")private Date publishTime;/*** 拒绝理由*/@TableField("reason")private String reason;/*** 发布库文章ID*/@TableField("article_id")private Long articleId;/*** //图片用逗号分隔*/@TableField("images")private String images;@TableField("enable")private Short enable;//状态枚举类@Alias("WmNewsStatus")public enum Status{NORMAL((short)0),SUBMIT((short)1),FAIL((short)2),ADMIN_AUTH((short)3),ADMIN_SUCCESS((short)4),SUCCESS((short)8),PUBLISHED((short)9);short code;Status(short code){this.code = code;}public short getCode(){return this.code;}}}
3.2.3)接口定义
说明 | |
---|---|
接口路径 | /api/v1/news/list |
请求方式 | POST |
参数 | WmNewsPageReqDto |
响应结果 | ResponseResult |
WmNewsPageReqDto :
package com.heima.model.wemedia.dtos;import com.heima.model.common.dtos.PageRequestDto;
import lombok.Data;import java.util.Date;@Data
public class WmNewsPageReqDto extends PageRequestDto {/*** 状态*/private Short status;/*** 开始时间*/private Date beginPubDate;/*** 结束时间*/private Date endPubDate;/*** 所属频道ID*/private Integer channelId;/*** 关键字*/private String keyword;
}
ResponseResult :
{"host": "null","code": 0,"errorMessage": "操作成功","data": [Object { ... },Object { ... },Object { ... }],"currentPage":1,"size":10,"total":21
}
3.2.4)功能实现
①:新增WmNewsController
package com.heima.wemedia.controller.v1;import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/api/v1/news")
public class WmNewsController {@PostMapping("/list")public ResponseResult findAll(@RequestBody WmNewsPageReqDto dto){return null;}}
②:新增WmNewsMapper
package com.heima.wemedia.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.heima.model.wemedia.pojos.WmNews;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface WmNewsMapper extends BaseMapper<WmNews> {}
③:新增WmNewsService
package com.heima.wemedia.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.WmNews;public interface WmNewsService extends IService<WmNews> {/*** 查询文章* @param dto* @return*/public ResponseResult findAll(WmNewsPageReqDto dto);}
实现类:
package com.heima.wemedia.service.impl;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.thread.WmThreadLocalUtil;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.service.WmNewsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
@Slf4j
@Transactional
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {/*** 查询文章* @param dto* @return*/@Overridepublic ResponseResult findAll(WmNewsPageReqDto dto) {//1.检查参数if(dto == null){return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);}//分页参数检查dto.checkParam();//获取当前登录人的信息WmUser user = WmThreadLocalUtil.getUser();if(user == null){return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);}//2.分页条件查询IPage page = new Page(dto.getPage(),dto.getSize());LambdaQueryWrapper<WmNews> lambdaQueryWrapper = new LambdaQueryWrapper<>();//状态精确查询if(dto.getStatus() != null){lambdaQueryWrapper.eq(WmNews::getStatus,dto.getStatus());}//频道精确查询if(dto.getChannelId() != null){lambdaQueryWrapper.eq(WmNews::getChannelId,dto.getChannelId());}//时间范围查询if(dto.getBeginPubDate()!=null && dto.getEndPubDate()!=null){lambdaQueryWrapper.between(WmNews::getPublishTime,dto.getBeginPubDate(),dto.getEndPubDate());}//关键字模糊查询if(StringUtils.isNotBlank(dto.getKeyword())){lambdaQueryWrapper.like(WmNews::getTitle,dto.getKeyword());}//查询当前登录用户的文章lambdaQueryWrapper.eq(WmNews::getUserId,user.getId());//发布时间倒序查询lambdaQueryWrapper.orderByDesc(WmNews::getCreatedTime);page = page(page,lambdaQueryWrapper);//3.结果返回ResponseResult responseResult = new PageResponseResult(dto.getPage(),dto.getSize(),(int)page.getTotal());responseResult.setData(page.getRecords());return responseResult;}}
④:控制器
package com.heima.wemedia.controller.v1;import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.wemedia.service.WmNewsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/api/v1/news")
public class WmNewsController {@Autowiredprivate WmNewsService wmNewsService;@PostMapping("/list")public ResponseResult findAll(@RequestBody WmNewsPageReqDto dto){return wmNewsService.findAll(dto);}}
3.2.5)测试
启动后端自媒体微服务和自媒体网关微服务,测试文章列表查询
3.3)文章发布
3.3.1)需求分析
3.3.2)表结构分析
保存文章,除了需要wm_news表以外,还需要另外两张表
wm_material 素材表
wm_news_material 文章素材关系表
其中wm_material和wm_news表的实体类已经导入到了项目中,下面是wm_news_material表对应的实体类:
package com.heima.model.wemedia.pojos;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;import java.io.Serializable;/*** <p>* 自媒体图文引用素材信息表* </p>** @author itheima*/
@Data
@TableName("wm_news_material")
public class WmNewsMaterial implements Serializable {private static final long serialVersionUID = 1L;/*** 主键*/@TableId(value = "id", type = IdType.AUTO)private Integer id;/*** 素材ID*/@TableField("material_id")private Integer materialId;/*** 图文ID*/@TableField("news_id")private Integer newsId;/*** 引用类型0 内容引用1 主图引用*/@TableField("type")private Short type;/*** 引用排序*/@TableField("ord")private Short ord;}
3.3.3)实现思路分析
1.前端提交发布或保存为草稿
2.后台判断请求中是否包含了文章id
3.如果不包含id,则为新增
3.1 执行新增文章的操作
3.2 关联文章内容图片与素材的关系
3.3 关联文章封面图片与素材的关系
4.如果包含了id,则为修改请求
4.1 删除该文章与素材的所有关系
4.2 执行修改操作
4.3 关联文章内容图片与素材的关系
4.4 关联文章封面图片与素材的关系
3.3.4)接口定义
说明 | |
---|---|
接口路径 | /api/v1/channel/submit |
请求方式 | POST |
参数 | WmNewsDto |
响应结果 | ResponseResult |
WmNewsDto
package com.heima.model.wemedia.dtos;import lombok.Data;import java.util.Date;
import java.util.List;@Data
public class WmNewsDto {private Integer id;/*** 标题*/private String title;/*** 频道id*/private Integer channelId;/*** 标签*/private String labels;/*** 发布时间*/private Date publishTime;/*** 文章内容*/private String content;/*** 文章封面类型 0 无图 1 单图 3 多图 -1 自动*/private Short type;/*** 提交时间*/private Date submitedTime; /*** 状态 提交为1 草稿为0*/private Short status;/*** 封面图片列表 多张图以逗号隔开*/private List<String> images;
}
前端给传递过来的json数据格式为:
{"title":"黑马头条项目背景","type":"1",//这个 0 是无图 1 是单图 3 是多图 -1 是自动"labels":"黑马头条","publishTime":"2020-03-14T11:35:49.000Z","channelId":1,"images":["http://192.168.200.130/group1/M00/00/00/wKjIgl5swbGATaSAAAEPfZfx6Iw790.png"],"status":1,"content":"[{"type":"text","value":"随着智能手机的普及,人们更加习惯于通过手机来看新闻。由于生活节奏的加快,很多人只能利用碎片时间来获取信息,因此,对于移动资讯客户端的需求也越来越高。黑马头条项目正是在这样背景下开发出来。黑马头条项目采用当下火热的微服务+大数据技术架构实现。本项目主要着手于获取最新最热新闻资讯,通过大数据分析用户喜好精确推送咨询新闻"},{"type":"image","value":"http://192.168.200.130/group1/M00/00/00/wKjIgl5swbGATaSAAAEPfZfx6Iw790.png"}
]"
}
ResponseResult:
{“code”:501,“errorMessage”:“参数失效"
}{“code”:200,“errorMessage”:“操作成功"
}{“code”:501,“errorMessage”:“素材引用失效"
}
3.3.5)功能实现
①:在新增WmNewsController中新增方法
@PostMapping("/submit")
public ResponseResult submitNews(@RequestBody WmNewsDto dto){return null;
}
②:新增WmNewsMaterialMapper类,文章与素材的关联关系需要批量保存,索引需要定义mapper文件和对应的映射文件
package com.heima.wemedia.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;import java.util.List;@Mapper
public interface WmNewsMaterialMapper extends BaseMapper<WmNewsMaterial> {void saveRelations(@Param("materialIds") List<Integer> materialIds,@Param("newsId") Integer newsId, @Param("type")Short type);
}
WmNewsMaterialMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.heima.wemedia.mapper.WmNewsMaterialMapper"><insert id="saveRelations">insert into wm_news_material (material_id,news_id,type,ord)values<foreach collection="materialIds" index="ord" item="mid" separator=",">(#{mid},#{newsId},#{type},#{ord})</foreach></insert></mapper>
③:常量类准备
package com.heima.common.constants;public class WemediaConstants {public static final Short COLLECT_MATERIAL = 1;//收藏public static final Short CANCEL_COLLECT_MATERIAL = 0;//取消收藏public static final String WM_NEWS_TYPE_IMAGE = "image";public static final Short WM_NEWS_NONE_IMAGE = 0;public static final Short WM_NEWS_SINGLE_IMAGE = 1;public static final Short WM_NEWS_MANY_IMAGE = 3;public static final Short WM_NEWS_TYPE_AUTO = -1;public static final Short WM_CONTENT_REFERENCE = 0;public static final Short WM_COVER_REFERENCE = 1;
}
④:在WmNewsService中新增方法
/*** 发布文章或保存草稿* @param dto* @return*/
public ResponseResult submitNews(WmNewsDto dto);
实现方法:
/*** 发布修改文章或保存为草稿* @param dto* @return*/
@Override
public ResponseResult submitNews(WmNewsDto dto) {//0.条件判断if(dto == null || dto.getContent() == null){return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);}//1.保存或修改文章WmNews wmNews = new WmNews();//属性拷贝 属性名词和类型相同才能拷贝BeanUtils.copyProperties(dto,wmNews);//封面图片 list---> stringif(dto.getImages() != null && dto.getImages().size() > 0){//[1dddfsd.jpg,sdlfjldk.jpg]--> 1dddfsd.jpg,sdlfjldk.jpgString imageStr = StringUtils.join(dto.getImages(), ",");wmNews.setImages(imageStr);}//如果当前封面类型为自动 -1if(dto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)){wmNews.setType(null);}saveOrUpdateWmNews(wmNews);//2.判断是否为草稿 如果为草稿结束当前方法if(dto.getStatus().equals(WmNews.Status.NORMAL.getCode())){return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);}//3.不是草稿,保存文章内容图片与素材的关系//获取到文章内容中的图片信息List<String> materials = ectractUrlInfo(dto.getContent());saveRelativeInfoForContent(materials,wmNews.getId());//4.不是草稿,保存文章封面图片与素材的关系,如果当前布局是自动,需要匹配封面图片saveRelativeInfoForCover(dto,wmNews,materials);return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);}/*** 第一个功能:如果当前封面类型为自动,则设置封面类型的数据* 匹配规则:* 1,如果内容图片大于等于1,小于3 单图 type 1* 2,如果内容图片大于等于3 多图 type 3* 3,如果内容没有图片,无图 type 0** 第二个功能:保存封面图片与素材的关系* @param dto* @param wmNews* @param materials*/
private void saveRelativeInfoForCover(WmNewsDto dto, WmNews wmNews, List<String> materials) {List<String> images = dto.getImages();//如果当前封面类型为自动,则设置封面类型的数据if(dto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)){//多图if(materials.size() >= 3){wmNews.setType(WemediaConstants.WM_NEWS_MANY_IMAGE);images = materials.stream().limit(3).collect(Collectors.toList());}else if(materials.size() >= 1 && materials.size() < 3){//单图wmNews.setType(WemediaConstants.WM_NEWS_SINGLE_IMAGE);images = materials.stream().limit(1).collect(Collectors.toList());}else {//无图wmNews.setType(WemediaConstants.WM_NEWS_NONE_IMAGE);}//修改文章if(images != null && images.size() > 0){wmNews.setImages(StringUtils.join(images,","));}updateById(wmNews);}if(images != null && images.size() > 0){saveRelativeInfo(images,wmNews.getId(),WemediaConstants.WM_COVER_REFERENCE);}}/*** 处理文章内容图片与素材的关系* @param materials* @param newsId*/
private void saveRelativeInfoForContent(List<String> materials, Integer newsId) {saveRelativeInfo(materials,newsId,WemediaConstants.WM_CONTENT_REFERENCE);
}@Autowired
private WmMaterialMapper wmMaterialMapper;/*** 保存文章图片与素材的关系到数据库中* @param materials* @param newsId* @param type*/
private void saveRelativeInfo(List<String> materials, Integer newsId, Short type) {if(materials!=null && !materials.isEmpty()){//通过图片的url查询素材的idList<WmMaterial> dbMaterials = wmMaterialMapper.selectList(Wrappers.<WmMaterial>lambdaQuery().in(WmMaterial::getUrl, materials));//判断素材是否有效if(dbMaterials==null || dbMaterials.size() == 0){//手动抛出异常 第一个功能:能够提示调用者素材失效了,第二个功能,进行数据的回滚throw new CustomException(AppHttpCodeEnum.MATERIASL_REFERENCE_FAIL);}if(materials.size() != dbMaterials.size()){throw new CustomException(AppHttpCodeEnum.MATERIASL_REFERENCE_FAIL);}List<Integer> idList = dbMaterials.stream().map(WmMaterial::getId).collect(Collectors.toList());//批量保存wmNewsMaterialMapper.saveRelations(idList,newsId,type);}}/*** 提取文章内容中的图片信息* @param content* @return*/
private List<String> ectractUrlInfo(String content) {List<String> materials = new ArrayList<>();List<Map> maps = JSON.parseArray(content, Map.class);for (Map map : maps) {if(map.get("type").equals("image")){String imgUrl = (String) map.get("value");materials.add(imgUrl);}}return materials;
}@Autowired
private WmNewsMaterialMapper wmNewsMaterialMapper;/*** 保存或修改文章* @param wmNews*/
private void saveOrUpdateWmNews(WmNews wmNews) {//补全属性wmNews.setUserId(WmThreadLocalUtil.getUser().getId());wmNews.setCreatedTime(new Date());wmNews.setSubmitedTime(new Date());wmNews.setEnable((short)1);//默认上架if(wmNews.getId() == null){//保存save(wmNews);}else {//修改//删除文章图片与素材的关系wmNewsMaterialMapper.delete(Wrappers.<WmNewsMaterial>lambdaQuery().eq(WmNewsMaterial::getNewsId,wmNews.getId()));updateById(wmNews);}}
④:控制器
@PostMapping("/submit")
public ResponseResult submitNews(@RequestBody WmNewsDto dto){return wmNewsService.submitNews(dto);
}
3.3.6)测试
== 0){
//手动抛出异常 第一个功能:能够提示调用者素材失效了,第二个功能,进行数据的回滚
throw new CustomException(AppHttpCodeEnum.MATERIASL_REFERENCE_FAIL);
}
if(materials.size() != dbMaterials.size()){throw new CustomException(AppHttpCodeEnum.MATERIASL_REFERENCE_FAIL);}List<Integer> idList = dbMaterials.stream().map(WmMaterial::getId).collect(Collectors.toList());//批量保存wmNewsMaterialMapper.saveRelations(idList,newsId,type);
}
}
/**
* 提取文章内容中的图片信息
* @param content
* @return
*/
private List ectractUrlInfo(String content) {
List materials = new ArrayList<>();
List<Map> maps = JSON.parseArray(content, Map.class);
for (Map map : maps) {if(map.get("type").equals("image")){String imgUrl = (String) map.get("value");materials.add(imgUrl);}
}return materials;
}
@Autowired
private WmNewsMaterialMapper wmNewsMaterialMapper;
/**
* 保存或修改文章
* @param wmNews
*/
private void saveOrUpdateWmNews(WmNews wmNews) {
//补全属性
wmNews.setUserId(WmThreadLocalUtil.getUser().getId());
wmNews.setCreatedTime(new Date());
wmNews.setSubmitedTime(new Date());
wmNews.setEnable((short)1);//默认上架
if(wmNews.getId() == null){//保存save(wmNews);
}else {//修改//删除文章图片与素材的关系wmNewsMaterialMapper.delete(Wrappers.<WmNewsMaterial>lambdaQuery().eq(WmNewsMaterial::getNewsId,wmNews.getId()));updateById(wmNews);
}
}
④:控制器```java
@PostMapping("/submit")
public ResponseResult submitNews(@RequestBody WmNewsDto dto){return wmNewsService.submitNews(dto);
}
3.3.6)测试
相关文章:
03-自媒体文章发布
自媒体文章发布 1)自媒体前后端搭建 1.1)后台搭建 ①:资料中找到heima-leadnews-wemedia.zip解压 拷贝到heima-leadnews-service工程下,并指定子模块 执行leadnews-wemedia.sql脚本 添加对应的nacos配置 spring:datasource:driver-class-name: com…...
Oracle中实现一次插入多条数据
一、需求描述 在我们实际的业务场景中,由于单条插入的效率很低(每次都需要数据库资源连接关闭的开销),故需要实现一次性插入多条数据,用以提升数据插入的效率; 如下图是常见的单条插入数据: 二…...
【C++入门】关键字、命名空间以及输入输出
💞💞 前言 hello hello~ ,这里是大耳朵土土垚~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹 💥个人主页&#x…...
初识MySQL(中篇)
使用语言 MySQL 使用工具 Navicat Premium 16 代码能力快速提升小方法,看完代码自己敲一遍,十分有用 目录 1.SQL语言 1.1 SQL语言组成部分 2.MySQL数据类型 2.1 数值类型 2.2 字符串类型 2.3 日期类型 3.创建数据表 3.1 创建数据表方法1 …...
前端订阅后端推送WebSocket定时任务
0.需求 后端定时向前端看板推送数据,每10秒或者30秒推送一次。 1.前言知识 HTTP协议是一个应用层协议,它的特点是无状态、无连接和单向的。在HTTP协议中,客户端发起请求,服务器则对请求进行响应。这种请求-响应的模式意味着服务器…...
提高机器人系统稳定性:引入阻尼作为共振后的相位超前
在机器人关节中,引入阻尼作为共振后的相位超前,确实是一种提高系统稳定性的有效策略。机器人关节的振动和共振是影响其性能稳定性的关键因素,特别是在进行高速、高精度操作时。阻尼的引入能够显著减少这些不利因素,提升机器人的整…...
深度学习理论基础(三)封装数据集及手写数字识别
目录 前期准备一、制作数据集1. excel表格数据2. 代码 二、手写数字识别1. 下载数据集2. 搭建模型3. 训练网络4. 测试网络5. 保存训练模型6. 导入已经训练好的模型文件7. 完整代码 前期准备 必须使用 3 个 PyTorch 内置的实用工具(utils): ⚫…...
vue3+eachrts饼图轮流切换显示高亮数据
<template><div class"charts-box"><div class"charts-instance" ref"chartRef"></div>// 自定义legend 样式<div class"charts-note"><span v-for"(items, index) in data.dataList" cla…...
UTONMOS:AI+Web3+元宇宙数字化“三位一体”将触发经济新爆点
人工智能、元宇宙、Web3,被称为数字化的“三位一体”,如何看待这三大技术所扮演的角色? 3月24日,2024全球开发者先锋大会“数字化的三位一体——人工智能、元宇宙、Web3.0”论坛在上海漕河泾开发区举行,首次提出&…...
开始焦虑了
大家好,我是洋子,25届的暑期实习自从3月份开始招聘有一段时间了,最近接到了几个25届同学的咨询,其中一个学妹印象比较深刻,她的情况如下 个人情况 学历是双非本,计算机专业,学习方向是Java&…...
数据结构和算法:十大排序
排序算法 排序算法用于对一组数据按照特定顺序进行排列。排序算法有着广泛的应用,因为有序数据通常能够被更高效地查找、分析和处理。 排序算法中的数据类型可以是整数、浮点数、字符或字符串等。排序的判断规则可根据需求设定,如数字大小、字符 ASCII…...
LLaMA-Factory微调(sft)ChatGLM3-6B保姆教程
LLaMA-Factory微调(sft)ChatGLM3-6B保姆教程 准备 1、下载 下载LLaMA-Factory下载ChatGLM3-6B下载ChatGLM3windows下载CUDA ToolKit 12.1 (本人是在windows进行训练的,显卡GTX 1660 Ti) CUDA安装完毕后,…...
Web安全-浏览器安全策略及跨站脚本攻击与请求伪造漏洞原理
Web安全-浏览器安全策略及跨站脚本攻击与请求伪造漏洞原理 Web服务组件分层概念 静态层 :web前端框架:Bootstrap,jQuery,HTML5框架等,主要存在跨站脚本攻击脚本层:web应用,web开发框架,web服务…...
蓝桥杯B组C++省赛——飞机降落(DFS)
题目连接:https://www.lanqiao.cn/problems/3511/learning/ 思路:由于数据范围很小,所有选择用DFS枚举所有飞机的所有的降落顺序,看哪个顺序可以让所有飞机顺利降落,有的话就算成功方案,输出了“YES”。 …...
Java 中的 Map集合
文章目录 添加和修改元素获取元素检查元素删除元素获取所有键 / 值 / 键值对大小 在 Java 中,Map 接口是 Java 集合框架的一部分,它存储键值对(key-value pairs)。Map 接口有许多常用的方法,用于添加、删除、获取元素&…...
基于springboot大学生兼职平台管理系统(完整源码+数据库)
一、项目简介 本项目是一套基于springboot大学生兼职平台管理系统 包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试,eclipse或者idea 确保可以运行! 该系统功能完善、界面美观、操作简单、功…...
C#学生信息管理系统
一、引言 学生信息管理系统是现代学校管理的重要组成部分,它能够有效地管理学生的基本信息、课程信息、成绩信息等,提高学校管理的效率和质量。本文将介绍如何使用SQL Server数据库和C#语言在.NET平台上开发一个学生信息管理系统的课程设计项目。 二、项…...
双机 Cartogtapher 建图文件配置
双机cartogtapher建图 最近在做硕士毕设的最后一个实验,其中涉及到多机建图,经过调研最终采用cartographer建图算法,其中配置多机建图的文件有些麻烦,特此博客以记录 非常感谢我的同门 ”叶少“ 山上的稻草人-CSDN博客的帮助&am…...
VMware提示 该虚拟机似乎正在使用中,如何解决?
VMware提示 该虚拟机似乎正在使用中,如何解决? 问题描述解决方法1.找到安装VMware的文件目录2.在VMware目录下.lck后缀的文件夹删除或重命名3.运行VMware 问题描述 该虚拟机似乎正在使用中。 如果该虚拟机未在使用,请按“获取所有权(T)”按钮获取它的所…...
阿里云短信服务业务
一、了解阿里云用户权限操作 1.注册账号、实名认证; 2.使用AccessKey 步骤一 点击头像,权限安全的AccessKey 步骤二 设置子用户AccessKey 步骤三 添加用户组和用户 步骤四 添加用户组记得绑定短信服务权限 步骤五 添加用户记得勾选openApi访问 添加…...
ElasticSearch的DSL查询
ElasticSearch的DSL查询 准备工作 创建测试方法,初始化测试结构。 import org.apache.http.HttpHost; import org.apache.lucene.search.TotalHits; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchRespo…...
每天定时杀spark进程
##编写shell脚本 #!/bin/bash arr(“zhangsan” “lisi” “wangwu”) for i in “${arr[]}” do processps -ef|grep ${i}| grep -v "grep"| awk {print $2} kill -9 ${process} done ##每日定时杀手动启动的进程 0 19 * * * cd /kill_process && sh kil…...
win10 安装kubectl,配置config连接k8s集群
安装kubectl 按照官方文档安装:https://kubernetes.io/docs/tasks/tools/install-kubectl-windows/ curl安装 (1)下载curl安装压缩包: curl for Windows (2)配置环境变量: 用户变量: Path变…...
Calico IPIP和BGP TOR的数据包走向
IPIP Mesh全网互联 文字描述 APOD eth0 10.7.75.132 -----> APOD 网关 -----> A宿主机 cali76174826315网卡 -----> Atunl0 10.7.75.128 封装 ----> Aeth0 10.120.181.20 -----> 通过网关 10.120.181.254 -----> 下一跳 BNODE eth0 10.120.179.8 解封装 --…...
静态成员主要用于提供与类本身相关的功能或数据,有什么应用场景
静态成员(包括静态方法和静态属性)在JavaScript中常用于多种应用场景,它们为类提供了与类本身直接相关而不是与实例相关的功能或数据。以下是一些常见的应用场景: 工厂方法 静态方法可以作为工厂方法,用于创建类的实…...
在线考试|基于Springboot的在线考试管理系统设计与实现(源码+数据库+文档)
在线考试管理系统目录 目录 基于Springboot的在线考试管理系统设计与实现 一、前言 二、系统设计 三、系统功能设计 1、前台: 2、后台 管理员功能 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取: 博主…...
C语言-----数据在内存中的存储(1)
1.整数在内存中的存储 我们之前就了解过整数的二进制写法分别有3种,分别为原码,反码,补码。整型在内存中存储的是补码。 原码,反码,补码都有自己的符号位和数值位,符号位为1时,则表示负数&…...
Ribbon有哪些负载均衡策略
负载均衡类都实现了IRule接口。 RandomRule:随机的选用一个实例 RoundRobinRule:轮询的使用实例 RetryRule:在轮询的基础上加了一个错误重试机制,在deadline时间内会不断的重试 WeightResponeTimeRule:根据权重去做…...
websocket多级nginx代理
在使用多层Nginx代理时,WebSocket的连接可能会遇到一些问题,因为WebSocket连接是持久化的,它需要Upgrade头部来确认升级到WebSocket协议。在多层代理的情况下,每层代理可能会修改或丢失这个Upgrade头部信息。 为了确保WebSocket能…...
【python从入门到精通】-- 第四战:语句汇总
🌈 个人主页:白子寰 🔥 分类专栏:python从入门到精通,魔法指针,进阶C,C语言,C语言题集,C语言实现游戏👈 希望得到您的订阅和支持~ 💡 坚持创作博文…...
新兴县做网站的/全球搜是什么公司
前言 1、Promise 的意义? 在javascript的世界中,所有代码都是单线程执行的,由于这个“缺陷”,导致JavaScript的所有网络操作,浏览器事件,都必须是异步执行。Ajax可以解决这个问题,但是并不好复用…...
vr模式的网站建设公司/上海关键词排名优化怎样
本文章是❤️力扣 (LeetCode)❤️的内容,该专栏还有多篇优质内容在等待你观看,现在点击右上角点击这个————🚀订阅专栏🚀 🔆坚持刷算法 💎每天进步一点点 🚀冲冲冲冲冲冲冲冲冲冲 Ǵ…...
wordpress 文章页 模板/广州网站快速优化排名
某天使用cmd窗口进入mysql,输入命令如下 C:\Users\xxx>net start mysql发生系统错误 5。 拒绝访问。 C:\Users\xxx>mysql -u root -pEnter password: ****ERROR 2003 (HY000): Cant connect to MySQL server on localhost:3306 (10061) 这个ERROR怎么解决…...
wordpress 怎么添加即时联系窗口/网店运营流程步骤
原标题:听说,近视的人智商更高?近视的你还好吗如果你在学校里走路的时候碰到了熟人跟他打招呼却没有得到回应千万不要生气因为他可能是因为……………………没戴眼镜!!!近日,德国美因茨大学科学…...
网站建设之织梦模板/b2b网站平台
str.format() Python2.6之后新增的一宗格式化字符串的函数。 用{}和:来替换以前的% >>>"{} {}".format("hello", "world") # 不设置指定位置,按默认顺序 hello world>>> "{0} {1}".format("h…...
做论坛网站价格/百度推广
原文地址:http://dev.mysql.com/tech-resources/articles/hierarchical-data.html 作者:Mike Hillyer 翻译:陈建平 chinaontologygmail.com 摘要:无限分级的树状结构往往很难处理,作者推荐“嵌套集合模型”方法&…...