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

【Spring练习项目】博客系统

目录

  • 1.项目展示
  • 2.项目结构设计
  • 3.项目功能设计
  • 4 数据库准备
    • 4.1 建表
    • 4.2 DB相关数据
  • 5.项目模块
  • 6.添加项目公共模块
    • 6.1 common
    • 6.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相关查询:

  1. 获取所有博客列表
  2. 根据博客Id获取博客详情
  3. 插⼊博客
  4. 更新博客
  5. 根据id查询user信息
  6. 根据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_flag=0 and id=#{id}")User selectById(Integer id);@Select("select id,user_name,password,github_url,delete_flag,create_time from user where delete_flag=0 and user_name=#{name}")User selectByName(String name);
}

BlogMapper类:

@Mapper
public interface BlogMapper {@Select("select * from blog where delete_flag=0")List<Blog> selectAllBlog();@Select("select * from blog where delete_flag=0 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 namespace="com.example.springblog.mapper.BlogMapper"><update id="updateBlog">update blog<set><if test="title!=null">title=#{title},</if><if test="content!=null">content=#{content},</if><if test="userId!=null">user_id=#{userId},</if><if test="deleteFlag!=null">delete_flag=#{deleteFlag},</if></set>where id=#{id}</update>
</mapper>

5.项目模块

在这里插入图片描述

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 result=new Result();result.setCode(code);result.setMsg(msg);result.setData("");return result;}public static  Result fail(Integer code,String msg,Object data) {Result result=new Result();result.setCode(code);result.setMsg(msg);result.setData(data);return result;}/*** 业务处理成功* @param data* @return*/public static  Result success(Object data) {Result result=new Result();result.setCode(200);result.setMsg("");result.setData(data);return result;}public static  Result success(String msg,Object data) {Result result=new 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 objectMapper=new 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 List<Blog> getBlogList(){return blogService.selectAllBlog();}
}

在BlogService 中添加⽅法:

public class BlogService {@Autowiredprivate BlogMapper blogMapper;public List<Blog> selectAllBlog(){return blogMapper.selectAllBlog();}
}

部署程序, 验证服务器是否能正确返回数据 (使⽤ URL http://127.0.0.1:8080/blog/getlist 即可)

实现客户端代码

修改 blog_list.html, 删除之前写死的博客内容, 并新增js 代码处理 ajax 请求.

    <script src="./js/jquery.min.js"></script><script src="./js/common.js"></script><script>$.ajax({type:"get",url:"/blog/getlist",success:function(result){if(result.code==200 && result.data!=null && result.data.length>0){var blogs=result.data;var finalHtml="";for(var blog of blogs){finalHtml += '<div class="blog">';finalHtml += '<div class="title">'+blog.title+'</div>'finalHtml += '<div class="date">'+blog.createTime+'</div>'finalHtml += '<div class="desc">'+blog.content+'</div>'finalHtml += '<a class="detail" href="blog_detail.html?blogId='+blog.id+'">查看全文&gt;&gt;</a>'finalHtml += '</div>'}$(".right").html(finalHtml);}},error:function(error){console.log(error);if(error!=null && error.status==401){//用户未登录location.assign("blog_login.html");}}});var url="/user/getUserInfo";getUserInfo(url);</script>

7.2实现博客详情

⽬前点击博客列表⻚的 “查看全⽂” , 能进⼊博客详情⻚, 但是这个博客详情⻚是写死的内容. 我们期望能够根据当前的 博客 id 从服务器动态获取博客内容.

约定前后端交互接口

/blog/getBlogDetail?blogId=1
[响应]
{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 blog=blogService.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/getBlogDetail"+location.search,success:function(result){if(result.code==200 && result.data!=null){var blog=result.data;$(".title").text(blog.title);$(".date").text(blog.createTime);editormd.markdownToHTML("content", {markdown: blog.content ,});//$(".detail").text(blog.content);if(blog.loginUser==1){var html="";html+= '<button onclick="window.location.href=\'blog_update.html?blogId='+blog.id+'\'">编辑</button>';html+='<button onclick="deleteBlog()">删除</button>';$(".operating").html(html);}}},error:function(error){consolo.log(error);if(error!=null && error.status==401){//用户未登录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.code==200 && result.data!=null){var user=result.data;$(".left .card h3").text(user.userName);$(".left .card a").attr("href",user.githubUrl);}}});
}

7.3实现登录

  • 登陆⻚⾯提供⼀个 form 表单, 通过 form 的⽅式把⽤户名密码提交给服务器.

  • 服务器端验证⽤户名密码是否正确. 如果密码正确,

  • 则在服务器端创建 Session , 并把 sessionId 通过 Cookie 返回给浏览器

约定前后端交互接口

[请求]
/user/login
username=test&password=123
[响应]
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 user=userService.selectByName(username);if(user==null || !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"></script><script>function login(){$.ajax({type:"post",url:"/user/login",data:{username:$("#userName").val(),password:$("#password").val()},success:function(result){if(result.code==200){location.href="blog_list.html";return;}else if(result.code<0 && result.msg!=''){alert(result.msg);return;}},error:{}});}</script>

7.4实现强制要求登录

当⽤户访问 博客列表⻚ 和 博客详情⻚ 时, 如果⽤户当前尚未登陆, 就⾃动跳转到登陆⻚⾯.

添加拦截器

登录拦截器:

@Component
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {HttpSession session=request.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 List<String> 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.status==401){//用户未登录location.assign("blog_login.html");}}

2.修改 blog_list.html

  • 访问⻚⾯时, 添加失败处理代码
  • 使⽤ location.assign 进⾏⻚⾯跳转.
            error:function(error){consolo.log(error);if(error!=null && error.status==401){//用户未登录location.assign(blog_login.html);}}

7.5实现显示用户信息

  • 如果当前⻚⾯是博客列表⻚, 则显示当前登陆⽤户的信息.
  • 如果当前⻚⾯是博客详情⻚, 则显示该博客的作者⽤户信息.

约定前后端交互接口

在博客列表⻚, 获取当前登陆的⽤户的⽤户信息.

[请求]
/user/getUserInfo
[响应]
{
userId: 1,
username: test...
}

在博客详情⻚, 获取当前⽂章作者的⽤户信息

[请求]
/user/getAuthorInfo?blogId=1
[响应]
{
userId: 1,
username: test
}

实现服务器代码

在 UserController 中添加⽅法:

    /*** 获取登录用户信息* @return*/@RequestMapping("/getUserInfo")public Result getUserInfo(HttpSession session){if(session==null || 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(blogId==null || blogId<=0){return Result.fail(-1,"博客不存在~");}User user=userService.selectAuthorByBlogId(blogId);return Result.success(user);}

在UserService 中添加⽅法:

    public User selectAuthorByBlogId(Integer blogId){User user=null;Blog blog=blogMapper.selectBlogById(blogId);if(blog!=null && blog.getUserId()>0){user=userMapper.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 class="nav-span" href="#" onclick="logout()">注销</a>

在common.js中添加logout⽅法:

function logout(){$.ajax({type:"get",url:"/user/logout",success:function(result){if(result!=null && result.data==true){location.href="blog_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(user==null || user.getId()<=0){return Result.fail(-1,"用户不存在");}try{Blog blog=new 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.code==200 && result.data==true){location.href="blog_list.html";}else{alert(result.msg);}},error:function(error){if(error!=null && error.status==401){alert("请先登录!!!");}}});});

7.8实现删除/编辑博客

进⼊⽤户详情⻚时, 如果当前登陆⽤户正是⽂章作者, 则在导航栏中显示 “删除” 按钮, ⽤户点击时则删除该⽂章.

需要实现两件事:

  • 判定当前博客详情⻚中是否要显示 删除 按钮
  • 实现删除逻辑.

约定前后端交互接口

编辑博客

[请求]
/blog?BlogId=1
[响应]
{blogId: 1,title: "第⼀篇博客",content: "博客正⽂",userId: 1,postTime: "2021-07-07 12:00:00",loginUser: 1
}

删除博客

[请求]
GET /blog/delete?blogId=1
[响应]
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(blogId==null){return Result.fail(-1,"博客不存在~");}Blog blog=new 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.code==200 && result.data==true){location.href="blog_list.html";}else{alert(result.msg);}},eeror:function(error){if(error!=null && error.status==401){//用户未登录location.assign("blog_login.html");}}});}

编辑博客:

        //获取博客的详细内容,并且反应到页面上$.ajax({type:"get",url:"/blog/getBlogDetail" + location.search,success:function(result){if(result!=null && result.code==200 && result.data!=null){var blog=result.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.status==401){//用户未登录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.code==200 && result.data==true){location.href="blog_list.html";}else if(result!=null){alert(result.msg);}}});});</script>

7.9实现加密加盐

加密工具类

使用md5进行密码加密:

public class SecurityUtils {/*** 加密* 根据明文,返回密文(salt+加密后的密文)* @return*/public static String encry(String inputPassword){//生成盐值String salt= UUID.randomUUID().toString().replace("-","");//md5加密(明文+盐值)String password= DigestUtils.md5DigestAsHex((inputPassword+salt).getBytes());return salt+password;}/*** 验证密码是否正确* @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 salt=finalPassword.substring(0,32);String password= DigestUtils.md5DigestAsHex((inputPassword+salt).getBytes());return (salt+password).equals(finalPassword);}
}

使用

        //验证密码User user=userService.selectByName(username);if(user==null || !SecurityUtils.decrypt(password,user.getPassword())){return Result.fail(-2,"用户名密码错误");}

修改数据库密码

使⽤测试类给密码123456⽣成密⽂:
e2377426880545d287b97ee294fc30ea6d6f289424b95a2b2d7f8971216e39b7

执行SQL:

update user set password='e2377426880545d287b97ee294fc30ea6d6f289424b95a2b2
d7f8971216e39b7' where id=1;

相关文章:

【Spring练习项目】博客系统

目录 1.项目展示2.项目结构设计3.项目功能设计4 数据库准备4.1 建表4.2 DB相关数据 5.项目模块6.添加项目公共模块6.1 common6.2 实现前端界面 7.功能实现7.1实现博客列表约定前后端交互接口实现服务器代码实现客户端代码 7.2实现博客详情约定前后端交互接口实现服务器代码实现…...

神策新一代分析引擎架构演进

近日&#xff0c;神策数据已经推出全新的神策分析 2.5 版本&#xff0c;该版本支持分析模型与外部数据的融合性接入&#xff0c;构建全域数据融合模型&#xff0c;实现从用户到经营的全链路、全场景分析。新版本的神策分析能够为企业提供更全面、更有效的市场信息和经营策略&am…...

Systemui的介绍以及与普通应用的差异

一.SystemUI的介绍 简介 SystemUI是Android操作系统的一个关键组件&#xff0c;主要负责管理和提供用户界面的核心元素&#xff0c;如状态栏、导航栏和锁屏界面等。从下面两点出发了解SystemUI的特性&#xff1a; 一下就是systemui的部分界面&#xff0c;还包括锁屏界面&…...

群狼调研—产业园物业满意度的调研对象

群狼调研**&#xff08;湖南物业满意度调查&#xff09;**受顾客委托开展产业园物业满意度调查&#xff0c;产业园物业满意度调研对象&#xff1a;产业园物业满意度调研的对象主要是产业园内的企业和租户。这包括在产业园内租用场地或办公空间的企业、工厂、工作室等&#xff0…...

想参加华为杯竞赛、高教社杯和数学建模国赛的小伙伴看过来

本文目录 ⭐ 赛事介绍⭐ 辅导比赛 ⭐ 赛事介绍 ⭐ 参赛好处 ⭐ 辅导比赛 ⭐ 写在最后 ⭐ 赛事介绍 华为杯全国研究生数学建模竞赛是由华为公司主办的一项面向全国研究生的数学建模竞赛。该竞赛旨在通过实际问题的建模和解决&#xff0c;培养研究生的创新能力和团队合作精神&a…...

ELK 企业级日志分析系统

目录 ELK 概述 1、ELK 简介 2、为什么要使用 ELK&#xff1a; 3、完整日志系统基本特征 4、ELK 的工作原理&#xff1a; 总结 ELK Elasticsearch 集群部署&#xff08;在Node1、Node2节点上操作&#xff09; 1&#xff0e;环境准备 2&#xff0e;部署 Elasticsearch …...

PyTorch Lightning教程六:优化代码

有时候模型训练很慢&#xff0c;代码写得冗长之后&#xff0c;没法诶个检查到底那块出现了占用了时空间&#xff0c;本节通过利用Lightning的一些方法&#xff0c;检查分析是那块代码出现了问题&#xff0c;从而来进一步指导和优化代码 本节主要基于性能分析方法&#xff0c;通…...

基于linux下的高并发服务器开发(第四章)- 多线程实现并发服务器

>>了解文件描述符 文件描述符分为两类&#xff0c;一类是用于监听的&#xff0c;一类是用于通信的&#xff0c;在服务器端既有监听的&#xff0c;又有通信的。而且在服务器端只有一个用于监听的文件描述符&#xff0c;用于通信的文件描述符是有n个。和多少个客户端建立了…...

YUV 色彩空间中U 和 V 分量的范围

在YUV色彩空间中&#xff0c;U分量和V分量的范围通常是-0.5到0.5。 具体来说&#xff0c;对于标准的YUV色彩空间&#xff08;例如YUV420&#xff09;&#xff0c;取样是按照4:2:0的比例进行的。这意味着在水平和垂直方向上&#xff0c;U和V分量的取样比Y分量少一半。因此&…...

【云原生】K8S二进制搭建一

目录 一、环境部署1.1操作系统初始化 二、部署etcd集群2.1 准备签发证书环境在 master01 节点上操作在 node01与02 节点上操作 三、部署docker引擎四、部署 Master 组件4.1在 master01 节点上操 五、部署Worker Node组件 一、环境部署 集群IP组件k8s集群master01192.168.243.1…...

自动化应用杂志自动化应用杂志社自动化应用编辑部2023年第11期目录

数据处理与人工智能 大数据视域下无轨设备全生命周期健康管理技术的研究 赖凡; 1-3 三维激光扫描结合无人机倾斜摄影在街区改造测绘中的技术应用 张睿; 4-6 井上变电站巡检机器人的设计与应用 刘芳; 7-9 《自动化应用》投稿邮箱&#xff1a;cnqikantg126.com 基于机…...

Tensorflow2-初识

TensorFlow2是一个深度学习框架&#xff0c;可以理解为一个工具&#xff0c;有谷歌的全力支持&#xff0c;具有易用、灵活、可扩展、性能优越、良好的社区资源等优点。 1、环境的搭建 1.1 Anaconda3的安装 https://www.anaconda.com/ Python全家桶&#xff0c;包括Python环境和…...

idea-常用插件汇总

idea-常用插件汇总 码云插件 这个插件是码云提供的ps-码云是国内的一款类似github的代码托管工具。 Lombok Lombok是一个通用Java类库&#xff0c;能自动插入编辑器并构建工具&#xff0c;简化Java开发。通过添加注解的方式&#xff0c;不需要为类编写getter或setter等方法…...

【Kubernetes】

目录 一、Kubernetes 概述1、K8S 是什么&#xff1f;2、为什么要用 K8S?3、Kubernetes 集群架构与组件 二、核心组件1、Master 组件2、Node 组件3、K8S创建Pod的工作流程&#xff1f;&#xff08;重点&#xff09;4、K8S资源对象&#xff08;重点&#xff09;5、Kubernetes 核…...

使用逗号方式、JOIN方式和USING方式进行多表连接查询时哪个方式更好

在Oracle中&#xff0c;使用逗号方式、JOIN方式和USING方式进行多表连接查询时&#xff0c;性能上没有明显的差异。这是因为Oracle优化器会自动将这些语法转换为内部执行计划&#xff0c;以获得最佳的查询性能。 逗号方式&#xff1a;逗号方式是最简单的连接语法&#xff0c;它…...

MacOS上用docker运行mongo及mongo-express

MongoDB简介 MongoDB 是一个基于分布式文件存储的数据库。由 C 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。 MongoDB 是一个介于关系数据库和非关系数据库之间的产品&#xff0c;是非关系数据库当中功能最丰富&#xff0c;最像关系数据库的。 前提 要求…...

海康视频插件VideoWebPlugin在vue中的实现

一,将js文件放在public文件下 二,在index中全局引入 三.在视频页面写方法,创建实例,初始化,我写的是1*4屏的 <template><!--视频窗口展示--><div idplayWnd classNameplayWnd refplayWnd styleleft: 0; bottom: 0;height: 902px;width: 60vw></div>&…...

swagger相关问题

swagger相关问题 swagger版本为&#xff1a; <dependency><groupId>com.github.xiaoymin</groupId><artifactId>swagger-bootstrap-ui</artifactId><version>1.9.6</version> </dependency> <dependency><groupId&…...

Scala关键字lazy的见解

Scala中使用关键字lazy来定义惰性变量&#xff0c;实现延迟加载(懒加载)。 惰性变量只能是不可变变量&#xff0c;并且只有在调用惰性变量时&#xff0c;才会去实例化这个变量。 在Java中&#xff0c;要实现延迟加载(懒加载)&#xff0c;需要自己手动实现。一般的做法是这样的…...

sql分类 DDL、DML、DCL

DDL &#xff08;Data Definition Language 数据定义语言) 这些语句定了不同的数据库、表、视图、索引等数据库对象&#xff0c;还可以用来创建、删除、修改数据库和数据表的结构 如: CREATE \ DROP \ ALTER \ RENAME \ TRUNCATE 等 DML&#xff08;Data Manipulation Langua…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

渲染学进阶内容——模型

最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用

文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么&#xff1f;1.1.2 感知机的工作原理 1.2 感知机的简单应用&#xff1a;基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...

CSS | transition 和 transform的用处和区别

省流总结&#xff1a; transform用于变换/变形&#xff0c;transition是动画控制器 transform 用来对元素进行变形&#xff0c;常见的操作如下&#xff0c;它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)

题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...