黑龙江省建设安全网站郑州app制作

当前位置: 首页 > news >正文

黑龙江省建设安全网站,郑州app制作,做网站都需要什么贴吧,无备案网站加速目录 1.项目展示2.项目结构设计3.项目功能设计4 数据库准备4.1 建表4.2 DB相关数据 5.项目模块6.添加项目公共模块6.1 common6.2 实现前端界面 7.功能实现7.1实现博客列表约定前后端交互接口实现服务器代码实现客户端代码 7.2实现博客详情约定前后端交互接口实现服务器代码实现… 目录 1.项目展示2.项目结构设计3.项目功能设计4 数据库准备4.1 建表4.2 DB相关数据 5.项目模块6.添加项目公共模块6.1 common6.2 实现前端界面 7.功能实现7.1实现博客列表约定前后端交互接口实现服务器代码实现客户端代码 7.2实现博客详情约定前后端交互接口实现服务器代码实现客户端代码 7.3实现登录约定前后端交互接口实现服务器代码实现客户端代码 7.4实现强制要求登录添加拦截器实现客户端代码 7.5实现显示用户信息约定前后端交互接口实现服务器代码 7.6实现用户退出约定前后端交互接口实现服务器代码实现客户端代码 7.7实现发布博客约定前后端交互接口实现服务器代码实现客户端代码 7.8实现删除/编辑博客约定前后端交互接口实现服务器代码实现客户端代码 7.9实现加密加盐加密工具类使用修改数据库密码 1.项目展示 项目已经发布到云服务器上想要使用的小伙伴可以点击下面这个链接 博客项目 由于目前没有实现注册功能所以这里直接提供一个账号用以登录 账号lisi 密码123456 2.项目结构设计 后端框架SpringBoot 数据库mybatis 前后端交互ajax 3.项目功能设计 主要功能如下图所示 一共四个页面 登录页面 博客列表页面 博客详情页
写博客页面 4 数据库准备 4.1 建表 一共两张表 user(用户表) blog(博客表) 创建数据库 create database if not exists java_blog_spring charset utf8mb4;创建user表 drop table if exists java_blog_spring.user; CREATE TABLE java_blog_spring.user (id INT NOT NULL AUTO_INCREMENT,user_name VARCHAR(128) NOT NULL,password VARCHAR(128) NOT NULL,github_url VARCHAR(128) NULL,delete_flag TINYINT(4) NULL DEFAULT 0,create_time TIMESTAMP NULL DEFAULT current_timestamp(),PRIMARY KEY (id),UNIQUE INDEX user_name_UNIQUE (user_name ASC)) ENGINE InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT ⽤户表;创建blog表 drop table if exists java_blog_spring.blog; CREATE TABLE java_blog_spring.blog (id INT NOT NULL AUTO_INCREMENT,title VARCHAR(200) NULL,content TEXT NULL,user_id INT(11) NULL,delete_flag TINYINT(4) NULL DEFAULT 0,create_time TIMESTAMP NULL DEFAULT current_timestamp(),PRIMARY KEY (id)) ENGINE InnoDB DEFAULT CHARSET utf8mb4 COMMENT 博客表;增加一些测试数据 insert into java_blog_spring.user (user_name, password,github_url )values(zhangsan,123456,https://gitee.com/bubble-fish666/class-java4 5); insert into java_blog_spring.user (user_name, password,github_url )values(lisi,123456,https://gitee.com/bubble-fish666/class-java45); insert into java_blog_spring.blog (title,content,user_id) values (第⼀篇博客,111我是博客正⽂我是博客正⽂我是博客正⽂,1); insert into java_blog_spring.blog (title,content,user_id) values (第⼆篇博客,222我是博客正⽂我是博客正⽂我是博客正⽂,2);4.2 DB相关数据 DB相关查询 获取所有博客列表根据博客Id获取博客详情插⼊博客更新博客根据id查询user信息根据name查询user信息 User类 Data public class User {private Integer id;private String userName;private String password;private String githubUrl;private Byte deleteFlag;private Date createTime; }Blog类 Data public class Blog {private Integer id;private String title;private String content;private Integer userId;private Integer deleteFlag;private Date createTime;//是否为登录用户1表示为登录用户private Integer loginUser;public String getCreateTime() {//对时间进行格式化return DateUtils.formatDate(createTime);} }UserMapper类 Mapper public interface UserMapper {Select(select id,user_name,password,github_url,delete_flag,create_time from user where delete_flag0 and id#{id})User selectById(Integer id);Select(select id,user_name,password,github_url,delete_flag,create_time from user where delete_flag0 and user_name#{name})User selectByName(String name); }BlogMapper类 Mapper public interface BlogMapper {Select(select * from blog where delete_flag0)ListBlog selectAllBlog();Select(select * from blog where delete_flag0 and id#{blogId})Blog selectBlogById(Integer blogId);Integer updateBlog(Blog blog);Insert(insert into blog(title,content,user_id) values (#{title},#{content},#{userId}))Integer insertBlog(Blog blog); }BlogMapper.xml: mapper namespacecom.example.springblog.mapper.BlogMapperupdate idupdateBlogupdate blogsetif testtitle!nulltitle#{title},/ifif testcontent!nullcontent#{content},/ifif testuserId!nulluser_id#{userId},/ifif testdeleteFlag!nulldelete_flag#{deleteFlag},/if/setwhere id#{id}/update /mapper5.项目模块 6.添加项目公共模块 6.1 common 统一异常抽取为一个类 Data public class Result {//业务处理状态码 200成功 0失败private Integer code;//业务返回提示信息private String msg;//业务返回数据private Object data;/*** 失败时处理内容* return/public static Result fail(Integer code,String msg) {Result resultnew Result();result.setCode(code);result.setMsg(msg);result.setData();return result;}public static Result fail(Integer code,String msg,Object data) {Result resultnew Result();result.setCode(code);result.setMsg(msg);result.setData(data);return result;}/** 业务处理成功* param data* return/public static Result success(Object data) {Result resultnew Result();result.setCode(200);result.setMsg();result.setData(data);return result;}public static Result success(String msg,Object data) {Result resultnew Result();result.setCode(200);result.setMsg(msg);result.setData(data);return result;} }出错时统一异常处理 ControllerAdvice public class ErrorAdvice {ExceptionHandlerpublic Result error(Exception e){return Result.fail(-1,e.getMessage());} }数据统一返回格式 ControllerAdvice public class ResponseAdvice implements ResponseBodyAdvice {Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}//在数据返回之前进行处理SneakyThrows //异常处理注解Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {if(body instanceof Result){return body;}if(body instanceof String){ObjectMapper objectMappernew ObjectMapper();return objectMapper.writeValueAsString(Result.success(body));}return Result.success(body);} }6.2 实现前端界面 把之前写好的博客系统静态⻚⾯拷⻉到static⽬录下 7.功能实现 7.1实现博客列表 约定前后端交互接口 [请求] /blog/getlist [响应] [{blogId: 1,title: 第⼀篇博客,content: 博客正⽂,userId: 1,postTime: 2021-07-07 12:00:00},{blogId: 2,title: 第⼆篇博客,content: 博客正⽂,userId: 1,postTime: 2021-07-07 12:10:00},… ]我们约定, 浏览器给服务器发送⼀个 /blog/getlist 这样的 HTTP 请求, 服务器给浏览器返回了⼀个 JSON 格式的数据. 实现服务器代码 在 BlogController 中添加⽅法: Slf4j RequestMapping(/blog) RestController public class BlogController {Autowiredprivate BlogService blogService;RequestMapping(/getlist)public ListBlog getBlogList(){return blogService.selectAllBlog();} }在BlogService 中添加⽅法: public class BlogService {Autowiredprivate BlogMapper blogMapper;public ListBlog selectAllBlog(){return blogMapper.selectAllBlog();} }部署程序, 验证服务器是否能正确返回数据 (使⽤ URL http://127.0.0.1:8080/blog/getlist 即可) 实现客户端代码 修改 blog_list.html, 删除之前写死的博客内容, 并新增js 代码处理 ajax 请求. script src./js/jquery.min.js/scriptscript src./js/common.js/scriptscript\(.ajax({type:get,url:/blog/getlist,success:function(result){if(result.code200 result.data!null result.data.length0){var blogsresult.data;var finalHtml;for(var blog of blogs){finalHtml div classblog;finalHtml div classtitleblog.title/divfinalHtml div classdateblog.createTime/divfinalHtml div classdescblog.content/divfinalHtml a classdetail hrefblog_detail.html?blogIdblog.id查看全文gt;gt;/afinalHtml /div}\)(.right).html(finalHtml);}},error:function(error){console.log(error);if(error!null error.status401){//用户未登录location.assign(blog_login.html);}}});var url/user/getUserInfo;getUserInfo(url);/script7.2实现博客详情 ⽬前点击博客列表⻚的 “查看全⽂” , 能进⼊博客详情⻚, 但是这个博客详情⻚是写死的内容. 我们期望能够根据当前的 博客 id 从服务器动态获取博客内容. 约定前后端交互接口 /blog/getBlogDetail?blogId1 [响应] {blogId: 1,title: 第⼀篇博客,content: 博客正⽂,userId: 1,postTime: 2021-07-07 12:00:00 }实现服务器代码 在 BlogController 中添加getBlogDeatail ⽅法: /** 获取博客详情* param blogId* return/RequestMapping(/getBlogDetail)public Result getBlogDetail(Integer blogId,HttpSession session){log.info(blogId:blogId);if(blogId null){return Result.fail(-1,非法博客id);}Blog blogblogService.selectBlogById(blogId);//获取登录用户信息User loginUser(User) session.getAttribute(Constants.USER_INFO_SESSION);//判断登录用户和博客作者是否是同一个人if(loginUser!null loginUser.getId() blog.getUserId()){blog.setLoginUser(1);}return Result.success(blog);}在BlogService 中添加getBlogDeatil⽅法: public Blog selectBlogById(Integer blogId){return blogMapper.selectBlogById(blogId);}实现客户端代码 script\(.ajax({type:get,url:/blog/getBlogDetaillocation.search,success:function(result){if(result.code200 result.data!null){var blogresult.data;\)(.title).text(blog.title);\((.date).text(blog.createTime);editormd.markdownToHTML(content, {markdown: blog.content ,});//\)(.detail).text(blog.content);if(blog.loginUser1){var html;html button onclickwindow.location.href\blog_update.html?blogIdblog.id\编辑/button;htmlbutton onclickdeleteBlog()删除/button;\((.operating).html(html);}}},error:function(error){consolo.log(error);if(error!null error.status401){//用户未登录location.assign(blog_login.html);}}});var url /user/getAuthorInfo location.search;getUserInfo(url); common.js代码 function getUserInfo(url){\).ajax({type:get,url:url,success:function(result){if(result!null result.code200 result.data!null){var userresult.data;\((.left .card h3).text(user.userName);\)(.left .card a).attr(href,user.githubUrl);}}}); }7.3实现登录 登陆⻚⾯提供⼀个 form 表单, 通过 form 的⽅式把⽤户名密码提交给服务器. 服务器端验证⽤户名密码是否正确. 如果密码正确, 则在服务器端创建 Session , 并把 sessionId 通过 Cookie 返回给浏览器
约定前后端交互接口 [请求] /user/login usernametestpassword123 [响应] 200 登录成功 0 登录失败实现服务器代码 在 UserController 中添加⽅法: RestController RequestMapping(/user) public class UserController {Autowiredprivate UserService userService;RequestMapping(/login)public Result login(HttpServletRequest request,String username, String password){//参数校验if(!StringUtils.hasLength(username) || !StringUtils.hasLength(password)){return Result.fail(-1,用户名密码不能为空);}//验证密码User useruserService.selectByName(username);if(usernull || !SecurityUtils.decrypt(password,user.getPassword())){return Result.fail(-2,用户名密码错误);}//设置sessionHttpSession session request.getSession(true);session.setAttribute(Constants.USER_INFO_SESSION,user);return Result.success(登录成功);} }在UserService 中添加⽅法: Service public class UserService {Autowiredprivate UserMapper userMapper;Autowiredprivate BlogMapper blogMapper;public User selectByName(String name){return userMapper.selectByName(name);} }实现客户端代码 script src./js/jquery.min.js/scriptscriptfunction login(){\(.ajax({type:post,url:/user/login,data:{username:\)(#userName).val(),password:$(#password).val()},success:function(result){if(result.code200){location.hrefblog_list.html;return;}else if(result.code0 result.msg!){alert(result.msg);return;}},error:{}});}/script7.4实现强制要求登录 当⽤户访问 博客列表⻚ 和 博客详情⻚ 时, 如果⽤户当前尚未登陆, 就⾃动跳转到登陆⻚⾯. 添加拦截器 登录拦截器 Component public class LoginInterceptor implements HandlerInterceptor {Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {HttpSession sessionrequest.getSession(false);if(session!null session.getAttribute(Constants.USER_INFO_SESSION)!null){//用户已经登录了return true; //不拦截}response.setStatus(401);return false;} }使用拦截器 Configuration public class AppConfig implements WebMvcConfigurer {private final ListString excludePaths Arrays.asList(/**/
.html,/blog-editormd/,/css/,/js/,/pic/,/user/login);Autowiredprivate LoginInterceptor loginInterceptor;//添加拦截器Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor).addPathPatterns(/) //拦截所有路径.excludePathPatterns(excludePaths); //不拦截excludePaths包括的类型文件} }实现客户端代码 1.修改 blog_datail.html 访问⻚⾯时, 添加失败处理代码使⽤ location.assign 进⾏⻚⾯跳转. error:function(error){console.log(error);if(error!null error.status401){//用户未登录location.assign(blog_login.html);}}2.修改 blog_list.html 访问⻚⾯时, 添加失败处理代码使⽤ location.assign 进⾏⻚⾯跳转. error:function(error){consolo.log(error);if(error!null error.status401){//用户未登录location.assign(blog_login.html);}}7.5实现显示用户信息 如果当前⻚⾯是博客列表⻚, 则显示当前登陆⽤户的信息.如果当前⻚⾯是博客详情⻚, 则显示该博客的作者⽤户信息. 约定前后端交互接口 在博客列表⻚, 获取当前登陆的⽤户的⽤户信息. [请求] /user/getUserInfo [响应] { userId: 1, username: test… }在博客详情⻚, 获取当前⽂章作者的⽤户信息 [请求] /user/getAuthorInfo?blogId1 [响应] { userId: 1, username: test }实现服务器代码 在 UserController 中添加⽅法: /* 获取登录用户信息* return/RequestMapping(/getUserInfo)public Result getUserInfo(HttpSession session){if(sessionnull || session.getAttribute(Constants.USER_INFO_SESSION)null){return Result.fail(-1,用户未登录);}User user(User)session.getAttribute(Constants.USER_INFO_SESSION);return Result.success(user);}/** 获取博客作者信息* return/RequestMapping(/getAuthorInfo)public Result getAuthorInfo(Integer blogId){if(blogIdnull || blogId0){return Result.fail(-1,博客不存在~);}User useruserService.selectAuthorByBlogId(blogId);return Result.success(user);} 在UserService 中添加⽅法: public User selectAuthorByBlogId(Integer blogId){User usernull;Blog blogblogMapper.selectBlogById(blogId);if(blog!null blog.getUserId()0){useruserMapper.selectById(blog.getUserId());}if(user!null){user.setPassword();}return user;}7.6实现用户退出 约定前后端交互接口 [请求] /user/logout [响应] true实现服务器代码 在 UserController 中添加⽅法: /** 注销* return/RequestMapping(/logout)public Result logout(HttpSession session){session.removeAttribute(Constants.USER_INFO_SESSION);return Result.success(true);}实现客户端代码 客户端代码, 注销改为⼀个a标签, href 设置为logout, 点击的时候就会发送GET/logout请求 a classnav-span href# onclicklogout()注销/a在common.js中添加logout⽅法: function logout(){$.ajax({type:get,url:/user/logout,success:function(result){if(result!null result.datatrue){location.hrefblog_login.html;}}}); }7.7实现发布博客 约定前后端交互接口 [请求] /blog/add title标题content正⽂… [响应] true 成功 false 失败实现服务器代码 在 BlogController 中添加⽅法: /** 发布博客* return/RequestMapping(/add)public Result addBlog(String title, String content,HttpSession session){if(!StringUtils.hasLength(title) || !StringUtils.hasLength(content)){return Result.fail(-1,标题或内容不能为空);}User user (User) session.getAttribute(Constants.USER_INFO_SESSION);if(usernull || user.getId()0){return Result.fail(-1,用户不存在);}try{Blog blognew Blog();blog.setTitle(title);blog.setContent(content);blog.setUserId(user.getId());blogService.insertBlog(blog);}catch (Exception e){return Result.fail(-1,博客发布失败~);}return Result.success(true);}在BlogService 中添加⽅法: public Integer insertBlog(Blog blog){return blogMapper.insertBlog(blog);}实现客户端代码 给提交按钮添加click事件 input type“button” value发布⽂章id“submit” οnclick“submit()” \((#submit).click(function(){\).ajax({type:post,url:/blog/add,data:{title:\((#title).val(),content:\)(#content).val()},success:function(result){if(result!null result.code200 result.datatrue){location.hrefblog_list.html;}else{alert(result.msg);}},error:function(error){if(error!null error.status401){alert(请先登录);}}});});7.8实现删除/编辑博客 进⼊⽤户详情⻚时, 如果当前登陆⽤户正是⽂章作者, 则在导航栏中显示 “删除” 按钮, ⽤户点击时则删除该⽂章. 需要实现两件事: 判定当前博客详情⻚中是否要显示 删除 按钮实现删除逻辑. 约定前后端交互接口 编辑博客 [请求] /blog?BlogId1 [响应] {blogId: 1,title: 第⼀篇博客,content: 博客正⽂,userId: 1,postTime: 2021-07-07 12:00:00,loginUser: 1 }删除博客 [请求] GET /blog/delete?blogId1 [响应] true 删除成功实现服务器代码 在 BlogController 中添加⽅法: /** 更新博客* param blog* return/RequestMapping(/updateBlog)public Result updateBlog(Blog blog){if(!StringUtils.hasLength(blog.getTitle()) || !StringUtils.hasLength(blog.getContent()) || blog.getId()null){return Result.fail(-1,标题或内容不合法);}blogService.updateBlog(blog);return Result.success(true);}/** 删除博客* return/RequestMapping(/deleteBlog)public Result deleteBlog(Integer blogId){if(blogIdnull){return Result.fail(-1,博客不存在~);}Blog blognew Blog();blog.setId(blogId);blog.setDeleteFlag(1);blogService.updateBlog(blog);return Result.success(true);} }在BlogService 中添加⽅法: public Integer updateBlog(Blog blog){return blogMapper.updateBlog(blog);}实现客户端代码 删除博客 function deleteBlog(){\(.ajax({type:post,url:/blog/deleteBlog location.search,success:function(result){if(result!null result.code200 result.datatrue){location.hrefblog_list.html;}else{alert(result.msg);}},eeror:function(error){if(error!null error.status401){//用户未登录location.assign(blog_login.html);}}});}编辑博客 //获取博客的详细内容并且反应到页面上\).ajax({type:get,url:/blog/getBlogDetail location.search,success:function(result){if(result!null result.code200 result.data!null){var blogresult.data;\((#blogId).val(blog.id);\)(#title).val(blog.title);\((#content).val(blog.content);}else if(result!null){alert(result.msg);}},error:function(error){if(error!null error.status401){//用户未登录location.assign(blog_login.html);}}});\)(#submit).click(function(){\(.ajax({type:post,url:/blog/updateBlog,data:{id:\)(#blogId).val(),title:\((#title).val(),content:\)(#content).val()},success:function(result){if(result!null result.code200 result.datatrue){location.hrefblog_list.html;}else if(result!null){alert(result.msg);}}});});/script7.9实现加密加盐 加密工具类 使用md5进行密码加密 public class SecurityUtils {/** 加密* 根据明文返回密文salt加密后的密文* return/public static String encry(String inputPassword){//生成盐值String salt UUID.randomUUID().toString().replace(-,);//md5加密明文盐值String password DigestUtils.md5DigestAsHex((inputPasswordsalt).getBytes());return saltpassword;}/** 验证密码是否正确* return*/public static boolean decrypt(String inputPassword,String finalPassword){//判空if(!StringUtils.hasLength(inputPassword) || !StringUtils.hasLength(finalPassword)){return false;}//验证长度if(finalPassword.length()!64){return false;}//验证密码String saltfinalPassword.substring(0,32);String password DigestUtils.md5DigestAsHex((inputPasswordsalt).getBytes());return (saltpassword).equals(finalPassword);} } 使用 //验证密码User useruserService.selectByName(username);if(usernull || !SecurityUtils.decrypt(password,user.getPassword())){return Result.fail(-2,用户名密码错误);}修改数据库密码 使⽤测试类给密码123456⽣成密⽂: e2377426880545d287b97ee294fc30ea6d6f289424b95a2b2d7f8971216e39b7 执行SQL update user set passworde2377426880545d287b97ee294fc30ea6d6f289424b95a2b2 d7f8971216e39b7 where id1;