[JavaWeb]微头条项目
完整笔记和项目代码:
https://pan.baidu.com/s/1PZBO0mfpwDPic4Ezsk8orA?pwd=wwp5 提取码: wwp5
JavaWeb-微头条项目开发
1 项目简介
1.1 业务介绍
微头条新闻发布和浏览平台,主要包含业务如下
- 用户功能
- 注册功能
- 登录功能
- 头条新闻
- 新闻的分页浏览
- 通过标题关键字搜索新闻
- 查看新闻详情
- 新闻的修改和删除
- 权限控制
- 用户只能修改和自己发布的头条新闻
1.2 技术栈介绍
前端技术栈
- ES6作为基础JS语法
- nodejs用于运行环境
- npm用于项目依赖管理工具
- vite用于项目的构建架工具
- Vue3用于项目数据的渲染框架
- Axios用于前后端数据的交互
- Router用于页面的跳转
- Pinia用于存储用户的数据
- LocalStorage作为用户校验token的存储手段
- Element-Plus提供组件
后端技术栈
- JAVA作为开发语言,版本为JDK17
- Tomcat作为服务容器,版本为10.1.7
- Mysql8用于项目存储数据
- Servlet用于控制层实现前后端数据交互
- JDBC用于实现数据的CURD
- Druid用于提供数据源的连接池
- MD5用于用户密码的加密
- Jwt用于token的生成和校验
- Jackson用于转换JSON
- Filter用于用户登录校验和跨域处理
- Lombok用于处理实体类
1.3 后端项目结构
创建Web项目
导入依赖
准备包结构
- controller 控制层代码,主要由Servlet组成
- service 服务层代码,主要用于处理业务逻辑
- dao 数据访问层,主要用户定义对于各个表格的CURD的方法
- pojo 实体类层,主要用于存放和数据库对应的实体类以及一些VO对象
- util 工具类包,主要用存放一些工具类
- common 公共包,主要用户存放一些其他公共代码
- filters 过滤器包,专门用于存放一些过滤器
- test 测试代码包,专门用于定义一些测试的功能代码,上线前应该删掉,后期用maven可以自动处理掉
2 项目框架源码和注解
2.1 工具类
2.1.1 异步响应规范格式类
- Result类
package com.atguigu.headline.common;/*** 全局统一返回结果类**/
public class Result<T> {// 返回码private Integer code;// 返回消息private String message;// 返回数据private T data;public Result(){}// 返回数据protected static <T> Result<T> build(T data) {Result<T> result = new Result<T>();if (data != null)result.setData(data);return result;}public static <T> Result<T> build(T body, Integer code, String message) {Result<T> result = build(body);result.setCode(code);result.setMessage(message);return result;}public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {Result<T> result = build(body);result.setCode(resultCodeEnum.getCode());result.setMessage(resultCodeEnum.getMessage());return result;}/*** 操作成功* @param data baseCategory1List* @param <T>* @return*/public static<T> Result<T> ok(T data){Result<T> result = build(data);return build(data, ResultCodeEnum.SUCCESS);}public Result<T> message(String msg){this.setMessage(msg);return this;}public Result<T> code(Integer code){this.setCode(code);return this;}public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public T getData() {return data;}public void setData(T data) {this.data = data;}
}
- ResultCodeEnum 枚举类
package com.atguigu.headline.common;
/*** 统一返回结果状态信息类**/
public enum ResultCodeEnum {SUCCESS(200,"success"),USERNAME_ERROR(501,"usernameError"),PASSWORD_ERROR(503,"passwordError"),NOTLOGIN(504,"notLogin"),USERNAME_USED(505,"userNameUsed");private Integer code;private String message;private ResultCodeEnum(Integer code, String message) {this.code = code;this.message = message;}public Integer getCode() {return code;}public String getMessage() {return message;}
}
2.1.2 MD5加密工具类
package com.atguigu.headline.util;import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;public final class MD5Util {public static String encrypt(String strSrc) {try {char hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8','9', 'a', 'b', 'c', 'd', 'e', 'f' };byte[] bytes = strSrc.getBytes();MessageDigest md = MessageDigest.getInstance("MD5");md.update(bytes);bytes = md.digest();int j = bytes.length;char[] chars = new char[j * 2];int k = 0;for (int i = 0; i < bytes.length; i++) {byte b = bytes[i];chars[k++] = hexChars[b >>> 4 & 0xf];chars[k++] = hexChars[b & 0xf];}return new String(chars);} catch (NoSuchAlgorithmException e) {e.printStackTrace();throw new RuntimeException("MD5加密出错!!+" + e);}}
}
2.1.3 JDBCUtil连接池工具类
package com.atguigu.headline.util;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;public class JDBCUtil {private static ThreadLocal<Connection> threadLocal =new ThreadLocal<>();private static DataSource dataSource;// 初始化连接池static{// 可以帮助我们读取.properties配置文件Properties properties =new Properties();InputStream resourceAsStream = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");try {properties.load(resourceAsStream);} catch (IOException e) {throw new RuntimeException(e);}try {dataSource = DruidDataSourceFactory.createDataSource(properties);} catch (Exception e) {throw new RuntimeException(e);}}/*1 向外提供连接池的方法*/public static DataSource getDataSource(){return dataSource;}/*2 向外提供连接的方法*/public static Connection getConnection(){Connection connection = threadLocal.get();if (null == connection) {try {connection = dataSource.getConnection();} catch (SQLException e) {throw new RuntimeException(e);}threadLocal.set(connection);}return connection;}/*定义一个归还连接的方法 (解除和ThreadLocal之间的关联关系) */public static void releaseConnection(){Connection connection = threadLocal.get();if (null != connection) {threadLocal.remove();// 把连接设置回自动提交的连接try {connection.setAutoCommit(true);// 自动归还到连接池connection.close();} catch (SQLException e) {throw new RuntimeException(e);}}}
}
添加jdbc.properties配置文件
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/top_news
username=root
password=root
initialSize=5
maxActive=10
maxWait=1000
2.1.4 JwtHelper工具类
package com.atguigu.headline.util;import com.alibaba.druid.util.StringUtils;
import io.jsonwebtoken.*;import java.util.Date;public class JwtHelper {private static long tokenExpiration = 24*60*60*1000;private static String tokenSignKey = "123456";//生成token字符串public static String createToken(Long userId) {String token = Jwts.builder().setSubject("YYGH-USER").setExpiration(new Date(System.currentTimeMillis() + tokenExpiration)).claim("userId", userId).signWith(SignatureAlgorithm.HS512, tokenSignKey).compressWith(CompressionCodecs.GZIP).compact();return token;}//从token字符串获取useridpublic static Long getUserId(String token) {if(StringUtils.isEmpty(token)) return null;Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);Claims claims = claimsJws.getBody();Integer userId = (Integer)claims.get("userId");return userId.longValue();}//判断token是否有效public static boolean isExpiration(String token){try {boolean isExpire = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token).getBody().getExpiration().before(new Date());//没有过期,有效,返回falsereturn isExpire;}catch(Exception e) {//过期出现异常,返回truereturn true;}}
}
2.1.5 JSON转换的WEBUtil工具类
package com.atguigu.headline.util;import com.atguigu.headline.common.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.BufferedReader;
import java.io.IOException;
import java.text.SimpleDateFormat;public class WebUtil {private static ObjectMapper objectMapper;// 初始化objectMapperstatic{objectMapper=new ObjectMapper();// 设置JSON和Object转换时的时间日期格式objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));}// 从请求中获取JSON串并转换为Objectpublic static <T> T readJson(HttpServletRequest request,Class<T> clazz){T t =null;BufferedReader reader = null;try {reader = request.getReader();StringBuffer buffer =new StringBuffer();String line =null;while((line = reader.readLine())!= null){buffer.append(line);}t= objectMapper.readValue(buffer.toString(),clazz);} catch (IOException e) {throw new RuntimeException(e);}return t;}// 将Result对象转换成JSON串并放入响应对象public static void writeJson(HttpServletResponse response, Result result){response.setContentType("application/json;charset=UTF-8");try {String json = objectMapper.writeValueAsString(result);response.getWriter().write(json);} catch (IOException e) {throw new RuntimeException(e);}}
}
2.2 实体类和VO对象
2.2.1 NewsUser
package com.atguigu.headline.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;@AllArgsConstructor
@NoArgsConstructor
@Data
public class NewsUser implements Serializable {private Integer uid;private String username;private String userPwd;private String nickName;
}
2.2.2 NewsType
package com.atguigu.headline.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;@AllArgsConstructor
@NoArgsConstructor
@Data
public class NewsType implements Serializable {private Integer tid;private String tname;
}
2.2.3 NewsHeadline
package com.atguigu.headline.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;@AllArgsConstructor
@NoArgsConstructor
@Data
public class NewsHeadline implements Serializable {private Integer hid;private String title;private String article;private Integer type;private Integer publisher;private Integer pageViews;private Date createTime;private Date updateTime;private Integer isDeleted;}
2.2.4 HeadlineQueryVo
package com.atguigu.headline.pojo.vo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;@AllArgsConstructor
@NoArgsConstructor
@Data
public class HeadlineQueryVo implements Serializable {private String keyWords;private Integer type ;private Integer pageNum;private Integer pageSize;
}
2.2.5 HeadlinePageVo
package com.atguigu.headline.pojo.vo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;@AllArgsConstructor
@NoArgsConstructor
@Data
public class HeadlinePageVo implements Serializable {private Integer hid;private String title;private Integer type;private Integer pageViews;private Long pastHours;private Integer publisher;
}
2.2.6 HeadlineDetailVo
package com.atguigu.headline.pojo.vo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;@AllArgsConstructor
@NoArgsConstructor
@Data
public class HeadlineDetailVo implements Serializable {private Integer hid;private String title;private String article;private Integer type;private String typeName;private Integer pageViews;private Long pastHours;private Integer publisher;private String author;
}
2.3 Dao层
BaseDao基础类,封装了公共的查询方法和公共的增删改方法
注意,所有的Dao接口的实现类都要继承BaseDao
2.3.1 BaseDao
package com.atguigu.headline.dao;import com.atguigu.headline.util.JDBCUtil;
import java.lang.reflect.Field;
import java.sql.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;public class BaseDao {// 公共的查询方法 返回的是单个对象public <T> T baseQueryObject(Class<T> clazz, String sql, Object ... args) {T t = null;Connection connection = JDBCUtil.getConnection();PreparedStatement preparedStatement = null;ResultSet resultSet = null;int rows = 0;try {// 准备语句对象preparedStatement = connection.prepareStatement(sql);// 设置语句上的参数for (int i = 0; i < args.length; i++) {preparedStatement.setObject(i + 1, args[i]);}// 执行 查询resultSet = preparedStatement.executeQuery();if (resultSet.next()) {t = (T) resultSet.getObject(1);}} catch (Exception e) {throw new RuntimeException(e);} finally {if (null != resultSet) {try {resultSet.close();} catch (SQLException e) {throw new RuntimeException(e);}}if (null != preparedStatement) {try {preparedStatement.close();} catch (SQLException e) {throw new RuntimeException(e);}}JDBCUtil.releaseConnection();}return t;}// 公共的查询方法 返回的是对象的集合public <T> List<T> baseQuery(Class clazz, String sql, Object ... args){List<T> list =new ArrayList<>();Connection connection = JDBCUtil.getConnection();PreparedStatement preparedStatement=null;ResultSet resultSet =null;int rows = 0;try {// 准备语句对象preparedStatement = connection.prepareStatement(sql);// 设置语句上的参数for (int i = 0; i < args.length; i++) {preparedStatement.setObject(i+1,args[i]);}// 执行 查询resultSet = preparedStatement.executeQuery();ResultSetMetaData metaData = resultSet.getMetaData();int columnCount = metaData.getColumnCount();// 将结果集通过反射封装成实体类对象while (resultSet.next()) {// 使用反射实例化对象Object obj =clazz.getDeclaredConstructor().newInstance();for (int i = 1; i <= columnCount; i++) {String columnName = metaData.getColumnLabel(i);Object value = resultSet.getObject(columnName);// 处理datetime类型字段和java.util.Data转换问题if(value.getClass().equals(LocalDateTime.class)){value= Timestamp.valueOf((LocalDateTime) value);}Field field = clazz.getDeclaredField(columnName);field.setAccessible(true);field.set(obj,value);}list.add((T)obj);}} catch (Exception e) {throw new RuntimeException(e);} finally {if (null !=resultSet) {try {resultSet.close();} catch (SQLException e) {throw new RuntimeException(e);}}if (null != preparedStatement) {try {preparedStatement.close();} catch (SQLException e) {throw new RuntimeException(e);}}JDBCUtil.releaseConnection();}return list;}// 通用的增删改方法public int baseUpdate(String sql,Object ... args) {// 获取连接Connection connection = JDBCUtil.getConnection();PreparedStatement preparedStatement=null;int rows = 0;try {// 准备语句对象preparedStatement = connection.prepareStatement(sql);// 设置语句上的参数for (int i = 0; i < args.length; i++) {preparedStatement.setObject(i+1,args[i]);}// 执行 增删改 executeUpdaterows = preparedStatement.executeUpdate();// 释放资源(可选)} catch (SQLException e) {throw new RuntimeException(e);} finally {if (null != preparedStatement) {try {preparedStatement.close();} catch (SQLException e) {throw new RuntimeException(e);}}JDBCUtil.releaseConnection();}// 返回的是影响数据库记录数return rows;}
}
2.3.2 Dao层所有接口
package com.atguigu.headline.dao;
public interface NewsHeadLineDao {}package com.atguigu.headline.dao;
public interface NewsTypeDao {}package com.atguigu.headline.dao;
public interface NewsUserDao {}
2.3.3 dao层所有实现类
package com.atguigu.headline.dao.impl;
import com.atguigu.headline.dao.BaseDao;
import com.atguigu.headline.dao.NewsHeadLineDao;
public class NewsHeadlineDaoImpl extends BaseDao implements NewsHeadLineDao{}package com.atguigu.headline.dao.impl;
import com.atguigu.headline.dao.BaseDao;
import com.atguigu.headline.dao.NewsTypeDao;
public class NewsTypeDaoImpl extends BaseDao implements NewsTypeDao{}package com.atguigu.headline.dao.impl;
import com.atguigu.headline.dao.BaseDao;
import com.atguigu.headline.dao.NewsUserDao;
public class NewsUserDaoImpl extends BaseDao implements NewsUserDao{}
2.4 Service层
2.4.1 service层所有接口
package com.atguigu.headline.service;
public interface NewsHeadlineService {}package com.atguigu.headline.service;
public interface NewsTypeService {List<NewsType> findAll();
}package com.atguigu.headline.service;
public interface NewsUserService {}
2.4.2 service层所有实现类
package com.atguigu.headline.service.impl;
import com.atguigu.headline.service.NewsHeadlineService;
public class NewsHeadlineServiceImpl implements NewsHeadlineService {
}package com.atguigu.headline.service.impl;
import com.atguigu.headline.service.NewsTypeService;
public class NewsTypeServiceImpl implements NewsTypeService {}package com.atguigu.headline.service.impl;
import com.atguigu.headline.service.NewsUserService;
public class NewsUserServiceImpl implements NewsUserService {}
2.5 Controller层
BaseController 用于将路径关联到处理方法的基础控制器,所有的Controller都要继承该类
2.5.1 BaseController
package com.atguigu.headline.controller;import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;
import java.lang.reflect.Method;public class BaseController extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 响应的MIME类型和乱码问题resp.setContentType("application/json;charset=UTF-8");String requestURI = req.getRequestURI();String[] split = requestURI.split("/");String methodName =split[split.length-1];// 通过反射获取要执行的方法Class clazz = this.getClass();try {Method method=clazz.getDeclaredMethod(methodName,HttpServletRequest.class,HttpServletResponse.class);// 设置方法可以访问method.setAccessible(true);// 通过反射执行代码method.invoke(this,req,resp);} catch (Exception e) {e.printStackTrace();throw new RuntimeException(e.getMessage());}}
}
2.5.2 所有的Controller类
package com.atguigu.headline.controller;
import jakarta.servlet.annotation.WebServlet;
@WebServlet("/headline/*")
public class NewsHeadlineController extends BaseController {}package com.atguigu.headline.controller;
import jakarta.servlet.annotation.WebServlet;
@WebServlet("/type/*")
public class NewsTypeController {}package com.atguigu.headline.controller;
import jakarta.servlet.annotation.WebServlet;
@WebServlet("/user/*")
public class NewsUserController extends BaseController{}package com.atguigu.headline.controller;
import jakarta.servlet.annotation.WebServlet;
@WebServlet("/portal/*")
public class PortalController extends BaseController{}
2.6 过滤器
2.6.1 跨域过滤器
package com.atguigu.headline.filters;import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;@WebFilter("/*")
public class CrosFilter implements Filter {@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletResponse response = (HttpServletResponse) servletResponse;HttpServletRequest request =(HttpServletRequest) servletRequest;response.setHeader("Access-Control-Allow-Origin", "*");response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, HEAD");response.setHeader("Access-Control-Max-Age", "3600");response.setHeader("Access-Control-Allow-Headers", "access-control-allow-origin, authority, content-type, version-info, X-Requested-With");// 非预检请求,放行即可,预检请求,则到此结束,不需要放行if(!request.getMethod().equalsIgnoreCase("OPTIONS")){filterChain.doFilter(servletRequest, servletResponse);}}
}
3 项目具体实现
3.1 登录注册功能
3.1.1 登录表单提交
需求描述
- 用户在客户端输入用户名密码并向后端提交,后端根据用户名和密码判断登录是否成功,用户有误或者密码有误响应不同的提示信息
uri:
user/login
请求方式:
POST
请求参数
{"username":"zhangsan", //用户名"userPwd":"123456" //明文密码
}
响应示例
- 登录成功
{"code":"200", // 成功状态码 "message":"success" // 成功状态描述"data":{"token":"... ..." // 用户id的token}
}
- 用户名有误
{"code":"501","message":"用户名有误""data":{}
}
- 密码有误
{"code":"503","message":"密码有误""data":{}
}
后端代码
- NewsUserController
package com.atguigu.headline.controller;import com.atguigu.headline.common.Result;
import com.atguigu.headline.common.ResultCodeEnum;
import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.NewsUser;
import com.atguigu.headline.service.NewsUserService;
import com.atguigu.headline.service.impl.NewsUserServiceImpl;
import com.atguigu.headline.util.JwtHelper;
import com.atguigu.headline.util.MD5Util;
import com.atguigu.headline.util.WebUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;
import java.util.HashMap;
import java.util.Map;@WebServlet("/user/*")
public class NewsUserController extends BaseController{private NewsUserService newsUserService =new NewsUserServiceImpl();/*** 登录验证* @param req* @param resp* @throws ServletException* @throws IOException*/protected void login(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {NewsUser newsUser = WebUtil.readJson(req, NewsUser.class);Result result =null;NewsUser loginNewsUser =newsUserService.findByUserName(newsUser.getUsername());// 判断用户名if (null != loginNewsUser) {// 判断密码if(loginNewsUser.getUserPwd().equals(MD5Util.encrypt(newsUser.getUserPwd()))){// 密码正确Map<String,Object> data =new HashMap<>();// 生成token口令String token = JwtHelper.createToken(loginNewsUser.getUid().longValue());// 封装数据mapdata.put("token",token);// 封装结果result=Result.ok(data);}else{// 封装密码错误结果result=Result.build(null, ResultCodeEnum.PASSWORD_ERROR);}}else{// 封装用户名错误结果result=Result.build(null, ResultCodeEnum.USERNAME_ERROR);}// 响应结果WebUtil.writeJson(resp,result);}
}
- NewsUserService
package com.atguigu.headline.service;import com.atguigu.headline.pojo.NewsUser;public interface NewsUserService {/*** 根据用户名,获得查询用户的方法* @param username 要查询的用户名* @return 如果找到返回NewsUser对象,找不到返回null*/NewsUser findByUserName(String username);
}
- NewsUserServiceImpl
package com.atguigu.headline.service.impl;import com.atguigu.headline.dao.NewsUserDao;
import com.atguigu.headline.dao.impl.NewsUserDaoImpl;
import com.atguigu.headline.pojo.NewsUser;
import com.atguigu.headline.service.NewsTypeService;
import com.atguigu.headline.service.NewsUserService;
import com.atguigu.headline.util.MD5Util;public class NewsUserServiceImpl implements NewsUserService {private NewsUserDao newsUserDao =new NewsUserDaoImpl();@Overridepublic NewsUser findByUserName(String username) {return newsUserDao.findByUserName(username);}
}
- NewUserDao
package com.atguigu.headline.dao;
import com.atguigu.headline.pojo.NewsUser;public interface NewsUserDao {/*** 根据用户名查询用户信息* @param username 要查询的用户名* @return 找到返回NewsUser对象,找不到返回null*/NewsUser findByUserName(String username);
}
- NewsUserDaoImpl
package com.atguigu.headline.dao.impl;import com.atguigu.headline.dao.BaseDao;
import com.atguigu.headline.dao.NewsUserDao;
import com.atguigu.headline.pojo.NewsUser;
import java.util.List;public class NewsUserDaoImpl extends BaseDao implements NewsUserDao {@Overridepublic NewsUser findByUserName(String username) {// 准备SQLString sql ="select uid,username,user_pwd userPwd ,nick_name nickName from news_user where username = ?";// 调用BaseDao公共查询方法List<NewsUser> newsUserList = baseQuery(NewsUser.class, sql, username);// 如果找到,返回集合中的第一个数据(其实就一个)if (null != newsUserList && newsUserList.size()>0){return newsUserList.get(0);}return null;}
}
3.1.2 根据token获取完整用户信息
需求描述
- 客户端发送请求,提交token请求头,后端根据token请求头获取登录用户的详细信息并响应给客户端进行存储
uri
user/getUserInfo
请求方式
GET
请求头
token: ... ...
响应示例
- 成功获取
{"code": 200,"message": "success","data": {"loginUser": {"uid": 1,"username": "zhangsan","userPwd": "","nickName": "张三"}}
}
- 获取失败
{"code": 504,"message": "notLogin","data": null
}
后端代码
- NewsUserController
package com.atguigu.headline.controller;import com.atguigu.headline.common.Result;
import com.atguigu.headline.common.ResultCodeEnum;
import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.NewsUser;
import com.atguigu.headline.service.NewsUserService;
import com.atguigu.headline.service.impl.NewsUserServiceImpl;
import com.atguigu.headline.util.JwtHelper;
import com.atguigu.headline.util.MD5Util;
import com.atguigu.headline.util.WebUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;
import java.util.HashMap;
import java.util.Map;@WebServlet("/user/*")
public class NewsUserController extends BaseController{private NewsUserService newsUserService =new NewsUserServiceImpl();/*** 接收token,根据token查询完整用户信息* @param req* @param resp* @throws ServletException* @throws IOException*/protected void getUserInfo(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String token = req.getHeader("token");Result result =Result.build(null,ResultCodeEnum.NOTLOGIN);if(null!= token){if (!JwtHelper.isExpiration(token)) {Integer uid = JwtHelper.getUserId(token).intValue();NewsUser newsUser =newsUserService.findByUid(uid);newsUser.setUserPwd("");Map<String,Object> data =new HashMap<>();data.put("loginUser",newsUser);result=Result.ok(data);}}WebUtil.writeJson(resp,result);}
}
- NewsUserService
package com.atguigu.headline.service;import com.atguigu.headline.pojo.NewsUser;public interface NewsUserService {/*** 根据用户id查询用户信息* @param uid 要查询的用户id* @return 找到返回NewsUser对象,找不到返回null*/NewsUser findByUid(Integer uid);
}
- NewsUserServiceImpl
package com.atguigu.headline.service.impl;import com.atguigu.headline.dao.NewsUserDao;
import com.atguigu.headline.dao.impl.NewsUserDaoImpl;
import com.atguigu.headline.pojo.NewsUser;
import com.atguigu.headline.service.NewsTypeService;
import com.atguigu.headline.service.NewsUserService;
import com.atguigu.headline.util.MD5Util;public class NewsUserServiceImpl implements NewsUserService {private NewsUserDao newsUserDao =new NewsUserDaoImpl();@Overridepublic NewsUser findByUid(Integer uid) {return newsUserDao.findByUid(uid);}
}
- NewUserDao
package com.atguigu.headline.dao;import com.atguigu.headline.pojo.NewsUser;public interface NewsUserDao {/*** 根据用户id连接数据库查询用户信息* @param uid 要查询的用户id* @return 找到返回NewsUser对象,找不到返回null*/NewsUser findByUid(Integer uid);
}
- NewUserDaoImpl
package com.atguigu.headline.dao.impl;import com.atguigu.headline.dao.BaseDao;
import com.atguigu.headline.dao.NewsUserDao;
import com.atguigu.headline.pojo.NewsUser;
import java.util.List;public class NewsUserDaoImpl extends BaseDao implements NewsUserDao {@Overridepublic NewsUser findByUid(Integer uid) {String sql ="select uid,username,user_pwd userPwd ,nick_name nickName from news_user where uid = ?";List<NewsUser> newsUserList = baseQuery(NewsUser.class, sql, uid);if (null != newsUserList && newsUserList.size()>0){return newsUserList.get(0);}return null;}
}
3.1.3 注册时用户名占用校验
需求说明
- 用户在注册时输入用户名时,立刻将用户名发送给后端,后端根据用户名查询用户名是否可用并做出响应
uri:
user/checkUserName
请求方式:
POST
请求参数
username=zhangsan
响应示例
- 用户名校验通过
{"code":"200","message":"success""data":{}
}
- 用户名占用
{"code":"505","message":"用户名占用""data":{}
}
后端代码
- NewsUserController
package com.atguigu.headline.controller;import com.atguigu.headline.common.Result;
import com.atguigu.headline.common.ResultCodeEnum;
import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.NewsUser;
import com.atguigu.headline.service.NewsUserService;
import com.atguigu.headline.service.impl.NewsUserServiceImpl;
import com.atguigu.headline.util.JwtHelper;
import com.atguigu.headline.util.MD5Util;
import com.atguigu.headline.util.WebUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;
import java.util.HashMap;
import java.util.Map;@WebServlet("/user/*")
public class NewsUserController extends BaseController{private NewsUserService newsUserService =new NewsUserServiceImpl();/*** 注册时校验用户名是否被占用* @param req* @param resp* @throws ServletException* @throws IOException*/protected void checkUserName(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username = req.getParameter("username");NewsUser newsUser = newsUserService.findByUserName(username);Result result=null;if (null == newsUser){result=Result.ok(null);}else{result=Result.build(null,ResultCodeEnum.USERNAME_USED);}WebUtil.writeJson(resp,result);}
}
3.1.4 注册表单提交
需求说明
- 客户端将新用户信息发送给服务端,服务端将新用户存入数据库,存入之前做用户名是否被占用校验,校验通过响应成功提示,否则响应失败提示
uri:
user/regist
请求方式:
POST
请求参数
{"username":"zhangsan","userPwd":"123456","nickName":"张三"
}
响应示例
- 注册成功
{"code":"200","message":"success""data":{}
}
- 用户名占用
{"code":"505","message":"用户名占用""data":{}
}
后端代码
- NewsUserController
package com.atguigu.headline.controller;import com.atguigu.headline.common.Result;
import com.atguigu.headline.common.ResultCodeEnum;
import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.NewsUser;
import com.atguigu.headline.service.NewsUserService;
import com.atguigu.headline.service.impl.NewsUserServiceImpl;
import com.atguigu.headline.util.JwtHelper;
import com.atguigu.headline.util.MD5Util;
import com.atguigu.headline.util.WebUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;@WebServlet("/user/*")
public class NewsUserController extends BaseController{private NewsUserService newsUserService =new NewsUserServiceImpl();/*** 注册功能接口* @param req* @param resp* @throws ServletException* @throws IOException*/protected void regist(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {NewsUser newsUser = WebUtil.readJson(req, NewsUser.class);NewsUser usedUser = newsUserService.findByUserName(newsUser.getUsername());Result result=null;if (null == usedUser){newsUserService.registUser(newsUser);result=Result.ok(null);}else{result=Result.build(null,ResultCodeEnum.USERNAME_USED);}WebUtil.writeJson(resp,result);}
}
- NewsUserService
package com.atguigu.headline.service;import com.atguigu.headline.pojo.NewsUser;public interface NewsUserService {/*** 注册用户信息,注册成功返回大于0的整数,失败返回0* @param newsUser* @return*/int registUser(NewsUser newsUser);
}
- NewsUserServiceImpl
package com.atguigu.headline.service.impl;import com.atguigu.headline.dao.NewsUserDao;
import com.atguigu.headline.dao.impl.NewsUserDaoImpl;
import com.atguigu.headline.pojo.NewsUser;
import com.atguigu.headline.service.NewsTypeService;
import com.atguigu.headline.service.NewsUserService;
import com.atguigu.headline.util.MD5Util;public class NewsUserServiceImpl implements NewsUserService {@Overridepublic int registUser(NewsUser newsUser) {// 密码明文转密文newsUser.setUserPwd(MD5Util.encrypt(newsUser.getUserPwd()));// 存入数据库return newsUserDao.insertNewsUser(newsUser);}
}
- NewUserDao
package com.atguigu.headline.dao;import com.atguigu.headline.pojo.NewsUser;public interface NewsUserDao {/*** 将用户信息存入数据库* @param newsUser * @return*/int insertNewsUser(NewsUser newsUser);
}
- NewUserDaoImpl
package com.atguigu.headline.dao.impl;import com.atguigu.headline.dao.BaseDao;
import com.atguigu.headline.dao.NewsUserDao;
import com.atguigu.headline.pojo.NewsUser;
import java.util.List;public class NewsUserDaoImpl extends BaseDao implements NewsUserDao {@Overridepublic int insertNewsUser(NewsUser newsUser) {String sql ="insert into news_user values(DEFAULT,?,?,?)";return baseUpdate(sql,newsUser.getUsername(),newsUser.getUserPwd(),newsUser.getNickName());}
}
3.2 头条首页功能
3.2.1 查询所有头条分类
需求说明
- 进入新闻首页,查询所有分类并动态展示新闻类别栏位
uri:
portal/findAllTypes
请求方式
GET
请求参数
无
响应示例
{"code":"200","message":"OK""data":[{"tid":"1","tname":"新闻"},{"tid":"2","tname":"体育"},{"tid":"3","tname":"娱乐"},{"tid":"4","tname":"科技"},{"tid":"5","tname":"其他"}]}
后端代码
- PortalController
package com.atguigu.headline.controller;import com.atguigu.headline.common.Result;
import com.atguigu.headline.pojo.NewsType;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;
import com.atguigu.headline.service.NewsHeadlineService;
import com.atguigu.headline.service.NewsTypeService;
import com.atguigu.headline.service.impl.NewsHeadlineServiceImpl;
import com.atguigu.headline.service.impl.NewsTypeServiceImpl;
import com.atguigu.headline.util.WebUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;@WebServlet("/portal/*")
public class PortalController extends BaseController{private NewsHeadlineService headlineService=new NewsHeadlineServiceImpl();private NewsTypeService newsTypeService=new NewsTypeServiceImpl();/*** 查询所有新闻类型* @param req* @param resp* @throws ServletException* @throws IOException*/protected void findAllTypes(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {List<NewsType> newsTypeList =newsTypeService.findAll();WebUtil.writeJson(resp,Result.ok(newsTypeList));}
}
- NewsTypeService
package com.atguigu.headline.service;import com.atguigu.headline.pojo.NewsType;import java.util.List;public interface NewsTypeService {/*** 查询全部新闻类型* @return*/List<NewsType> findAll();
}
- NewsTypeServiceImpl
package com.atguigu.headline.service.impl;import com.atguigu.headline.dao.NewsTypeDao;
import com.atguigu.headline.dao.impl.NewsTypeDaoImpl;
import com.atguigu.headline.pojo.NewsType;
import com.atguigu.headline.service.NewsTypeService;import java.util.List;public class NewsTypeServiceImpl implements NewsTypeService {private NewsTypeDao newsTypeDao =new NewsTypeDaoImpl();@Overridepublic List<NewsType> findAll() {return newsTypeDao.findAll();}
}
- NewUserDao
package com.atguigu.headline.dao;import com.atguigu.headline.pojo.NewsType;import java.util.List;public interface NewsTypeDao {/*** 从数据库中查询全部新闻类型* @return*/List<NewsType> findAll();
}
- NewsTypeDaoImpl
package com.atguigu.headline.dao.impl;import com.atguigu.headline.dao.BaseDao;
import com.atguigu.headline.dao.NewsTypeDao;
import com.atguigu.headline.pojo.NewsType;import java.util.List;public class NewsTypeDaoImpl extends BaseDao implements NewsTypeDao {@Overridepublic List<NewsType> findAll() {String sql ="select tid,tname from news_type";return baseQuery(NewsType.class, sql);}
}
3.2.2 分页带条件查询所有头条
需求说明
- 客户端向服务端发送查询关键字,新闻类别,页码数,页大小
- 服务端根据条件搜索分页信息,返回含页码数,页大小,总页数,总记录数,当前页数据等信息,并根据时间降序,浏览量降序排序
uri:
portal/findNewsPage
请求方式:
POST
请求参数:
{"keyWords":"马斯克", // 搜索标题关键字"type":0, // 新闻类型"pageNum":1, // 页码数"pageSize":"10" // 页大小
}
响应示例:
{"code":"200","message":"success""data":{"pageInfo":{"pageData":[ // 本页的数据{"hid":"1", // 新闻id "title":"尚硅谷宣布 ... ...", // 新闻标题"type":"1", // 新闻所属类别编号"pageViews":"40", // 新闻浏览量"pastHours":"3" , // 发布时间已过小时数"publisher":"1" // 发布用户ID},{"hid":"1", // 新闻id "title":"尚硅谷宣布 ... ...", // 新闻标题"type":"1", // 新闻所属类别编号"pageViews":"40", // 新闻浏览量"pastHours":"3", // 发布时间已过小时数"publisher":"1" // 发布用户ID},{"hid":"1", // 新闻id "title":"尚硅谷宣布 ... ...", // 新闻标题"type":"1", // 新闻所属类别编号"pageViews":"40", // 新闻浏览量"pastHours":"3", // 发布时间已过小时数"publisher":"1" // 发布用户ID}],"pageNum":1, //页码数"pageSize":10, // 页大小"totalPage":20, // 总页数"totalSize":200 // 总记录数}}
}
后端代码
- PortalController
package com.atguigu.headline.controller;import com.atguigu.headline.common.Result;
import com.atguigu.headline.pojo.NewsType;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;
import com.atguigu.headline.service.NewsHeadlineService;
import com.atguigu.headline.service.NewsTypeService;
import com.atguigu.headline.service.impl.NewsHeadlineServiceImpl;
import com.atguigu.headline.service.impl.NewsTypeServiceImpl;
import com.atguigu.headline.util.WebUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;@WebServlet("/portal/*")
public class PortalController extends BaseController{private NewsHeadlineService headlineService=new NewsHeadlineServiceImpl();private NewsTypeService newsTypeService=new NewsTypeServiceImpl();/*** 分页带条件查询新闻* @param req* @param resp* @throws ServletException* @throws IOException*/protected void findNewsPage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {HeadlineQueryVo headLineQueryVo = WebUtil.readJson(req, HeadlineQueryVo.class);// 查询分页五项数据Map<String,Object> pageInfo =headlineService.findPage(headLineQueryVo);// 将分页五项数据放入PageInfoMapMap<String,Object> pageInfoMap=new HashMap<>();pageInfoMap.put("pageInfo",pageInfo);// 响应JSONWebUtil.writeJson(resp, Result.ok(pageInfoMap));}
}
- NewsHeadlineService
package com.atguigu.headline.service;import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;import java.util.List;
import java.util.Map;public interface NewsHeadlineService {/*** 分页查询头条新闻方法* @param headLineQueryVo* @return*/Map<String, Object> findPage(HeadlineQueryVo headLineQueryVo);
}
- NewsHeadlineServiceImpl
package com.atguigu.headline.service.impl;import com.atguigu.headline.dao.NewsHeadLineDao;
import com.atguigu.headline.dao.impl.NewsHeadlineDaoImpl;
import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlinePageVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;
import com.atguigu.headline.service.NewsHeadlineService;import java.util.HashMap;
import java.util.List;
import java.util.Map;public class NewsHeadlineServiceImpl implements NewsHeadlineService {private NewsHeadLineDao newsHeadLineDao =new NewsHeadlineDaoImpl();@Overridepublic Map<String, Object> findPage(HeadlineQueryVo headLineQueryVo) {// 准备一个map,用于装分页的五项数据Map<String,Object> pageInfo =new HashMap<>();// 分页查询本页数据List<HeadlinePageVo> pageData =newsHeadLineDao.findPageList(headLineQueryVo);// 分页查询满足记录的总数据量int totalSize = newsHeadLineDao.findPageCount(headLineQueryVo);// 页大小int pageSize =headLineQueryVo.getPageSize();// 总页码数int totalPage=totalSize%pageSize == 0 ? totalSize/pageSize : totalSize/pageSize+1;// 当前页码数int pageNum= headLineQueryVo.getPageNum();pageInfo.put("pageData",pageData);pageInfo.put("pageNum",pageNum);pageInfo.put("pageSize",pageSize);pageInfo.put("totalPage",totalPage);pageInfo.put("totalSize",totalSize);return pageInfo;}
}
- NewsHeadLineDao
package com.atguigu.headline.dao;import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlinePageVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;import java.util.List;public interface NewsHeadLineDao {/*** 根据查询条件,查询满足条件的记录数* @param headLineQueryVo* @return*/int findPageCount(HeadlineQueryVo headLineQueryVo);/*** 根据查询条件,查询当前页数据* @param headLineQueryVo* @return*/List<HeadlinePageVo> findPageList(HeadlineQueryVo headLineQueryVo);
}
- NewsHeadlineDaoImpl
package com.atguigu.headline.dao.impl;import com.atguigu.headline.dao.BaseDao;
import com.atguigu.headline.dao.NewsHeadLineDao;
import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlinePageVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;import java.util.LinkedList;
import java.util.List;public class NewsHeadlineDaoImpl extends BaseDao implements NewsHeadLineDao{@Overridepublic int findPageCount(HeadlineQueryVo headLineQueryVo) {// 拼接动态 SQL,拼接参数List<Object> args =new LinkedList<>();String sql="select count(1) from news_headline where is_deleted=0 ";StringBuilder sqlBuffer =new StringBuilder(sql) ;String keyWords = headLineQueryVo.getKeyWords();//判断并动态拼接条件if (null != keyWords && keyWords.length()>0){sqlBuffer.append("and title like ? ");args.add("%"+keyWords+"%");}// 判断并动态拼接条件Integer type = headLineQueryVo.getType();if(null != type && type != 0){sqlBuffer.append("and type = ? ");args.add(type);}// 参数转数组Object[] argsArr = args.toArray();System.out.println(sqlBuffer.toString());Long totalSize = baseQueryObject(Long.class, sqlBuffer.toString(), argsArr);// 返回数据return totalSize.intValue();}@Overridepublic List<HeadlinePageVo> findPageList(HeadlineQueryVo headLineQueryVo) {// 拼接动态 SQL,拼接参数List<Object> args =new LinkedList<>();String sql="select hid,title,type,page_views pageViews,TIMESTAMPDIFF(HOUR,create_time,NOW()) pastHours,publisher from news_headline where is_deleted=0 ";StringBuilder sqlBuffer =new StringBuilder(sql) ;String keyWords = headLineQueryVo.getKeyWords();if (null != keyWords && keyWords.length()>0){sqlBuffer.append("and title like ? ");args.add("%"+keyWords+"%");}Integer type = headLineQueryVo.getType();if(null != type && type != 0){sqlBuffer.append("and type = ? ");args.add(type);}sqlBuffer.append("order by pastHours , page_views desc ");sqlBuffer.append("limit ? , ?");args.add((headLineQueryVo.getPageNum()-1)*headLineQueryVo.getPageSize());args.add(headLineQueryVo.getPageSize());// 参数转数组Object[] argsArr = args.toArray();System.out.println(sqlBuffer.toString());List<HeadlinePageVo> pageData = baseQuery(HeadlinePageVo.class, sqlBuffer.toString(), argsArr);return pageData;}
}
3.2.3 查看头条详情
需求说明
- 用户点击"查看全文"时,向服务端发送新闻id
- 后端根据新闻id查询完整新闻文章信息并返回
- 后端要同时让新闻的浏览量+1
uri
portal/showHeadlineDetail
请求方式
POST
请求参数
hid=1
响应示例
{"code":"200","message":"success","data":{"headline":{"hid":"1", // 新闻id "title":"马斯克宣布 ... ...", // 新闻标题"article":"... ..." // 新闻正文"type":"1", // 新闻所属类别编号"typeName":"科技", // 新闻所属类别"pageViews":"40", // 新闻浏览量"pastHours":"3" , // 发布时间已过小时数"publisher":"1" , // 发布用户ID"author":"张三" // 新闻作者}}
}
后端代码
- PortalController
package com.atguigu.headline.controller;import com.atguigu.headline.common.Result;
import com.atguigu.headline.pojo.NewsType;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;
import com.atguigu.headline.service.NewsHeadlineService;
import com.atguigu.headline.service.NewsTypeService;
import com.atguigu.headline.service.impl.NewsHeadlineServiceImpl;
import com.atguigu.headline.service.impl.NewsTypeServiceImpl;
import com.atguigu.headline.util.WebUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;@WebServlet("/portal/*")
public class PortalController extends BaseController{private NewsHeadlineService headlineService=new NewsHeadlineServiceImpl();private NewsTypeService newsTypeService=new NewsTypeServiceImpl();/*** 查询单个新闻详情* @param req* @param resp* @throws ServletException* @throws IOException*/protected void showHeadlineDetail(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 获取要查询的详情新闻idInteger hid =Integer.parseInt(req.getParameter("hid"));// 查询新闻详情voHeadlineDetailVo headlineDetailVo =headlineService.findHeadlineDetail(hid);// 封装data内容Map<String ,Object> data =new HashMap<>();data.put("headline",headlineDetailVo);// 响应JSONWebUtil.writeJson(resp,Result.ok(data));}
}
- NewsHeadlineService
package com.atguigu.headline.service;import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;import java.util.List;
import java.util.Map;public interface NewsHeadlineService {/*** 根据头条id,显示头条详情* @param hid* @return*/HeadlineDetailVo findHeadlineDetail(Integer hid);
}
- NewsHeadlineServiceImpl
package com.atguigu.headline.service.impl;import com.atguigu.headline.dao.NewsHeadLineDao;
import com.atguigu.headline.dao.impl.NewsHeadlineDaoImpl;
import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlinePageVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;
import com.atguigu.headline.service.NewsHeadlineService;import java.util.HashMap;
import java.util.List;
import java.util.Map;public class NewsHeadlineServiceImpl implements NewsHeadlineService {private NewsHeadLineDao newsHeadLineDao =new NewsHeadlineDaoImpl();@Overridepublic HeadlineDetailVo findHeadlineDetail(Integer hid) {// 修改新闻信息浏览量+1newsHeadLineDao.increasePageViews(hid);// 查询新闻详情return newsHeadLineDao.findHeadlineDetail(hid);}
}
- NewsHeadLineDao
package com.atguigu.headline.dao;import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlinePageVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;import java.util.List;public interface NewsHeadLineDao {/*** 多表查询新闻详情* @param hid* @return*/HeadlineDetailVo findHeadlineDetail(Integer hid);int increasePageViews(Integer hid);
}
- NewsHeadlineDaoImpl
package com.atguigu.headline.dao.impl;import com.atguigu.headline.dao.BaseDao;
import com.atguigu.headline.dao.NewsHeadLineDao;
import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlinePageVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;import java.util.LinkedList;
import java.util.List;public class NewsHeadlineDaoImpl extends BaseDao implements NewsHeadLineDao{@Overridepublic HeadlineDetailVo findHeadlineDetail(Integer hid) {String sql ="select hid,title,article,type, tname typeName ,page_views pageViews,TIMESTAMPDIFF(HOUR,create_time,NOW()) pastHours,publisher,nick_name author from news_headline h left join news_type t on h.type = t.tid left join news_user u on h.publisher = u.uid where hid = ?";List<HeadlineDetailVo> headlineDetailVoList = baseQuery(HeadlineDetailVo.class, sql, hid);if(null != headlineDetailVoList && headlineDetailVoList.size()>0)return headlineDetailVoList.get(0);return null;}@Overridepublic int increasePageViews(Integer hid) {String sql ="update news_headline set page_views = page_views +1 where hid =?";return baseUpdate(sql,hid);}
}
3.3 头条发布修改和删除
3.3.1 登录校验
需求说明
- 客户端在进入发布页前、发布新闻前、进入修改页前、修改前、删除新闻前先向服务端发送请求携带token请求头
- 后端接收token请求头后,校验用户登录是否过期并做响应
- 前端根据响应信息提示用户进入登录页还是进入正常业务页面
uri
user/checkLogin
请求方式
GET
请求参数
无
请求头
token: ... ...
响应示例
- 登录未过期
{"code":"200","message":"success","data":{}
}
- 登录已过期
{"code":"504","message":"loginExpired","data":{}
}
后端代码
- NewsUserController
package com.atguigu.headline.controller;import com.atguigu.headline.common.Result;
import com.atguigu.headline.common.ResultCodeEnum;
import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.NewsUser;
import com.atguigu.headline.service.NewsUserService;
import com.atguigu.headline.service.impl.NewsUserServiceImpl;
import com.atguigu.headline.util.JwtHelper;
import com.atguigu.headline.util.MD5Util;
import com.atguigu.headline.util.WebUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;
import java.util.HashMap;
import java.util.Map;@WebServlet("/user/*")
public class NewsUserController extends BaseController{private NewsUserService newsUserService =new NewsUserServiceImpl();/*** 通过token检验用户登录是否过期* @param req* @param resp* @throws ServletException* @throws IOException*/protected void checkLogin(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String token = req.getHeader("token");Result result =Result.build(null,ResultCodeEnum.NOTLOGIN);if(null!= token){if (!JwtHelper.isExpiration(token)) {result=Result.ok(null);}}WebUtil.writeJson(resp,result);}
}
- 登录校验过滤器
package com.atguigu.headline.filters;import com.atguigu.headline.common.Result;
import com.atguigu.headline.common.ResultCodeEnum;
import com.atguigu.headline.util.JwtHelper;
import com.atguigu.headline.util.WebUtil;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;public class LoginFilter implements Filter {@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request =(HttpServletRequest) servletRequest;String token = request.getHeader("token");boolean flag =false;// token不为空并且没过期if (null != token ){boolean expiration = JwtHelper.isExpiration(token);if (!expiration ){flag=true;}}if (flag){filterChain.doFilter(servletRequest,servletResponse);}else{WebUtil.writeJson((HttpServletResponse) servletResponse, Result.build(null, ResultCodeEnum.NOTLOGIN));}}
}
- web.xml中配置登录校验过滤器
<!--登录校验过滤器--><filter><filter-name>loginFilter</filter-name><filter-class>com.atguigu.headline.filters.LoginFilter</filter-class></filter><filter-mapping><filter-name>loginFilter</filter-name><url-pattern>/headline/*</url-pattern></filter-mapping>
3.3.2 提交发布头条
需求说明
- 用户在客户端输入发布的新闻信息完毕后
- 发布前先请求后端的登录校验接口验证登录
- 登录通过则提交新闻信息
- 后端将新闻信息存入数据库
uri
headline/publish
请求方式
POST
请求头
token: ... ...
请求参数
{"title":"尚硅谷宣布 ... ...", // 文章标题"article":"... ...", // 文章内容"type":"1" // 文章类别
}
响应示例
- 发布成功
{"code":"200","message":"success","data":{}
}
- 失去登录状态发布失败
{"code":"504","message":"loginExpired","data":{}
}
后端代码
- NewsHeadlineController
package com.atguigu.headline.controller;import com.atguigu.headline.common.Result;
import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.service.NewsHeadlineService;
import com.atguigu.headline.service.impl.NewsHeadlineServiceImpl;
import com.atguigu.headline.util.JwtHelper;
import com.atguigu.headline.util.WebUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;
import java.util.HashMap;
import java.util.Map;@WebServlet("/headline/*")
public class NewsHeadlineController extends BaseController {private NewsHeadlineService newsHeadlineService =new NewsHeadlineServiceImpl();/*** 发布新闻* @param req* @param resp* @throws ServletException* @throws IOException*/protected void publish(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 读取新闻信息NewsHeadline newsHeadline = WebUtil.readJson(req, NewsHeadline.class);// 通过token获取发布者IDString token = req.getHeader("token");Long userId = JwtHelper.getUserId(token);newsHeadline.setPublisher(userId.intValue());// 将新闻存入数据库newsHeadlineService.addNewsHeadline(newsHeadline);WebUtil.writeJson(resp,Result.ok(null));}
}
- NewsHeadlineService
package com.atguigu.headline.service;import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;import java.util.List;
import java.util.Map;public interface NewsHeadlineService {/*** 新增头条* @param newsHeadline* @return*/int addNewsHeadline(NewsHeadline newsHeadline);
}
- NewsHeadlineServiceImpl
package com.atguigu.headline.service.impl;import com.atguigu.headline.dao.NewsHeadLineDao;
import com.atguigu.headline.dao.impl.NewsHeadlineDaoImpl;
import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlinePageVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;
import com.atguigu.headline.service.NewsHeadlineService;import java.util.HashMap;
import java.util.List;
import java.util.Map;public class NewsHeadlineServiceImpl implements NewsHeadlineService {private NewsHeadLineDao newsHeadLineDao =new NewsHeadlineDaoImpl();public int addNewsHeadline(NewsHeadline newsHeadline) {return newsHeadLineDao.addNewsHeadline(newsHeadline);}
}
- NewsHeadLineDao
package com.atguigu.headline.dao;import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlinePageVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;import java.util.List;public interface NewsHeadLineDao {/*** 头条存入数据库* @param newsHeadline* @return*/int addNewsHeadline(NewsHeadline newsHeadline);
}
- NewsHeadlineDaoImpl
package com.atguigu.headline.dao.impl;import com.atguigu.headline.dao.BaseDao;
import com.atguigu.headline.dao.NewsHeadLineDao;
import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlinePageVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;import java.util.LinkedList;
import java.util.List;public class NewsHeadlineDaoImpl extends BaseDao implements NewsHeadLineDao{@Overridepublic int addNewsHeadline(NewsHeadline newsHeadline) {String sql = "insert into news_headline values(DEFAULT,?,?,?,?,0,NOW(),NOW(),0)";return baseUpdate(sql,newsHeadline.getTitle(),newsHeadline.getArticle(),newsHeadline.getType(),newsHeadline.getPublisher());}
}
3.3.3 修改头条回显
需求说明
- 前端先调用登录校验接口,校验登录是否过期
- 登录校验通过后 ,则根据新闻id查询新闻的完整信息并响应给前端
uri
headline/findHeadlineByHid
请求方式
POST
请求参数
hid=1
响应示例
- 查询成功
{"code":"200","message":"success","data":{"headline":{"hid":"1","title":"马斯克宣布","article":"... ... ","type":"2"}}
}
后端代码
- NewsHeadlineController
package com.atguigu.headline.controller;import com.atguigu.headline.common.Result;
import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.service.NewsHeadlineService;
import com.atguigu.headline.service.impl.NewsHeadlineServiceImpl;
import com.atguigu.headline.util.JwtHelper;
import com.atguigu.headline.util.WebUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;
import java.util.HashMap;
import java.util.Map;@WebServlet("/headline/*")
public class NewsHeadlineController extends BaseController {private NewsHeadlineService newsHeadlineService =new NewsHeadlineServiceImpl();/*** 修改新闻回显* @param req* @param resp* @throws ServletException* @throws IOException*/protected void findHeadlineByHid(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {Integer hid = Integer.parseInt(req.getParameter("hid"));NewsHeadline newsHeadline =newsHeadlineService.findHeadlineByHid(hid);Map<String ,Object> data =new HashMap<>();data.put("headline",newsHeadline);WebUtil.writeJson(resp,Result.ok(data));}
}
- NewsHeadlineService
package com.atguigu.headline.service;import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;import java.util.List;
import java.util.Map;public interface NewsHeadlineService {/*** 根据新闻id查询单个新闻* @param hid* @return*/NewsHeadline findHeadlineByHid(Integer hid);
}
- NewsHeadlineServiceImpl
package com.atguigu.headline.service.impl;import com.atguigu.headline.dao.NewsHeadLineDao;
import com.atguigu.headline.dao.impl.NewsHeadlineDaoImpl;
import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlinePageVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;
import com.atguigu.headline.service.NewsHeadlineService;import java.util.HashMap;
import java.util.List;
import java.util.Map;public class NewsHeadlineServiceImpl implements NewsHeadlineService {private NewsHeadLineDao newsHeadLineDao =new NewsHeadlineDaoImpl();@Overridepublic NewsHeadline findHeadlineByHid(Integer hid) {return newsHeadLineDao.findHeadlineByHid(hid);}
}
- NewsHeadLineDao
package com.atguigu.headline.dao;import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlinePageVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;import java.util.List;public interface NewsHeadLineDao {NewsHeadline findHeadlineByHid(Integer hid);
}
- NewUserDaoImpl
package com.atguigu.headline.dao.impl;import com.atguigu.headline.dao.BaseDao;
import com.atguigu.headline.dao.NewsHeadLineDao;
import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlinePageVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;import java.util.LinkedList;
import java.util.List;public class NewsHeadlineDaoImpl extends BaseDao implements NewsHeadLineDao{@Overridepublic NewsHeadline findHeadlineByHid(Integer hid) {String sql ="select hid,title,article,type,publisher,page_views pageViews from news_headline where hid =?";List<NewsHeadline> newsHeadlineList = baseQuery(NewsHeadline.class, sql, hid);if(null != newsHeadlineList && newsHeadlineList.size()>0)return newsHeadlineList.get(0);return null;}
}
3.3.4 保存修改
需求描述
- 客户端将新闻信息修改后,提交前先请求登录校验接口校验登录状态
- 登录校验通过则提交修改后的新闻信息,后端接收并更新进入数据库
uri
headline/update
请求方式
POST
请求参数
{"hid":"1","title":"尚硅谷宣布 ... ...","article":"... ...","type":"2"
}
响应示例
- 修改成功
{"code":"200","message":"success","data":{}
}
- 修改失败
{"code":"504","message":"loginExpired","data":{}
}
后端代码
- NewsHeadlineController
package com.atguigu.headline.controller;import com.atguigu.headline.common.Result;
import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.service.NewsHeadlineService;
import com.atguigu.headline.service.impl.NewsHeadlineServiceImpl;
import com.atguigu.headline.util.JwtHelper;
import com.atguigu.headline.util.WebUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;
import java.util.HashMap;
import java.util.Map;@WebServlet("/headline/*")
public class NewsHeadlineController extends BaseController {private NewsHeadlineService newsHeadlineService =new NewsHeadlineServiceImpl();/*** 更新新闻信息* @param req* @param resp* @throws ServletException* @throws IOException*/protected void update(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {NewsHeadline newsHeadline = WebUtil.readJson(req, NewsHeadline.class);newsHeadlineService.updateNewsHeadline(newsHeadline);WebUtil.writeJson(resp,Result.ok(null));}
}
- NewsHeadlineService
package com.atguigu.headline.service;import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;import java.util.List;
import java.util.Map;public interface NewsHeadlineService {int updateNewsHeadline(NewsHeadline newsHeadline);
}
- NewsHeadlineServiceImpl
package com.atguigu.headline.service.impl;import com.atguigu.headline.dao.NewsHeadLineDao;
import com.atguigu.headline.dao.impl.NewsHeadlineDaoImpl;
import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlinePageVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;
import com.atguigu.headline.service.NewsHeadlineService;import java.util.HashMap;
import java.util.List;
import java.util.Map;public class NewsHeadlineServiceImpl implements NewsHeadlineService {private NewsHeadLineDao newsHeadLineDao =new NewsHeadlineDaoImpl();@Overridepublic int updateNewsHeadline(NewsHeadline newsHeadline) {return newsHeadLineDao.updateNewsHeadline(newsHeadline);}
}
- NewsHeadLineDao
package com.atguigu.headline.dao;import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlinePageVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;import java.util.List;public interface NewsHeadLineDao {int updateNewsHeadline(NewsHeadline newsHeadline);
}
- NewUserDaoImpl
package com.atguigu.headline.dao.impl;import com.atguigu.headline.dao.BaseDao;
import com.atguigu.headline.dao.NewsHeadLineDao;
import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlinePageVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;import java.util.LinkedList;
import java.util.List;public class NewsHeadlineDaoImpl extends BaseDao implements NewsHeadLineDao{@Overridepublic int updateNewsHeadline(NewsHeadline newsHeadline) {String sql ="update news_headline set title = ?, article= ? , type =? , update_time = NOW() where hid = ? ";return baseUpdate(sql,newsHeadline.getTitle(),newsHeadline.getArticle(),newsHeadline.getType(),newsHeadline.getHid());}
}
3.3.5 删除头条
需求说明
- 将要删除的新闻id发送给服务端
- 服务端校验登录是否过期,未过期则直接删除,过期则响应登录过期信息
uri
headline/removeByHid
请求方式
POST
请求参数
hid=1
响应示例
- 删除成功
{"code":"200","message":"success","data":{}
}
- 删除失败
{"code":"504","message":"loginExpired","data":{}}
后端代码
- NewsHeadlineController
package com.atguigu.headline.controller;import com.atguigu.headline.common.Result;
import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.service.NewsHeadlineService;
import com.atguigu.headline.service.impl.NewsHeadlineServiceImpl;
import com.atguigu.headline.util.JwtHelper;
import com.atguigu.headline.util.WebUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;
import java.util.HashMap;
import java.util.Map;@WebServlet("/headline/*")
public class NewsHeadlineController extends BaseController {private NewsHeadlineService newsHeadlineService =new NewsHeadlineServiceImpl();/*** 删除新闻* @param req* @param resp* @throws ServletException* @throws IOException*/protected void removeByHid(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {Integer hid = Integer.parseInt(req.getParameter("hid"));newsHeadlineService.removeByHid(hid);WebUtil.writeJson(resp,Result.ok(null));}
}
- NewsHeadlineService
package com.atguigu.headline.service;import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;import java.util.List;
import java.util.Map;public interface NewsHeadlineService {int removeByHid(Integer hid);
}
- NewsHeadlineServiceImpl
package com.atguigu.headline.service.impl;import com.atguigu.headline.dao.NewsHeadLineDao;
import com.atguigu.headline.dao.impl.NewsHeadlineDaoImpl;
import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlinePageVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;
import com.atguigu.headline.service.NewsHeadlineService;import java.util.HashMap;
import java.util.List;
import java.util.Map;public class NewsHeadlineServiceImpl implements NewsHeadlineService {private NewsHeadLineDao newsHeadLineDao =new NewsHeadlineDaoImpl();@Overridepublic int removeByHid(Integer hid) {return newsHeadLineDao.removeByHid(hid);}
}
- NewsHeadLineDao
package com.atguigu.headline.dao;import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlinePageVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;import java.util.List;public interface NewsHeadLineDao {int removeByHid(Integer hid);
}
- NewsHeadlineDaoImpl
package com.atguigu.headline.dao.impl;import com.atguigu.headline.dao.BaseDao;
import com.atguigu.headline.dao.NewsHeadLineDao;
import com.atguigu.headline.pojo.NewsHeadline;
import com.atguigu.headline.pojo.vo.HeadlineDetailVo;
import com.atguigu.headline.pojo.vo.HeadlinePageVo;
import com.atguigu.headline.pojo.vo.HeadlineQueryVo;import java.util.LinkedList;
import java.util.List;public class NewsHeadlineDaoImpl extends BaseDao implements NewsHeadLineDao{@Overridepublic int removeByHid(Integer hid) {String sql ="update news_headline set is_deleted =1 , update_time =NOW() where hid = ? ";return baseUpdate(sql,hid);}
相关文章:
[JavaWeb]微头条项目
完整笔记和项目代码: https://pan.baidu.com/s/1PZBO0mfpwDPic4Ezsk8orA?pwdwwp5 提取码: wwp5 JavaWeb-微头条项目开发 1 项目简介 1.1 业务介绍 微头条新闻发布和浏览平台,主要包含业务如下 用户功能 注册功能登录功能 头条新闻 新闻的分页浏览通过标题关键字搜…...
Linux(CentOS)安装达梦数据库 dm8
CentOS版本:CentOS 7,查看操作系统版本信息,请查阅 查看Linux内核版本信息 达梦数据库版本:dm8 一、获取 dm8 安装文件 1、下载安装文件 打开达梦官网:https://www.dameng.com/ 下载的文件 解压后的文件 2、上传安…...
【专题】中国企业出海洞察报告暨解码全球制胜之道报告汇总PDF洞察(附原数据表)
原文链接:https://tecdat.cn/?p38314 在当今全球化的浪潮中,中国企业的出海行动正以前所未有的规模和速度展开,成为全球经济舞台上的重要力量。本报告旨在对 2024 年中国企业出海情况进行深度洞察,涵盖多个领域和视角。 从对外投…...
[ 跨域问题 ] 前后端以及服务端 解决跨域的各种方法
这篇文章主要介绍了跨域问题,包括其定义、产生原因及各种解决方法。原因是浏览器安全策略限制,方法有 JSONP、CORS、Domain、 postMessage、Nginx配置、.NetCore配置。 前言 什么是跨域问题? 在Web应用中,当一个网页的脚本试图去请求另一个域…...
网络安全之信息收集-实战-2
请注意,本文仅供合法和授权的渗透测试使用,任何未经授权的活动都是违法的。 目录 7、网络空间引擎搜索 8、github源码泄露 9、端口信息 10、框架指纹识别 11、WAF识别 12、后台查找 7、网络空间引擎搜索 FOFA:https://fofa.info/ 360 …...
利用飞书多维表格自动发布版本
文章目录 背景尝试1,轮询尝试2,长连接 背景 博主所在的部门比较奇特,每个车型每周都需要发版,所以实际上一周会发布好几个版本。经过之前使用流水线自动发版改造之后,发版的成本已经大大降低了,具体参考&a…...
深入内核讲明白Android Binder【一】
深入内核讲明白Android Binder【一】 前言一、Android Binder应用编写概述二、基于C语言编写Android Binder跨进程通信Demo0. Demo简介1. 服务的管理者server_manager.c2. Binder服务端代码实现 test_service.c2.1 实现思路2.2 完整实现代码 3. Binder客户端代码实现 test_clie…...
Photoshop(PS)——人像磨皮
1.新建一个文件,背景为白色,将图片素材放入文件中 2.利用CtrlJ 复制两个图层出来,选择第一个拷贝图层,选择滤镜---杂色---蒙尘与划痕 3.调整一下数值,大概能够模糊痘印痘坑,点击确定。 4.然后选择拷贝2图层…...
如何用Excel批量提取文件夹内所有文件名?两种简单方法推荐
在日常办公中,我们有时需要将文件夹中的所有文件名整理在Excel表格中,方便管理和查阅。手动复制文件名既费时又易出错,因此本文将介绍两种利用Excel自动提取文件夹中所有文件名的方法,帮助你快速整理文件信息。 方法一࿱…...
YOLOv8改进,YOLOv8通过RFAConv卷积创新空间注意力和标准卷积,包括RFCAConv, RFCBAMConv,二次创新C2f结构,助力涨点
摘要 空间注意力已广泛应用于提升卷积神经网络(CNN)的性能,但它存在一定的局限性。作者提出了一个新的视角,认为空间注意力机制本质上解决了卷积核参数共享的问题。然而,空间注意力生成的注意力图信息对于大尺寸卷积核来说是不足够的。因此,提出了一种新型的注意力机制—…...
【实验11】卷积神经网络(2)-基于LeNet实现手写体数字识别
👉🏼目录👈🏼 🍒1. 数据 1.1 准备数据 1.2 数据预处理 🍒2. 模型构建 2.1 模型测试 2.2 测试网络运算速度 2.3 输出模型参数量 2.4 输出模型计算量 🍒3. 模型训练 🍒4.模…...
chatgpt训练需要什么样的gpu硬件
训练像ChatGPT这样的大型语言模型对GPU硬件提出了极高的要求,因为这类模型的训练过程涉及大量的计算和数据处理。以下是训练ChatGPT所需的GPU硬件的关键要素: ### 1. **高性能计算能力** - **Tensor Cores**: 现代深度学习训练依赖于Tensor Cores&#…...
Kubernetes常用命令
Kubernetes常用命令 一、集群管理 kubectl cluster-info:显示集群信息,包括控制平面地址和服务的 URL。 kubectl get nodes:查看集群中的节点列表,包括节点状态、IP 地址等信息。 kubectl describe node <node-name>&…...
Flutter:key的作用原理(LocalKey ,GlobalKey)
第一段代码实现的内容:创建了3个块,随机3个颜色,每次点击按钮时,把第一个块删除 import dart:math; import package:flutter/material.dart; import package:flutter_one/demo.dart;void main() {runApp(const App()); }class App…...
R语言基础入门详解
文章目录 R语言基础入门详解一、引言二、R语言环境搭建1、安装R和RStudio1.1、步骤1.2、获取工作目录 三、R语言基础2、语法基础2.1、赋值操作2.2、注释 3、数据类型与结构3.1、向量3.2、矩阵 4、基本操作4.1、数据读取4.2、数据可视化 四、R语言使用示例4.1、统计分析示例4.2、…...
django启动项目报错解决办法
在启动此项目报错: 类似于: django.core.exceptions.ImproperlyConfigured: Requested setting EMOJI_IMG_TAG, but settings are not c启动方式选择django方式启动,以普通python方式启动会报错 2. 这句话提供了对遇到的错误的一个重要线索…...
详细描述一下Elasticsearch搜索的过程?
大家好,我是锋哥。今天分享关于【详细描述一下Elasticsearch搜索的过程?】面试题。希望对大家有帮助; 详细描述一下Elasticsearch搜索的过程? Elasticsearch 的搜索过程是其核心功能之一,允许用户对存储在 Elasticsea…...
Spring、SpringMVC、SpringBoot、Mybatis小结
Spring Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架) Spring框架的核心特性包括依赖注入(Dependency Injection ,DI)、面向切面编程(Aspe…...
.NET 9 运行时中的新增功能
本文介绍了适用于 .NET 9 的 .NET 运行时中的新功能和性能改进。 文章目录 一、支持修剪的功能开关的属性模型二、UnsafeAccessorAttribute 支持泛型参数三、垃圾回收四、控制流实施技术.NET 安装搜索行为性能改进循环优化感应变量加宽Arm64 上的索引后寻址强度降低循环计数器可…...
Linux下安装mysql8.0版本
先确定我的下载安装的目录,安装文件是下载在 /opt/install 目录下面 (安装地址不同的话注意修改地址) 1.在线下载 wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.20-linux-glibc2.12-x86_64.tar.xz2.解压 tar -xvf mysql-8.0.20-linux-glibc2.12-x86_64.t…...
kvm-dmesg:从宿主机窥探虚拟机内核dmesg日志
在虚拟化环境中,实时获取虚拟机内核日志对于系统管理员和开发者来说至关重要。传统的 dmesg 工具可以方便地查看本地系统的内核日志,但在KVM(基于内核的虚拟机)环境下,获取虚拟机内部的内核日志则复杂得多。为了简化这…...
植物明星大乱斗15
能帮到你的话,就给个赞吧 😘 文章目录 player.hplayer.cppparticle.hparticle.cpp player.h #pragma once #include <graphics.h> #include "vector2.h" #include "animation.h" #include "playerID.h" #include &…...
go-zero(三) 数据库操作
go-zero 数据库操作 在本篇文章中,我们将实现一个用户注册和登录的服务。我们将为此构建一个简单而高效的 API,包括请求参数和响应参数的定义。 一、Mysql连接 1. 创建数据库和表 在 MySQL 中创建名为 test_zero的数据库,并创建user 表 …...
SQL面试题——间隔连续问题
间隔连续问题 某游戏公司记录的用户每日登录数据如下 +----+----------+ | id| date| +----+----------+ |1001|2021-12-12| |1001|2021-12-13| |1001|2021-12-14| |1001|2021-12-16| |1001|2021-12-19| |1001|2021-12-20| |1002|2021-12-12| |1002|2021-12-16| |1002|…...
vim配置 --> 在创建的普通用户下
在目录/etc/ 下面,有个名为vimrc 的文件,这是系统中公共的vim配置文件对所有用户都有效 我们现在创建一个普通用户 dm 创建好以后,我们退出重新链接 再切换到普通用户下 再输入密码(是不显示的,输入完后,…...
(计算机毕设)基于SpringBoot+Vue的房屋租赁系统的设计与实现
博主可接毕设设计!!! 各种毕业设计源码只要是你有的题目我这里都有源码 摘 要 社会的发展和科学技术的进步,互联网技术越来越受欢迎。网络计算机的生活方式逐渐受到广大人民群众的喜爱,也逐渐进入了每个用户的使用。互…...
【含开题报告+文档+PPT+源码】基于SpringBoot的医院药房管理系统
开题报告 在科技迅速发展的今天,各行各业都在积极寻求与现代技术的融合,以提升自身的运营效率和竞争力。医疗行业作为关乎国计民生的关键领域,其信息化建设的步伐尤为迅速。医院药房作为医疗体系中的核心环节,其管理效率和服务质…...
基于SpringBoot的“数码论坛系统设计与实现”的设计与实现(源码+数据库+文档+PPT)
基于SpringBoot的“数码论坛系统设计与实现”的设计与实现(源码数据库文档PPT) 开发语言:Java 数据库:MySQL 技术:SpringBoot 工具:IDEA/Ecilpse、Navicat、Maven 系统展示 系统总体结构图 系统首页界面图 数码板…...
Linux-第2集-打包压缩 zip、tar WindowsLinux互传
欢迎来到Linux第2集,这一集我会非常详细的说明如何在Linux上进行打包压缩操作,以及解压解包 还有最最重要的压缩包的网络传输 毕竟打包压缩不是目的,把文件最终传到指定位置才是目的 由于打包压缩分开讲没有意义,并且它们俩本来…...
项目进度计划表:详细的甘特图的制作步骤
甘特图(Gantt chart),又称为横道图、条状图(Bar chart),是一种用于管理时间和任务活动的工具。 甘特图由亨利劳伦斯甘特(Henry Laurence Gantt)发明,是一种通过条状图来…...
如何在阿里云云服务器上搭建网站/百度一下网页版浏览器
【摘要】 SQL 虽然是针对记录的集合进行运算, 但在记录的多次利用以及有序运算却经常要重复计算,效率不佳。而集算器 SPL 则要直观许多,可以按自然思维习惯写出运算。这里对 SQL 和集算器 SPL 在记录的利用及有序运算方面进行了对比,…...
政府门户网站集约化建设会/百度网盘网页
爱一个人难道有错吗? 我不知道。 本以为自己可以忘记 本以为自己可以勇敢的面对 本以为我可以不在乎对你的感受 本以为我可以战胜自己 但是 渐渐的 我发现 原来我不能! 我真的不能做到!~ 是我太软弱,还是我太脆弱? 不&…...
长沙便宜做网站/2023年10月疫情还会严重吗
在百度与机器之心联合举办的【三小时AI开发进阶】系列公开课中,百度资深研发工程师倾囊相授,首节课关注视觉模型开发难点:解析小目标检测的技术原理并带来现场实战演示,让我们一文快速回顾本节课的核心干货! 【课程主…...
个人网站在那建设/短视频剪辑培训班速成
Thread.currentThread():static 当前线程 方法: setName() getName() isAlive() 优先级: 概率 非绝对的优先级 t1.setPriority(Thread.MAX_PRIORITY); t1.getPriority(); * MAX_PRIORITY 10 * NORM_PRIORITY 5 * MIN_PRIORITY 1 /*** 描述:优先级 概率 非绝对的优先级* MA…...
网站特色/西安网站关键词排名
01PDF下载识别下方二维码,回复“网易画像”,即可下载。02PPT预览...
福田做商城网站建设哪家服务周到/推广找客户平台
本文与前文是有关联的,之前的两篇文章客官可以抬腿出门右转 导读,ELK 之前端,ELK 之分布式发#前端和消息队列搞定之后,我们需要安装数据采集工具filebeats和数据过滤机运输工具Logstash,一般情况我们都使用filebeats 用…...