【JavaWeb】头条新闻项目实现 基本增删改查 分页查询 登录注册校验 业务功能实现 第二期

news2024/11/15 16:25:33

文章目录

  • 一、为什么使用token口令
  • 二、登录注册功能
    • 2.1 登录表单提交
      • 后端代码:
    • 2.2 根据token获取完整用户信息
      • 代码实现:
    • 2.3 注册时用户名占用校验
      • 代码实现:
    • 2.4 注册表单提交
      • 代码实现:
  • 三、头条首页功能
    • 3.1 查询所有头条分类
    • 3.2 分页带条件查询所有头条
      • 代码实现:
    • 3.3 查看头条详情
      • 代码实现:
  • 四、头条发布修改和删除
    • 4.1 登录校验
      • 代码实现:
    • 4.2 提交发布头条(新增
      • 代码实现:
    • 4.3 修改头条回显
    • 4.4 保存修改
      • 代码实现:
    • 4.5 删除头条
  • 总结
    • 2.1 登录表单提交


一、为什么使用token口令

为什么使用 token 口令 而不使用 cookie和session

  • cookie和session 对于高并发项目不合适
    1
  • token:
    1

二、登录注册功能

gif

2.1 登录表单提交

需求描述:
输入 用户名 密码 验证登录,根据输入的用户名 和 密码 提示不同的响应信息

URI:
user/login

请求方式:
POST

请求参数:
{ "username":"dougwake", //用户名 "userPwd":"123456" //明文密码 }
1
响应示例:

  • 登录成功
    1
  • 用户名输入有误:
    在这里插入图片描述
  • 密码错误:
    在这里插入图片描述

后端代码:

2.1.1 Controller 层

package com.doug.headline.controller;

import com.doug.headline.common.Result;
import com.doug.headline.common.ResultCodeEnum;
import com.doug.headline.dao.NewsUserDao;
import com.doug.headline.pojo.NewsUser;
import com.doug.headline.service.NewsUserService;
import com.doug.headline.service.impl.NewsUserServiceImpl;
import com.doug.headline.util.JwtHelper;
import com.doug.headline.util.MD5Util;
import com.doug.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 {
        // 接收前端传递过来的JSON串 (即请求参数)
        NewsUser newsUser = WebUtil.readJson(req, NewsUser.class);
        // 调用业务层代码 查找用户名是否存在
        NewsUser loginNewsUser = newsUserService.findByUsername(newsUser.getUsername());
        Result result = null;
        if (null != loginNewsUser) {
            // 用户名存在 -> 进一步判断 密码是否正确(先将明文密码转成MD5 再与已存密码对比)
            if (loginNewsUser.getUserPwd().equals(MD5Util.encrypt(newsUser.getUserPwd()))) {
                // 响应结果 是键值对形式 所以用map
                Map<String, Object> data = new HashMap<>();
                // 创建token 
                String token = JwtHelper.createToken(loginNewsUser.getUid().longValue());

                data.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);
    }
}

2.1.2 service

public interface NewsUserService {
    /**
     * 根据用户名,获得查询的用户信息
     * @param username 要查找的用户名
     * @return 如果找到返回NewsUser对象,找不到返回null
     */
    NewsUser findByUsername(String username);
}
public class NewsUserServiceImpl implements NewsUserService {
    private NewsUserDao newsUserDao = new NewsUserDaoImpl();
    @Override
    public NewsUser findByUsername(String username) {
        return newsUserDao.findByUsername(username);
    }
}

2.1.3 dao

public interface NewsUserDao {
    /**
     * 根据用户名,获得查询的用户信息
     * @param username 要查找的用户名
     * @return 如果找到返回NewsUser对象,找不到返回null
     */
    NewsUser findByUsername(String username);
}
public class NewsUserDaoImpl  extends BaseDao implements NewsUserDao {
    @Override
    public NewsUser findByUsername(String username) {
        String sql = """
                select
                    uid,username,user_pwd userPwd,nick_name nickName
                from
                    news_user
                where
                    username = ?;
                """;
        List<NewsUser> newsUserList = baseQuery(NewsUser.class, sql, username);
        // 如果找到,返回集合中的第一个数据(其实就一个)
        if(null != newsUserList && newsUserList.size() > 0){
            return newsUserList.get(0);
        }
        return null;
    }
}

2.2 根据token获取完整用户信息

需求描述:
客户端发送请求,提交token请求头,后端根据token请求头获取登录用户的详细信息并响应给客户端进行存储

URI:
user/getUserInfo

请求方式:
GET

请求头
token: ...

响应示例

  • 成功获取
    1
  • 获取失败
    504

代码实现:

2.2.1 Controller

    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);
        // token 存在
        if(null != token){
            // token 没有到期
            if(!JwtHelper.isExpiration(token)){
                Integer uid = JwtHelper.getUserId(token).intValue();
                // 通过token的uid 找对象
                NewsUser newsUser = newsUserService.findByUid(uid);
                newsUser.setUserPwd("");
                HashMap<String, Object> data = new HashMap<>();
                data.put("loginUser",newsUser);
                result = Result.ok(data);
            }
        }
        WebUtil.writeJson(resp,result);
    }

2.2.2 Service

    /**
     * 根据用户id查询用户信息
     * @param uid 要查询的用户id
     * @return 找到返回NewsUser对象,找不到返回null
     */
    NewsUser findByUid(Integer uid);
    @Override
    public NewsUser findByUid(Integer uid) {
        return newsUserDao.finByUid(uid);
    }

2.2.3 Dao

    NewsUser finByUid(Integer uid);
    @Override
    public NewsUser finByUid(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);
        // 如果找到,返回集合中的第一个数据(其实就一个)
        return null != newsUserList && newsUserList.size() > 0 ? newsUserList.get(0):null;
    }

2.3 注册时用户名占用校验

用户在注册时输入用户名时,立刻将用户名发送给后端,后端根据用户名查询用户名是否可用并做出响应

URI
user/checkUserName

请求方式: POST

请求参数: username=DougWake

响应示例:

  • 用户名校验通过
    2
  • 用户名被占用
    2

代码实现:

    /**
     * 注册时校验用户名是否占用
     * @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);
    }

2.4 注册表单提交

客户端将新用户信息发送给服务端,服务端将新用户存入数据库,存入之前做用户名是否被占用校验,校验通过响应成功提示,否则响应失败提示

URI : user/regist

请求方式: POST

请求参数 :

{
   "username":"GavinGroves",
   "userPwd":"0123456",
   "nickName":"加文"
}

响应示例:

  • 注册成功:
    1
  • 用户名占用:(第二次注册)
    2

代码实现:

2.4.1 Controller

    /**
     * 用户注册
     * @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){
            result = Result.build(null,ResultCodeEnum.USERNAME_USED);
        }else{
            newsUserService.registUser(newsUser);
            result = Result.ok(null);
        }
        WebUtil.writeJson(resp,result);
    }

2.4.2 Service

    /**
     * 注册用户信息,注册成功返回大于0的整数,失败返回0
     * @param newsUser 要添加的新对象
     * @return
     */
    int registUser(NewsUser newsUser);
    @Override
    public int registUser(NewsUser newsUser) {
        // 密码明文转密文
        newsUser.setUserPwd(MD5Util.encrypt(newsUser.getUserPwd()));
        return newsUserDao.insertNewsUser(newsUser);
    }

2.4.3 Dao

    /**
     * 将用户信息存入数据库
     * @param newsUser 插入新的用户对象
     * @return
     */
    int insertNewsUser(NewsUser newsUser);
    public int insertNewsUser(NewsUser newsUser) {
        String sql = "insert into news_user values(DEFAULT,?,?,?)";
        return baseUpdate(sql, newsUser.getUsername(), newsUser.getUserPwd(), newsUser.getNickName());
    }

result

三、头条首页功能

2

3.1 查询所有头条分类

进入新闻首页,查询所有分类并动态展示新闻类别栏位

URI: portal/findAllTypes
请求方式: GET

  • 响应示例:
{
    "code": 200,
    "message": "success",
    "data": [
        {
            "tid": 1,
            "tname": "新闻"
        },
        {
            "tid": 2,
            "tname": "体育"
        },
        {
            "tid": 3,
            "tname": "娱乐"
        },
        {
            "tid": 4,
            "tname": "科技"
        },
        {
            "tid": 5,
            "tname": "其他"
        }
    ]
}
  • Controller
package com.doug.headline.controller;

import com.doug.headline.common.Result;
import com.doug.headline.pojo.NewsType;
import com.doug.headline.service.NewsTypeService;
import com.doug.headline.service.impl.NewsTypeServiceImpl;
import com.doug.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.List;

/**
 * @Author: Gavin
 * @Date: 2024-02-02 17:10
 * @Description: 门户 控制器 即 当用户没有登录时候 所看到的页面(首页)
 */
@WebServlet("/portal/*")
public class PortalController extends BaseController {
    private NewsTypeService typeService = new NewsTypeServiceImpl();

    /**
     * 查询所有头条类型 业务接口实现
     *
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    protected void findAllTypes(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        List<NewsType> newsTypeList = typeService.findAllTypes();
        WebUtil.writeJson(resp,Result.ok(newsTypeList));
    }
}
  • service
public interface NewsTypeService {
    /**
     * 查询全部新闻类型
     * @return 新闻类型数据
     */
    List<NewsType> findAllTypes();
}
public class NewsTypeServiceImpl implements NewsTypeService {
    private NewsTypeDao typeDao= new NewsTypeDaoImpl();
    @Override
    public List<NewsType> findAllTypes() {
        return typeDao.findAllTypes();
    }
}
  • dao
public interface NewsTypeDao {
    /**
     * 查询全部新闻类型
     * @return 新闻类型数据
     */
    List<NewsType> findAllTypes();
}

public class NewsTypeDaoImpl extends BaseDao implements NewsTypeDao {
    @Override
    public List<NewsType> findAllTypes() {
        String sql = "select tid,tname from news_type";
        return baseQuery(NewsType.class,sql);
    }
}

3.2 分页带条件查询所有头条

  • 客户端向服务端发送查询关键字,新闻类别,页码数,页大小
  • 服务端根据条件搜索分页信息,返回含页码数,页大小,总页数,总记录数,当前页数据等信息,并根据时间降序,浏览量降序排序

uri: portal/findNewsPage

请求方式:POST

  • 请求参数:
{
    "keyWords":"马斯克", // 搜索标题关键字
    "type":0,           // 新闻类型
    "pageNum":1,        // 页码数(当前页码)
    "pageSize":"10"     // 页大小(一页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 // 总记录数
		}
	}
}

detial

代码实现:

3.2.1 controller

@WebServlet("/portal/*")
public class PortalController extends BaseController {
    private NewsTypeService typeService = new NewsTypeServiceImpl();
    private NewsHeadlineService headlineService = new NewsHeadlineServiceImpl();

    /**
     * 分页带条件查询新闻
     * @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);
        //将分页五项数据放入
        Map<String, Object> pageInfoMap = new HashMap<>();
        pageInfoMap.put("pageInfo",pageInfo);
        WebUtil.writeJson(resp,Result.ok(pageInfoMap));
    }

3.2.2 service

public interface NewsHeadlineService {
    /**
     * 分页查询头条新闻方法
     * @param headlineQueryVo
     * @return
     */
    Map<String, Object> findPage(HeadlineQueryVo headlineQueryVo);
}

public class NewsHeadlineServiceImpl implements NewsHeadlineService {
    private NewsHeadLineDao headLineDao = new NewsHeadlineDaoImpl();

    @Override
    public Map<String, Object> findPage(HeadlineQueryVo headlineQueryVo) {
        // 准备一个map,用于装分页的五项数据
        Map<String, Object> pageInfo = new HashMap<>();
        // 分页查询本页数据新闻
        List<HeadlinePageVo> pageData = headLineDao.findPageList(headlineQueryVo);
        // 当前 页码数
        int pageNum = headlineQueryVo.getPageNum();
        // 页大小
        int pageSize = headlineQueryVo.getPageSize();
        // 总记录数
        int totalSize = headLineDao.findPageCount(headlineQueryVo);
        // 总页数(多出一条数据的情况 +1页上去
        int totalPage = totalSize % pageSize == 0 ? totalSize / pageSize : totalSize / pageSize + 1;

        pageInfo.put("pageData",pageData);
        pageInfo.put("pageNum",pageNum);
        pageInfo.put("pageSize",pageSize);
        pageInfo.put("totalPage",totalPage);
        pageInfo.put("totalSize",totalSize);

        return pageInfo;
    }
}

3.2.3 dao

public interface NewsHeadLineDao {
    /**
     * 根据查询条件,查询当前页数据
     * @param headlineQueryVo
     * @return
     */
    List<HeadlinePageVo> findPageList(HeadlineQueryVo headlineQueryVo);

    /**
     * 根据查询条件,查询满足条件的记录数
     * @param headlineQueryVo
     * @return
     */
    int findPageCount(HeadlineQueryVo headlineQueryVo);

}
package com.doug.headline.dao.impl;

import com.doug.headline.dao.BaseDao;
import com.doug.headline.dao.NewsHeadLineDao;
import com.doug.headline.pojo.vo.HeadlinePageVo;
import com.doug.headline.pojo.vo.HeadlineQueryVo;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class NewsHeadlineDaoImpl extends BaseDao implements NewsHeadLineDao {
    @Override
    public List<HeadlinePageVo> findPageList(HeadlineQueryVo headlineQueryVo) {
        List params = new ArrayList();
        String sql = """
                select
                    hid,
                    title,
                    type,
                    page_views pageViews,
                    TIMESTAMPDIFF(HOUR,create_time,now()) pastHours,
                    publisher
                from
                    news_headline
                where
                    is_deleted = 0
                """;

        if(headlineQueryVo.getType() != 0){
            sql = sql.concat(" and type = ? ");
            params.add(headlineQueryVo.getType());
        }

        if(headlineQueryVo.getKeyWords() != null && !headlineQueryVo.getKeyWords().equals("")){
            sql = sql.concat(" and title like ? ");
            params.add("%"+headlineQueryVo.getKeyWords()+"%");
        }

        // 按时间升序 浏览量降序
        sql = sql.concat(" order by pastHours ASC , page_views DESC ");
        // 分页显示
        sql = sql.concat(" limit ?,? ");
        params.add((headlineQueryVo.getPageNum()-1)*headlineQueryVo.getPageSize());
        params.add(headlineQueryVo.getPageSize());

        return baseQuery(HeadlinePageVo.class,sql,params.toArray());
    }

    @Override
    public int findPageCount(HeadlineQueryVo headlineQueryVo) {
        //  拼接动态 SQL,拼接参数
        List 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();
    }
}

3.3 查看头条详情

1

  • 用户点击"查看全文"时,向服务端发送新闻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":"张三"                 // 新闻作者
        }
    }
}

代码实现:

3.3.1 controller

    /**
     * 查询单个新闻详情
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    protected void showHeadlineDetail(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取要查询的详情新闻id
        Integer hid = Integer.valueOf(req.getParameter("hid"));
        // 封装data内容
        HashMap<String, Object> headlineInfo = new HashMap<>();
        // 查询新闻详情的vo
        HeadlineDetailVo headlineDetailVo = headlineService.findHeadlineByHid(hid);

        Result result = null;
        if(null != headlineDetailVo){
            headlineInfo.put("headline",headlineDetailVo);
            result = Result.ok(headlineInfo);
        }
        WebUtil.writeJson(resp,result);
    }

3.3.2 service

    /**
     * 根据hid 查看单个新闻详情
     * @param hid
     * @return
     */
    HeadlineDetailVo findHeadlineByHid(Integer hid);
    @Override
    public HeadlineDetailVo findHeadlineByHid(Integer hid) {
        // 修改新闻信息浏览量+1
        headLineDao.increasePageViews(hid);
        // 查询新闻详情
        return headLineDao.findHeadlineInfoByHid(hid);
    }

3.3.3 dao

    /**
     * 根据 hid 查看详细新闻
     * @param hid 新闻对应ID
     * @return
     */
    HeadlineDetailVo findHeadlineInfoByHid(Integer hid);

    /**
     * 新闻浏览量+1
     * @param hid
     * @return
     */
    int increasePageViews(Integer hid);
    @Override
    public HeadlineDetailVo findHeadlineInfoByHid(Integer hid) {
        String sql = """
                select
                    h.hid,
                    h.title,
                    h.article,
                    h.type,
                    h.page_views as pageViews,
                    TIMESTAMPDIFF(HOUR,create_time,now()) pastHours,
                    h.publisher,
                    t.tname as typeName,
                    u.nick_name as 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
                    h.hid = ?
                                                """;

        List<HeadlineDetailVo> headlineDetailVoList = baseQuery(HeadlineDetailVo.class, sql, hid);
        if (null != headlineDetailVoList && headlineDetailVoList.size() > 0) {
            return headlineDetailVoList.get(0);
        }
        return null;
    }

    @Override
    public int increasePageViews(Integer hid) {
        String sql = "update news_headline set page_views = page_views +1 where hid = ?";
        return baseUpdate(sql, hid);
    }

四、头条发布修改和删除

4.1 登录校验

  • 客户端在进入发布页前、发布新闻前、进入修改页前、修改前、删除新闻前先向服务端发送请求携带token请求头
  • 后端接收token请求头后,校验用户登录是否过期并做响应
  • 前端根据响应信息提示用户进入登录页还是进入正常业务页面

URI : user/checkLogin
请求 : GET
请求头: token: … …

  • 响应:
    • 登录未过期
{
    "code":"200",
    "message":"success",
    "data":{}
}
    • 登录已过期
{
    "code":"504",
    "message":"loginExpired",
    "data":{}
}

代码实现:

4.1.1 controller

    /**
     * 前端自行校验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);
        //token 不等于空 且 没有过期
        if(null != token){
            if(!JwtHelper.isExpiration(token)){
                result = Result.ok(null);
            }
        }
        WebUtil.writeJson(resp,result);
    }

4.1.2 登录过滤器

/**
 * @Author: Gavin
 * @Date: 2024-02-07 21:58
 * @Description: 过滤器自动校验请求是否过期(过滤所有/headline/*下的方法
 */
@WebFilter("/headline/*")
public class LoginFilter implements Filter {

    @Override
    public 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;
        //    }
        //}

        boolean flag = null != token && (!JwtHelper.isExpiration(token));

        if(flag){
            //放行 请求响应
            filterChain.doFilter(servletRequest,servletResponse);
        }else{
            WebUtil.writeJson((HttpServletResponse) servletResponse, Result.build(null, ResultCodeEnum.NOTLOGIN));
        }
    }
}

4.1.3 web.xml中配置登录校验过滤器

    <!--登录校验过滤器-->
    <filter>
        <filter-name>loginFilter</filter-name>
        <filter-class>com.doug.headline.filters.LoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>loginFilter</filter-name>
        <url-pattern>/headline/*</url-pattern>
    </filter-mapping>

4.2 提交发布头条(新增

1

  • 用户在客户端输入发布的新闻信息完毕后
  • 发布前先请求后端的登录校验接口验证登录
  • 登录通过则提交新闻信息
  • 后端将新闻信息存入数据库

URI : headline/publish
请求方式 : POST
请求头 : token: … …

  • 请求参数:
{
    "title":"道格维克 ... ...",   // 文章标题
    "article":"... ...",          // 文章内容
    "type":"1"                    // 文章类别
}
  • 响应示例:
    • 响应发布
{
    "code":"200",
    "message":"success",
    "data":{}
}
    • 失去登录状态发布失败
{
    "code":"504",
    "message":"loginExpired",
    "data":{}
}

代码实现:

4.2.1 controller

package com.doug.headline.controller;

import com.doug.headline.common.Result;
import com.doug.headline.pojo.NewsHeadline;
import com.doug.headline.service.NewsHeadlineService;
import com.doug.headline.service.impl.NewsHeadlineServiceImpl;
import com.doug.headline.util.JwtHelper;
import com.doug.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;

@WebServlet("/headline/*")
public class NewsHeadlineController extends BaseController {
    private NewsHeadlineService headlineService = 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获取发布者ID
        String token = req.getHeader("token");
        Long userId = JwtHelper.getUserId(token);
        newsHeadline.setPublisher(userId.intValue());
        // 将新闻存入数据库
        headlineService.addNewsHeadline(newsHeadline);
        WebUtil.writeJson(resp, Result.ok(null));
    }
}

4.2.2 seriver

    /**
     * 新增头条新闻
     * @param newsHeadline
     * @return
     */
    int addNewsHeadline(NewsHeadline newsHeadline);
    /**
     * 发布新闻
     *
     * @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获取发布者ID
        String token = req.getHeader("token");
        Long userId = JwtHelper.getUserId(token);
        newsHeadline.setPublisher(userId.intValue());
        // 将新闻存入数据库
        headlineService.addNewsHeadline(newsHeadline);
        WebUtil.writeJson(resp, Result.ok(null));
    }

4.2.3 dao

    /**
     * 增加新闻头条
     * @param newsHeadline
     * @return
     */
    int addNewsHeadline(NewsHeadline newsHeadline);
    @Override
    public 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());
    }

添加成功:
1

4.3 修改头条回显

1

  • 前端先调用登录校验接口,校验登录是否过期
  • 登录校验通过后 ,则根据新闻id查询新闻的完整信息并响应给前端

URI : headline/findHeadlineByHid
请求方式:POST
请求参数:hid=1

  • 响应实例:
    • 查询成功
{
    "code":"200",
    "message":"success",
    "data":{
        "headline":{
            "hid":"1",
            "title":"马斯克宣布",
            "article":"... ... ",
            "type":"2"
        }
    }
}

4.3.1 controller

    /**
     * 修改新闻信息
     *
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    protected void findHeadlineByHid(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Integer hid = Integer.valueOf(req.getParameter("hid"));
        HeadlineDetailVo headlineByHid = headlineService.findHeadlineByHid(hid);
        HashMap<String, Object> headlineMap = new HashMap<>();
        Result result = null;
        if(null != headlineByHid){
            headlineMap.put("headline",headlineByHid);
            result = Result.ok(headlineMap);
        }
        WebUtil.writeJson(resp,result);
    }

4.4 保存修改

1

  • 客户端将新闻信息修改后,提交前先请求登录校验接口校验登录状态
  • 登录校验通过则提交修改后的新闻信息,后端接收并更新进入数据库

URI:headline/update
请求方式:post

  • 请求参数:
{
    "hid":"1",
    "title":"道格维克 ... ...",
    "article":"... ...",
    "type":"2"
}
  • 响应实例:

修改成功:

{
    "code":"200",
    "message":"success",
    "data":{}
}

修改失败:

{
    "code":"504",
    "message":"loginExpired",
    "data":{}
}

代码实现:

4.4.1 controller

    /**
     * 修改新闻信息
     * @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);
        headlineService.updateHeadline(newsHeadline);
        WebUtil.writeJson(resp,Result.ok(null));
    }

4.4.2 service

    /**
     * 修改新闻信息
     * @param newsHeadline
     * @return
     */
    int updateHeadline(NewsHeadline newsHeadline);
    @Override
    public int updateHeadline(NewsHeadline newsHeadline) {
        return headLineDao.updateHeadlineInfo(newsHeadline);
    }

4.4.3 dao

    /**
     * 修改新闻信息
     * @param newsHeadline
     * @return
     */
    int updateHeadlineInfo(NewsHeadline newsHeadline);
    @Override
    public int updateHeadlineInfo(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());
    }

4.5 删除头条

2

  • 将要删除的新闻id发送给服务端
  • 服务端校验登录是否过期,未过期则直接删除,过期则响应登录过期信息

URI : headline/removeByHid
请求方式:POST
请求参数:hid=1

  • 响应实例:

删除成功

{
    "code":"200",
    "message":"success",
    "data":{}
}

删除失败

{
    "code":"504",
    "message":"loginExpired",
    "data":{}
    
}
  • controller:
    /**
     * 删除对应Hid的新闻
     * @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"));
        headlineService.removeByHid(hid);
        WebUtil.writeJson(resp,Result.ok(null));
    }
  • service
    /**
     * 删除单个新闻
     * @param hid 新闻hid
     * @return
     */
    int removeByHid(Integer hid);
    @Override
    public int removeByHid(Integer hid) {
        return headLineDao.removeByHid(hid);
    }
  • dao
    /**
     * 删除对应hid的新闻
     * @param hid
     * @return
     */
    int removeByHid(Integer hid);
    @Override
    public int removeByHid(Integer hid) {
        String sql = "update news_headline set is_deleted = 1, update_time = NOW() where hid = ?";
        return baseUpdate(sql, hid);
    }

总结

2.1 登录表单提交

controller

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1440982.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

免费生成ios证书的方法(无需mac电脑)

使用hbuilderx的uniapp框架开发移动端程序很方便&#xff0c;可以很方便地开发出移动端的小程序和app。但是打包ios版本的app的时候却很麻烦&#xff0c;官方提供的教程需要使用mac电脑来生成证书&#xff0c;但是mac电脑却不便宜&#xff0c;一般的型号都差不多上万。 因此&a…

网络学习:数据链路层VLAN原理和配置

一、简介&#xff1a; VLAN又称为虚拟局域网&#xff0c;它是用来将使用路由器的网络分割成多个虚拟局域网&#xff0c;起到隔离广播域的作用&#xff0c;一个VLAN通常对应一个IP网段&#xff0c;不同VLAN通常规划到不同IP网段。划分VLAN可以提高网络的通讯质量和安全性。 二、…

彻底学会系列:一、机器学习之线性回归(一)

1.基本概念(basic concept) 线性回归&#xff1a; 有监督学习的一种算法。主要关注多个因变量和一个目标变量之间的关系。 因变量&#xff1a; 影响目标变量的因素&#xff1a; X 1 , X 2 . . . X_1, X_2... X1​,X2​... &#xff0c;连续值或离散值。 目标变量&#xff1a; …

C++Linux网络编程day02:select模型

本文是我的学习笔记&#xff0c;学习路线跟随Github开源项目&#xff0c;链接地址&#xff1a;30dayMakeCppServer 文章目录 select模型fd_set结构体 timeval结构体文件描述符的就绪条件带外数据与普通数据socket的状态 select模型 select是Linux下的一个IO复用模型&#xff…

用HTML5实现灯笼效果

本文介绍了两种实现效果&#xff1a;一种使用画布&#xff08;canvas&#xff09;标签/元素&#xff0c;另一种不用画布&#xff08;canvas&#xff09;标签/元素主要使用CSS实现。 使用画布&#xff08;canvas&#xff09;标签/元素实现&#xff0c;下面&#xff0c;在画布上…

Idea里自定义封装数据警告解决 Spring Boot Configuration Annotation Processor not configured

我们自定对象封装指定数据&#xff0c;封装类上面一个红色警告&#xff0c;虽然不影响我们的执行&#xff0c;但是有强迫症看着不舒服&#xff0c; 去除方式&#xff1a; 在pom文件加上坐标刷新 <dependency><groupId>org.springframework.boot</groupId><…

Android AOSP源码研究之万事开头难----经验教训记录

文章目录 1.概述2.Android源下载1.配置环境变量2.安装curl3.下载repo并授权4.创建一个文件夹保存源码5.设置repo的地址并配置为清华源6.初始化仓库7.指定我们需要下载的源码分支并初始化 2.1 使用移动硬盘存放Android源码的坑2.2 解决方法 3.Android源码编译4.Android源烧录 1.…

v-if 和v-for的联合规则及示例

第073个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下&#xff0c;本专栏提供行之有效的源代码示例和信息点介绍&#xff0c;做到灵活运用。 提供vue2的一些基本操作&#xff1a;安装、引用&#xff0c;模板使用&#xff0c;computed&a…

SpringBoot WebSocket客户端与服务端一对一收发信息

依赖 <!--websocket--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>配置类 Configuration public class WebSocketConfig {Bean //方法返回值交…

跟着小德学C++之TCP基础

嗨&#xff0c;大家好&#xff0c;我是出生在达纳苏斯的一名德鲁伊&#xff0c;我是要立志成为海贼王&#xff0c;啊不&#xff0c;是立志成为科学家的德鲁伊。最近&#xff0c;我发现我们所处的世界是一个虚拟的世界&#xff0c;并由此开始&#xff0c;我展开了对我们这个世界…

FATFA文件系统

一.文件系统基本知识 1.文件系统是什么&#xff1f; 文件系统是一种用于组织和存储计算机上的文件和目录的方法。它是操作系统中的一个重要组成部分&#xff0c;负责管理磁盘或其他存储介质上的文件&#xff0c;使其易于访问和使用。文件系统提供了一种结构化的方式来组织文件…

three.js 匀速动画(向量表示速度)

效果&#xff1a; 代码&#xff1a; <template><div><el-container><el-main><div class"box-card-left"><div id"threejs" style"border: 1px solid red"></div>1. 匀速动画(向量表示速度)</div…

RibbonOpenFeign源码(待完善)

Ribbon流程图 OpenFeign流程图

Window环境下使用go编译grpc最新教程

网上的grpc教程都或多或少有些老或者有些问题&#xff0c;导致最后执行生成文件时会报很多错。这里给出个人实践出可执行的编译命令与碰到的报错与解决方法。&#xff08;ps:本文代码按照煎鱼的教程编写&#xff1a;4.2 gRPC Client and Server - 跟煎鱼学 Go (gitbook.io)&…

R语言rmarkdown使用

1、安装 install.packages(rmarkdown) library(rmarkdown) install.packages(tinytex) tinytex::install_tinytex() 2、新建R Markdown 3、基本框架 红色框内为YAML&#xff1a;包括标题、作者和日期等 黄色框内为代码块&#xff1a;执行后面的代码&#xff0c;并可以设置展…

Java风暴:打造高效作家信息管理平台

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

Spring Boot + 七牛OSS: 简化云存储集成

引言 Spring Boot 是一个非常流行的、快速搭建应用的框架&#xff0c;它无需大量的配置即可运行起来&#xff0c;而七牛云OSS提供了稳定高效的云端对象存储服务。利用两者的优势&#xff0c;可以为应用提供强大的文件存储功能。 为什么选择七牛云OSS? 七牛云OSS提供了高速的…

NGINX upstream、stream、四/七层负载均衡以及案例示例

文章目录 前言1. 四/七层负载均衡1.1 开放式系统互联模型 —— OSI1.2 四/七层负载均衡 2. Nginx七层负载均衡2.1 upstream指令2.2 server指令和负载均衡状态与策略2.2.1 负载均衡状态2.2.2 负载均衡策略 2.3 案例 3. Nginx四层负载均衡的指令3.1 stream3.2 upstream指令3.3 四…

排序算法---归并排序

原创不易&#xff0c;转载请注明出处。欢迎点赞收藏~ 归并排序是一种常见的排序算法&#xff0c;它采用了分治的思想。它将一个待排序的数组递归地分成两个子数组&#xff0c;分别对两个子数组进行排序&#xff0c;然后将排好序的子数组合并成一个有序数组。 具体的归并排序过…

Docker部署前端项目

某次阿里云的自动流水线失败了&#xff0c;代码本地跑起来莫得问题&#xff0c;错误日志提示让我跑一下npm run build &#xff0c;但是俺忽然发现&#xff0c;我跑了&#xff0c;文件打包好了&#xff0c;但是往哪里运行呢&#xff1f;这涉及到要构建一个环境供打包文件部署吧…