【JavaWeb】头条新闻项目实现 基本增删改查 分页查询 登录注册校验 业务功能实现 第二期
文章目录
- 一、为什么使用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 对于高并发项目不合适
- token:
二、登录注册功能
2.1 登录表单提交
需求描述:
输入 用户名 密码 验证登录,根据输入的用户名 和 密码 提示不同的响应信息
URI:
user/login
请求方式:
POST
请求参数:
{ "username":"dougwake", //用户名 "userPwd":"123456" //明文密码 }
响应示例:
- 登录成功
- 用户名输入有误:
- 密码错误:
后端代码:
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()))) {// 响应结果 是键值对形式 所以用mapMap<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();@Overridepublic 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 {@Overridepublic NewsUser findByUsername(String username) {String sql = """selectuid,username,user_pwd userPwd,nick_name nickNamefromnews_userwhereusername = ?;""";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: ...
响应示例
- 成功获取
- 获取失败
代码实现:
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);
@Overridepublic NewsUser findByUid(Integer uid) {return newsUserDao.finByUid(uid);}
2.2.3 Dao
NewsUser finByUid(Integer uid);
@Overridepublic NewsUser finByUid(Integer uid) {String sql = """selectuid,username,user_pwd userPwd,nick_name nickNamefromnews_userwhereuid = ?;""";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
响应示例:
- 用户名校验通过
- 用户名被占用
代码实现:
/*** 注册时校验用户名是否占用* @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":"加文"
}
响应示例:
- 注册成功:
- 用户名占用:(第二次注册)
代码实现:
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);
@Overridepublic 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());}
三、头条首页功能
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();@Overridepublic List<NewsType> findAllTypes() {return typeDao.findAllTypes();}
}
- dao
public interface NewsTypeDao {/*** 查询全部新闻类型* @return 新闻类型数据*/List<NewsType> findAllTypes();
}
public class NewsTypeDaoImpl extends BaseDao implements NewsTypeDao {@Overridepublic 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 // 总记录数}}
}
代码实现:
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();@Overridepublic 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 {@Overridepublic List<HeadlinePageVo> findPageList(HeadlineQueryVo headlineQueryVo) {List params = new ArrayList();String sql = """selecthid,title,type,page_views pageViews,TIMESTAMPDIFF(HOUR,create_time,now()) pastHours,publisherfromnews_headlinewhereis_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());}@Overridepublic 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 查看头条详情
- 用户点击"查看全文"时,向服务端发送新闻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 {// 获取要查询的详情新闻idInteger hid = Integer.valueOf(req.getParameter("hid"));// 封装data内容HashMap<String, Object> headlineInfo = new HashMap<>();// 查询新闻详情的voHeadlineDetailVo 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);
@Overridepublic HeadlineDetailVo findHeadlineByHid(Integer hid) {// 修改新闻信息浏览量+1headLineDao.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);
@Overridepublic HeadlineDetailVo findHeadlineInfoByHid(Integer hid) {String sql = """selecth.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 authorfromnews_headline hleft joinnews_type tonh.type = t.tidleft joinnews_user uonh.publisher = u.uidwhereh.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);}
四、头条发布修改和删除
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 {@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;// }//}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 提交发布头条(新增
- 用户在客户端输入发布的新闻信息完毕后
- 发布前先请求后端的登录校验接口验证登录
- 登录通过则提交新闻信息
- 后端将新闻信息存入数据库
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获取发布者IDString 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获取发布者IDString 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);
@Overridepublic int addNewsHeadline(NewsHeadline newsHeadline) {String sql = """insert intonews_headlinevalues(DEFAULT,?,?,?,?,0,NOW(),NOW(),0) """;return baseUpdate(sql,newsHeadline.getTitle(),newsHeadline.getArticle(),newsHeadline.getType(),newsHeadline.getPublisher());}
添加成功:
4.3 修改头条回显
- 前端先调用登录校验接口,校验登录是否过期
- 登录校验通过后 ,则根据新闻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 保存修改
- 客户端将新闻信息修改后,提交前先请求登录校验接口校验登录状态
- 登录校验通过则提交修改后的新闻信息,后端接收并更新进入数据库
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);
@Overridepublic int updateHeadline(NewsHeadline newsHeadline) {return headLineDao.updateHeadlineInfo(newsHeadline);}
4.4.3 dao
/*** 修改新闻信息* @param newsHeadline* @return*/int updateHeadlineInfo(NewsHeadline newsHeadline);
@Overridepublic 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 删除头条
- 将要删除的新闻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);
@Overridepublic int removeByHid(Integer hid) {return headLineDao.removeByHid(hid);}
- dao
/*** 删除对应hid的新闻* @param hid* @return*/int removeByHid(Integer hid);
@Overridepublic int removeByHid(Integer hid) {String sql = "update news_headline set is_deleted = 1, update_time = NOW() where hid = ?";return baseUpdate(sql, hid);}
总结
2.1 登录表单提交
相关文章:
【JavaWeb】头条新闻项目实现 基本增删改查 分页查询 登录注册校验 业务功能实现 第二期
文章目录 一、为什么使用token口令二、登录注册功能2.1 登录表单提交后端代码: 2.2 根据token获取完整用户信息代码实现: 2.3 注册时用户名占用校验代码实现: 2.4 注册表单提交代码实现: 三、头条首页功能3.1 查询所有头条分类3.2…...
HiveQL——不借助任何外表,产生连续数值
注:参考文章: HiveSql一天一个小技巧:如何不借助其他任何外表,产生连续数值_hive生成连续数字-CSDN博客文章浏览阅读1.3k次。0 需求描述输出结果如下所示:12345...1001 问题分析方法一:起始值(…...
Docker容器监控-CIG
目录 一、CIG说明 1. CAdvisor 2. InfluxDB 3. Grafana 二、环境搭建 1. 创建目录 2. 编写 docker-compose.yml 3. 检查并运行容器 三、进行测试 1. 查看 influxdb 存储服务 是否能正常访问 2. 查看 cAdvisor 收集服务能否正常访问 3. 查看 grafana 展现服务&#…...
python调用golang中函数方法
一、原因说明:由于simhash方法有多种实现方式,现python中simhash方法与golang中的不一样,需要两者代码生成结果保持一致,故采用python中的代码调用golang编译的so文件来实现。 环境配置:①Windows10系统要有gcc环境&a…...
Ps:颜色取样器工具
颜色取样器工具 Color Sampler Tool允许用户从图像中设置特定的颜色取样点,然后利用“信息”面板查看该点在不同颜色模式下(包括:RGB、CMYK、Lab、灰度等)的颜色值,因此可为色彩分析、颜色校正、色彩匹配等提供精确的数…...
Rust引用、借用和所有权详解
在Rust中,引用、借用和所有权是语言的核心概念,它们共同构成了内存管理的基石。本篇博客将介绍Rust中的这些概念,并通过具体的例子深入探讨它们的用法和优势。 所有权 Rust中的所有权是一种独特的内存管理机制,它规定了在特定作…...
C# 字体大小的相关问题
设置字体大小无法这么写, button1.Font.Size 20; 这个是只读属性; 把字体大小改为16, button2.Font new Font(button2.Font.Name, 16); 程序运行的时候先看一下窗体和控件的默认字体尺寸,都是9;然后点b…...
使用 Express.js 和 MySQL 构建 Web 应用程序
Express.js 是一个流行的 Node.js Web 框架,而 MySQL 是一种广泛使用的关系型数据库。本文将介绍如何结合使用 Express.js 和 MySQL 构建功能强大的 Web 应用程序。 一、安装和设置 首先,确保您已经安装了 Node.js 和 MySQL。然后,通过以下…...
1306. 跳跃游戏 III
经过测试,两种写法耗时差距10倍,我也不知道原因是啥 用访问次数的是更快的 class Solution { public:int n;bool dfs(vector<int>& arr, int start, vector<int>& visited){if(start<0||start>n || visited[start]1) return …...
List与数组相互转换
文章目录 将 List 转 数组List.toArra()Stream().toArray() 将 数组 转 ListLists.newArrayList()Stream.of() 将 List 转 数组 List.toArra() List<Integer> list Lists.newArrayList(1, 2, 3);// 无需转换类型 --> [1,2,3]Integer[] intArray list.toArray(new I…...
Linux openKylin(开放麒麟)系统SSH服务安装配置与公网远程连接
文章目录 前言1. 安装SSH服务2. 本地SSH连接测试3. openKylin安装Cpolar4. 配置 SSH公网地址5. 公网远程SSH连接6. 固定SSH公网地址7. SSH固定地址连接8. 结语 前言 openKylin是中国首个基于Linux 的桌面操作系统开发者平台,通过开放操作系统源代码的方式ÿ…...
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之AlphabetIndexer组件
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之AlphabetIndexer组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、AlphabetIndexer组件 可以与容器组件联动用于按逻辑结构快速定位容器显…...
java学习07---综合练习
飞机票 1.需求: 机票价格按照淡季旺季、头等舱和经济舱收费、输入机票原价、月份和头等舱或经济舱。 按照如下规则计算机票价格:旺季(5-10月)头等舱9折,经济舱8.5折,淡季(11月到来年4月)头等舱7…...
【RL】Bellman Equation (贝尔曼等式)
Lecture2: Bellman Equation State value 考虑grid-world的单步过程: S t → A t R t 1 , S t 1 S_t \xrightarrow[]{A_t} R_{t 1}, S_{t 1} StAt Rt1,St1 t t t, t 1 t 1 t1:时间戳 S t S_t St:时间 t t t时所处的sta…...
PyTorch 2.2大更新!集成FlashAttention-2,性能提升2倍
【新智元导读】新的一年,PyTorch也迎来了重大更新,PyTorch 2.2集成了FlashAttention-2和AOTInductor等新特性,计算性能翻倍。 新的一年,PyTorch也迎来了重大更新! 继去年十月份的PyTorch大会发布了2.1版本之后&#…...
2.9日学习打卡----初学RabbitMQ(四)
2.9日学习打卡 一.RabbitMQ 死信队列 在MQ中,当消息成为死信(Dead message)后,消息中间件可以将其从当前队列发送到另一个队列中,这个队列就是死信队列。而在RabbitMQ中,由于有交换机的概念,实…...
大数据Flume--入门
文章目录 FlumeFlume 定义Flume 基础架构AgentSourceSinkChannelEvent Flume 安装部署安装地址安装部署 Flume 入门案例监控端口数据官方案例实时监控单个追加文件实时监控目录下多个新文件实时监控目录下的多个追加文件 Flume Flume 定义 Flume 是 Cloudera 提供的一个高可用…...
【SQL高频基础题】550.游戏玩法分析IⅣ
这个SQL花了很久。但是有挺多启发的。 如果我们做不出来,就去看答案。 但是看完答案之后,不要着急就去看下一道题,先把这道题吃透,后面的题目就会更有思路。 题目: Table: Activity ----------------------- | Co…...
sheng的学习笔记-部署-目录
标题传送门 sheng的学习笔记-docker部署,原理图,命令,用idea设置docker sheng的学习笔记-docker部署,原理图,命令,用idea设置docker sheng的学习笔记-docker部署springboot sheng的学习笔记-docker部署spri…...
【Java】悲观锁和乐观锁有什么区别?
Java中的悲观锁和乐观锁的主要区别体现在以下几个方面: 加锁策略:悲观锁在操作数据时,总是假设最坏的情况,即认为其他线程会修改数据,因此在读取或操作数据时,会先对数据进行加锁,以保证数据的…...
Elasticsearch:使用查询规则(query rules)进行搜索
在之前的文章 “Elasticsearch 8.10 中引入查询规则 - query rules”,我们详述了如何使用 query rules 来进行搜索。这个交互式笔记本将向你介绍如何使用官方 Elasticsearch Python 客户端来使用查询规则。 你将使用 query rules API 将查询规则存储在 Elasticsearc…...
Java核心设计模式:代理设计模式
一、生活中常见的代理案例 房地产中介:客户手里没有房源信息,找一个中介帮忙商品代购:代理者一般有好的资源渠道,降低购物成本(如海外代购,自己不用为了买东西出国) 二、为什么要使用代理 对…...
JSP编程
JSP编程 您需要理解在JSP API的类和接口中定义的用于创建JSP应用程序的各种方法的用法。此外,还要了解各种JSP组件,如在前一部分中学习的JSP动作、JSP指令及JSP脚本。JSP API中定义的类提供了可借助隐式对象通过JSP页面访问的方法。 1. JSP API的类 JSP API是一个可用于创建…...
【Flink入门修炼】1-1 为什么要学习 Flink?
流处理和批处理是什么? 什么是 Flink? 为什么要学习 Flink? Flink 有什么特点,能做什么? 本文将为你解答以上问题。 一、批处理和流处理 早些年,大数据处理还主要为批处理,一般按天或小时定时处…...
刘谦龙年春晚魔术模拟
守岁共此时 代码 直接贴代码了,异常处理有点问题,正常流程能跑通 package com.yuhan.snginx.util.chunwan;import java.util.*;/*** author yuhan* since 2024/02/10*/ public class CWMS {static String[] num {"A", "2", &quo…...
re:从0开始的CSS学习之路 9. 盒子水平布局
0. 写在前面 过年也不能停止学习,一停下就难以为继,实属不应 1. 盒子的水平宽度 当一个盒子出现在另一个盒子的内容区时,该盒子的水平宽度“必须”等于父元素内容区的宽度 盒子水平宽度: margin-left border-left padding-lef…...
【MySQL基础】:深入探索DQL数据库查询语言的精髓(上)
🎥 屿小夏 : 个人主页 🔥个人专栏 : MySQL从入门到进阶 🌄 莫道桑榆晚,为霞尚满天! 文章目录 📑前言一. DQL1.1 基本语法1.2 基础查询1.3 条件查询1.3 聚合函数 🌤️ 全篇…...
JavaScript实现轮播图方法
效果图 先来看下效果图,嫌麻烦就不用具体图片来实现了,主要是理清思路。(自动轮播,左右按钮切换图片,小圆点切换图片,鼠标移入暂停轮播,鼠标移出继续轮播) HTML 首先是html内容&am…...
Web课程学习笔记--jsonp的原理与简单实现
jsonp的原理与简单实现 原理 由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源,为了实现跨域请求,可以通过script标签实现跨域请求,然后在服务端输出JSON数据并执行回调函数&…...
第78讲 修改密码
系统管理实现 修改密码实现 前端 modifyPassword.vue: <template><el-card><el-formref"formRef":model"form":rules"rules"label-width"150px"><el-form-item label"用户名:&quo…...
wordpress ftp安装/整合营销传播的定义
Docker 基础学习Docker概述Docker为什么出现Docker历史Docker能干什么Docker架构图安装Docker安装准备安装阿里云镜像加速回顾helloworld流程Docker底层原理Docker的常用命令帮助命令镜像命令容器命令其他常用命令小结作业部署nginx部署tomcat可视化工具portainer镜像讲解Docke…...
网站代码复制/2345浏览器影视大全
RFID(俗称电子标签),是物联网产业链感知层的重要环节。RFID产业发展的快与慢,会直接影响物联网发展的速度。 在RFID应用中分为低频、高频、超高频。而RFID超高频电子标签以其标签体积小、读写距离远、读写时间快、价格便宜等诸多…...
青海网站建设设计/seo公司优化方案
现在互联网发展迅速,前端也成了很重要的岗位之一,许多人都往前端靠拢,可又无能为力,不知所措,首先我们说为什么在编程里,大家都倾向于往前端靠呢?原因很简单,那就是,在程…...
政府网站建设管理意见/太原seo霸屏
眨眼间又到了2020年的12月31日,大家都在按着公司要求写着年终总结,然后我们在邮件里立着各式各样的flag比如工作一定加倍努力,,收入一定稳步提高,快乐的发送邮件以后迎来小长假,结果纷纷在上班第一天被打回…...
手机上怎么做能打开的网站/万网创始人
一、我们可以且应该优化什么? 硬件 操作系统/软件库 SQL服务器(设置和查询) 应用编程接口(API) 应用程序 -------------------------------------------------------------------------------- 二、优化硬件 如果你需要庞大的数据库表(>2G),你应该考虑…...
网站内做全文搜索/微信管理系统软件
在上期聊了ThinkPHP类的自动加载,如你还不太了解可以跟这下文链接去进行查看。本文会带你一起解读ThinkPHP配置文件。 前言 想了很久终于要开始系列文章的编写了,期望是写出提升和面试都可以搞定的系列文章。 当你看到本文时,如果你发现咔咔…...