[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…...
AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...
算法打卡第18天
从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 示例 1: 输入:inorder [9,3,15,20,7…...
Java并发编程实战 Day 11:并发设计模式
【Java并发编程实战 Day 11】并发设计模式 开篇 这是"Java并发编程实战"系列的第11天,今天我们聚焦于并发设计模式。并发设计模式是解决多线程环境下常见问题的经典解决方案,它们不仅提供了优雅的设计思路,还能显著提升系统的性能…...
