Java项目---图片服务器

图片服务器--->服务器(图床)

  • 核心功能:上传图片、展示图片等

比如:编写博客时我们会插入图片,本质上是往文章中放了一个链接(URL),这个URL资源在另外一个服务器上。

  • 核心知识点:

(1)简单的Web服务器设计开发能力(Servlet)

Web服务器--->HTTP服务器

Servlet是Tomcat这个HTTP服务器所提供的一组编程接口

(2)使用数据库来进行存储(MySQL)JDBC操作MySql

(3)数据库设计(根据实际场景设计数据库表结构)

(4)前后端交互的API的设计(基于HTTP协议)

(5)认识JSON数据格式,学习使用Java中的Gson这个库操作JSON数据

(6)学习测试一个HTTP服务器(Postman)

(7)使用HTML CSS JavaScript技术构建一个简单的网页

一、服务器设计

1.数据库设计

数据库中存储的是图片的属性(元信息);图片正文是以文件的形式直接存在磁盘上的;数据库中就记录一个path,path就对应到磁盘上的一个文件。

  • md5:图片的md5校验和(字符串哈希算法,哈希表)
  • 校验和:通过一个更短的字符串,来验证整体数据是否正确,短的字符串是根据原串内容通过一定的规则来计算出来的。

2.服务器API设计(前后端交互接口设计)

(1)JSON

一种数据组织的格式,格式键值对的结构。JSON只是一种数据格式,和编程语言无关。

JSON结构展示:

{"name":"曹操","skill1":"剑气","skill2":"三段跳","skill3":"加攻击和吸血","skill4":"加攻速",
}

使用JSON完成数据的序列化方便完成网络传输。

(2)Gson:google搞得一个开源的JSON解析库

(3)文件上传操作在HTML中是如何完成的(用到form表单)

文件上传在HTTP协议中是如何完成的

  • 开始设计前后端交互API

1>新增图片

请求:使用POST,POST到/image这个路径上

Content-Type:multipart/from-data;

(正文内容包含图片自身的一些信息)

(图片正文的二进制内容)

响应:(1)上传成功

①HTTP/1.1 200 OK 

②{

        "ok":true,

}

(2)上传失败

①HTTP/1.1 200 OK 

②{

        "ok":false,

        "reason":"具体的失败原因"

}

2>查看所有图片信息(数据库里面存的属性信息)

请求:GET/image

响应:①成功:HTTP/1.1 200 OK

成功返回的数组:

[

    {

          imageid:1,

          imageName:"1.png",

          contentType:"image/png",

          size:1000,

          uploadTime:"20200222",

          path:"./data/1.png",

          md5:"11223344",

     },

    {

         .........

    }

]

②:失败:HTTP/1.1 200 OK

失败返回的数组:

[](返回一个空数组)

3>查看指定图片属性

请求:GET/image?imageid=[具体的数值]

响应:

①:成功

HTTP/1.1 200 OK

{

          imageid:1,

          imageName:"1.png",

          contentType:"image/png",

          size:1000,

          uploadTime:"20200222",

          path:"./data/1.png",

          md5:"11223344",

}

②:失败

HTTP/1.1 200 OK

{

       ok:false,

       reason:"具体出错的原因"

}

4>删除指定图片

请求:DELETE/image?image=[具体的图片id]

响应:

①:成功

HTTP/1.1 200 OK

{

       ok:true,

}

②:失败

HTTP/1.1 200 OK

{

        ok:false,

        reason:"具体的出错原因",

}

服务器实现代码的时候就可以判断方法,如果是DELETE方法就执行删除操作

删除不一定非要用DELETE方法,也可以用:GET/image?image=xxx&delete=1

5>查看指定图片内容

请求:GET/imageShow?imageid=[具体的图片id]

响应:

①:成功:

HTTP/1.1 200 OK

Content-Tpye:image/png

[图片的二进制内容]

②:失败

HTTP/1.1 200 OK

{

      ok:false,

      reason:"[具体的出错原因]"

}

3.源码的开发

1.数据库操作

先创建DBUtil,封装一下获取数据库链接的过程

dao--->数据访问层,这里面的类围绕着数据操作展开

ctrl+alt+t--->选中一些代码,在这些代码外面包上一些其他代码

二、实现代码

package dao;public class Image {private int imageId;private String imageName;private int size;private String uploadTime;private String contentType;private String path;private String md5;public int getImageId() {return imageId;}public void setImageId(int imageId) {this.imageId = imageId;}public String getImageName() {return imageName;}public void setImageName(String imageName) {this.imageName = imageName;}public int getSize() {return size;}public void setSize(int size) {this.size = size;}public String getUploadTime() {return uploadTime;}public void setUploadTime(String uploadTime) {this.uploadTime = uploadTime;}public String getContentType() {return contentType;}public void setContentType(String contentType) {this.contentType = contentType;}public String getPath() {return path;}public void setPath(String path) {this.path = path;}public String getMd5() {return md5;}public void setMd5(String md5) {this.md5 = md5;}@Overridepublic String toString() {return "Image{" +"imageId=" + imageId +", imageName='" + imageName + '\'' +", size=" + size +", uploadTime='" + uploadTime + '\'' +", contentType='" + contentType + '\'' +", path='" + path + '\'' +", md5='" + md5 + '\'' +'}';}
}

1.封装数据库操作(DAO层)

DBUtil封装获取数据库链接的操作;

Image对应到一个图片对象(包含图片的相关属性);

ImageDao Image对象管理器,借助这个类完成Image对象的增删改查操作;

ImageDao有一个selectAll方法,查找出所有数据库中的数据,但是如果有上亿条数据这样查找很低效,更科学的方法可以指定一些其他筛选条件(分页);

  • 出现异常之后的具体措施:
  • 1.当前接触过的大部分都是打印调用栈
  • 2.让程序直接终止
  • 3.通过监控报警通知程序员

(JAR:类似于zip这样的压缩包,一大堆.class文件放在一起,打包成一个文件)

ImageDao:
package dao;
import common.JavaImageServerException;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;public class ImageDao {//把image对象插入到数据库中public void insert(Image image)  {//1.获取数据库连接Connection connection=DBUtil.getConnection();//2.创建并拼装SQL语句String sql="insert into image_table values(null,?,?,?,?,?)";PreparedStatement statement=null;try {statement=connection.prepareStatement(sql);statement.setString(1, image.getImageName());statement.setInt(2,image.getSize());statement.setString(3,image.getUploadTime());statement.setString(4,image.getContentType());statement.setString(5,image.getPath());statement.setString(6,image.getMd5());//3.执行SQL语句int ret=statement.executeUpdate();if(ret!=1){//程序出现问题,抛出一个异常throw new JavaImageServerException("插入大户巨款出错");}} catch (SQLException e) {e.printStackTrace();}catch (JavaImageServerException e){e.printStackTrace();}finally{//4.关闭连接和statement对象DBUtil.close(connection,statement,null);}}//查找数据库中的所有图片的信息public List<Image> selectAll(){List<Image> images=new ArrayList<>();//1、获取数据库连接Connection connection=DBUtil.getConnection();//2.构造SQL语句String  sql="select * from image_table";PreparedStatement statement=null;ResultSet resultSet=null;try {//3.执行sql语句statement=connection.prepareStatement(sql);resultSet=statement.executeQuery();//4.处理结果集while(resultSet.next()){Image image=new Image();image.setImageId(resultSet.getInt("imageId"));image.setImageName(resultSet.getString("imageName"));image.setSize(resultSet.getInt("size"));image.setUploadTime(resultSet.getString("uploadTime"));image.setContentType(resultSet.getString("contentType"));image.setPath(resultSet.getString("path"));image.setMd5(resultSet.getString("md5"));images.add(image);}return images;}catch (SQLException e){e.printStackTrace();}finally{//关闭连接DBUtil.close(connection,statement,resultSet);}return null;}//根据imageId查找指定的图片信息public Image selectOne(int imageId){//1.获取数据库连接Connection connection=DBUtil.getConnection();//2.构造SQL语句String  sql="select * from image_table where imageId = ?";PreparedStatement statement=null;ResultSet resultSet=null;//3.执行SQL语句try {statement=connection.prepareStatement(sql);statement.setInt(1,imageId);resultSet =statement.executeQuery();//4.处理结果集if(resultSet.next()){Image image=new Image();image.setImageId(resultSet.getInt("imageId"));image.setImageName(resultSet.getString("imageName"));image.setSize(resultSet.getInt("size"));image.setUploadTime(resultSet.getString("uploadTime"));image.setContentType(resultSet.getString("contentType"));image.setPath(resultSet.getString("path"));image.setMd5(resultSet.getString("md5"));return image;}} catch (SQLException e) {e.printStackTrace();}finally{//5.关闭连接DBUtil.close(connection,statement,resultSet);}return null;}//根据imageId删除指定图片public void delete(int imageId){//1、获取数据库连接Connection connection=DBUtil.getConnection();//2.拼装SQL语句String  sql="delete * from image_table where imageId = ?";PreparedStatement statement=null;
//        ResultSet resultSet=null;//3.执行SQL语句try {statement=connection.prepareStatement(sql);statement.setInt(1,imageId);int ret =statement.executeUpdate();//4.处理结果集if(ret!=1){throw new JavaImageServerException("删除数据库操作失败")}} catch (SQLException | JavaImageServerException e) {e.printStackTrace();}finally{//4.关闭连接DBUtil.close(connection,statement,null);}}public static void main(String[] args) {//用于进行简单的测试//1.测试插入数据
//        Image image=new Image();
//        image.setImageName("1.png");
//        image.setSize(100);
//        image.setUploadTime("2023");
//        image.setContentType("image/png");
//        image.setPath("./date/1.png");
//        image.setMd5("112233");
//        ImageDao imageDao=new ImageDao();
//        imageDao.insert(image);//2.测试查找所有图片信息
//        ImageDao imageDao=new ImageDao();
//        List<Image> images=imageDao.selectAll();
//        System.out.println(images);//3.测试查找指定图片信息ImageDao imageDao=new ImageDao();Image image=imageDao.selectOne(1);System.out.println(image);//4.测试查找指定图片信息ImageDao imageDao=new ImageDao();imageDao.delete(1);}
}

2.基于Servlet来搭建服务器

(1)安装Servlet

(2)创建一个类,继承HttpServlet父类(重写父类中的一些重要方法)

如果服务器收到的是GET方法,就会自动调用HttpServlet的doGet方法;

如果服务器收到的是POST方法,就会自动调用HttpServlet的doPost方法;

如果服务器收到的是DELETE方法,就会自动调用HttpServlet的doDelete方法;

HttpServletRequest req--->请求(方法、url、各种header、body)
HttpServletResponse resp--->响应(状态码、各种header、body)

给网页上显示一个hello world,修改请求还是修改响应--->修改响应;当代码写完之后,还需要修改webapp/WEB-INF/web.xml把新创建的Servlet注册进去:

<?xml version ="1.0" encoding =" UTF -8"?><web-app xmlns ="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation ="http://xmlns.jcp.org/xm1/ns/javaeehttp://xmIns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"version ="3.1"metadata-complete =" true "><servlet><servlet-name>Hello</servlet-name ><servlet-class>HelloServlet </servlet-class></ servlet ><servlet-mapping ><servlet-name> Hello </ servlet-name><url-pattern >/ hello-servlet </url-pattern></ servlet-mapping>
</web-app>

<servlet>标签-->>告诉Tomcat当前这个servlet对应到代码中的那个类

<servlet-mapping >标签-->>告诉Tomcat当前这个servlet对应到的URL的path是什么

三、基于Servlet搭建好项目的后端部分

部署:

(1)使用maven打包(war) maven package

(2)把war包拷贝到tomcat的webapps目录中

部署完之后,就可以在浏览器(http客户端)中访问服务器了。

http://47.98.116.42:8080/java_image_server/image

java_image_server----->war包的名字;image---->web.xml配置的内容

  • ImageServlet:

(1)上传图片

需要用到第三方库

对于JSON格式的响应,需要把content-type设定成指定格式

如果有两个图片,内容不同,但是名字相同,此时会出现上传失败的情况;应该让每次上传图片对应的路径都不相同(在路径上加上时间戳)

(2)查看所有图片信息

(3)查看所有指定图片信息

(4)删除指定图片

代码:

package api;import dao.Image;
import dao.ImageDao;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;public class ImageServlet extends HttpServlet {//查看图片属性,既能查看所有,也能查看指定@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws SecurityException, ServletException, IOException {//考虑到查看所有图片属性和查看指定图片属性//通过是否URL中带有imageId参数来进行区分//存在imageId查看指定图片属性,否则就查看所有图片属性//例如:URL/image?imageId=100//imageId的值就是"100"//如果URL中不存在imageId那么返回nullString imageId =req.getParameter("imageId");if(imageId==null || imageId.equals("")){//查看所有图片属性selectAll(req,resp);}else{//查看指定图片selectOne(imageId,resp);}//        //req对象中包含了请求中的所有信息
//        //resp对象要生成的结果就放到里面去
//        //当前这个doGet方法就是要根据请求,生成响应
//        resp.setStatus(200);
//        //这个代码就是把hello这个字符串放到http响应的body中了
//        resp.getWriter().write("hello");}private void selectAll(HttpServletRequest req,HttpServletResponse resp){//1.创建一个ImageDao对象,并查找数据库ImageDao imageDao=new ImageDao();List<Image> images=imageDao.selectAll();//2.把查找到的结果转成JSON格式的字符串,并且写回到resp对象Gson gson=new GsonBuilder().create();//jsonData就是一个json格式的字符串,和之前约定的格式是一样的String jsonDate=gson.toJson(images);resp.getWriter().write(jsonDate);}private void selectOne(String imageId,HttpServletResponse resp){resp.setContentType("application/json;charset=utf-8");//1.创建ImageDao对象ImageDao imageDao=new ImageDao();Image image=imageDao.selectOne(Integer.parseInt(imageId));//2.使用gson把查看到的数据转成json格式,并写回给响应对象Gson gson=new GsonBuilder().create;String jsonData=gson.toJson(image);resp.getWriter().write(jsonData);}//上传图片@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1.获取图片的属性信息,并且存入数据库//1>需要创建一个factory对象,和upload对象,为了获取到图片属性做的准备工作FileItemFactory factory=new DiskFileItemFactory();ServletFileUpload upload=new ServletFileUpload(factory);//2>通过upload对象进一步解析请求List<FileItem> items=null;try{items=upload.paresRequest(req); }catch(FileUploadException e){//出现异常说明解析出错e.printStackTrace();//告诉客户端出现的具体的错误是什么resp.setContentType("application/json;charset=utf-8");resp.getWriter().write("{\"ok\":false,\"reason\",\"请求解析失败\"}");return;}//3>把FileItem中的属性提取出来,转换成Image对象,才能存到数据库中//当前只考虑一张图片的情况FileItem fileItem=item.get(0);Image image=new Image();image.setImageName(fileItem.getName());image.setSize((int)fileItem.getSize());//手动获取一下当前日期,并转换成格式化日期SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyyMMdd");image.setUploadTime(simpleDateFormat.format(new Date()));image.setContentType(fileItem.getContentType());//自己构造一个路径来保存,引入时间戳为了让文件能够唯一image.setPath("./image/"+System.currentTimeMillis()+"_"+image.getImageName());//TODO MD5(先不管,写死)image.setMD5("112233");//存到数据库中ImageDao imageDao=new ImageDao();imageDao.insert(image);//2.获取图片的内容信息,并且写入磁盘文件File file=new File(image.getPath());try{fileItem.write(file);}catch(Exception e){e.printStackTrace();resp.setContentType("application/json;charset=utf-8");resp.getWriter().write("{\"ok\":false,\"reason\",\"写磁盘失败\"}");return;}//3.给客户端返回一个结果数据//resp.setContentType("application/json;charset=utf-8");// resp.getWriter().write("{\"ok\":true}");resp.sendRedirect("index.html");}//删除指定图片@Overrideprotected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("application/json;charset=utf-8");//1.先获取到请求中的imageIdString imageId=req.getParameter("imageId");if(imageId==null || imageId.equals("")){resp.setStatus(200);resp.getWriter().write("{\"ok\":false,\"reason\",\"解析请求失败\"}");return;}//2.传教imageDao对象,查看到该图片对象对应的相关属性(为了知道这个图片对应的文件路径)ImageDao imageDao=new ImageDao();Image image=imageDao.selectOne(Integer.parseInt(ImageId));if(image==null){//此时请求中传入的id在数据库中不存在resp.setStatus(200);resp.getWriter().write("{\"ok\":false,\"reason\",\"image在数据库中不存在\"}");return;}//3.删除数据库中的记录imageDao.delete(Integer.parseInt(imageId));//4.删除本地磁盘文件File fule=new File(image.getPath());file.delete();resp.setStatus(200);resp.getWriter().write("{\"ok\":true}");}
}
  • ImageShowServlet

代码:

package api;import dao.Image;
import dao.ImageDao;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;public class ImageShowServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1.解析出imageIdString imageId=req.getParameter("imageId");if(imageId==null || imageId.equals("")){resp.setContentType("application/json;charset=utf-8");resp.getWriter().write("{\"ok\":false,\"reason\",\"imageId解析失败\"}");return;}//2.根据imageId查找数据库,得到对应的图片属性信息(需要知道图片存储的路径ImageDao imageDao=new ImageDao();Image image=imageDao.selectOne(Integer.parseInt(ImageId));//3.根据路径打开文件,读取其中的内容,写入到响应对象中resp.setContentType(image.getContentType());File file=new File(image.getPath());//由于图片是二进制文件,应该使用字节流的方式读取文件OutputStream outputStream=resp.getOutputStream();FileInputStream fileInputStream=new FileInputStream(file);byte[] buffer=new byte[1024];while(true){int len=fileInputStream.read(buffer);if(len==-1){//文件读取结束break;}//此时语句读到一部分数据,放到buffer里面,把buffer中的内容写到响应对象中outputStream.write(buffer);}fileInputStream.close();outputStream.close();}
}

四、实现前端页面(展示图片,增删操作)、

  • 实现前端页面主要应用的技术:

(1)HTML-->网页的骨架;

(2)CSS--->描述网页上组件的样式(位置、大小、颜色等);

(3)JavaScript:描述前端页面上的一些动作(和用户具体交互的行为)

(HTML、CSS、JavaScript可以写到一个HTML文件中,也可以分开写)

把网页上显示的这些预览图片替换成服务器上保存的图片,img标签中scr改成服务器上存在的图片的url就可以了;

需要获取到服务器上所有图片的url(ImageServlet),需要通过JS先获取到所有图片的属性,再分别加载每一个图片;使用JS来完成。

  • 主流的前端框架

(1)Vue

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> 
var app = new Vue({ el: '#app', data: { message: 'Hello Vue!' } 
})

(2)React(facebook)

(3)Auglar(google)

JS中变量类型都是在初始化的时候自动推导的

var声明这是一个变量;

Vue所做的最核心的工作,把页面显示的内容和JS中的代码相互关联到一起;

修改js中的变量就能很方便的影响的页面的显示情况。

var app = new Vue({ el:'#app', data: { images: [ { imageId: 1, imageName: "1.png", contentType: "image/png", md5: "aabbccdd", }, { imageId: 2, imageName: "2.png", contentType: "image/png", md5: "aabbccdd", } } }, methods: {}, 
});

Vue对象中构造一组写死的数据,先去借助这组数据来渲染页面

Vue中的命令:

1>v-for--->>循环访问一个数据

2>v-bind-->>把数据绑定到html标签上的某个属性

<div class="am-g am-g-fixed blog-fixed blog-content"> <figure data-am-widget="figure" class="am am-figure am-figure-default " data-am-figure="
{ pureview: 'true' }"> <div id="container"> <div v-for="image in images"> <img v-bind:src=" 'imageShow?imageId=' + image.imageId " style="height:200px;width:200px"> <h3>{{image.imageName}}</h3> </div> </div> </figure> 
</div>

3>v-on-->>绑定某种事件的处理函数(点击鼠标、双击、右键等)

remove(image_id) { $.ajax({ url:"image?image_id=" + image_id, type:"delete", context: this, success: function(data, status) { this.getImages(); alert("删除成功"); } }) 
}

如果是在标签内部使用Vue对象中的数据,就需要使用插值表达式;

如果是在标签属性中使用Vue对象中的数据,步需要使用插值表达式,但要搭配Vue的命令;

images这个数组里面的内容是写死的,接下里通过浏览器中JS代码请求服务器,获取到服务器上都有那些图片,把这个数据作为Vue渲染的依据(Vue对象中的images数组)

getImages() { $.ajax({ url: "image", type: "get", context: this, success: function(data, status) { this.images = data; // 这个代码用来触发 resize 事件. $("#app").resize(); } }) 
},

ajax:JSz中构造HTTP请求发送给服务器的一种实现方式

原来页面的渲染过程:

1>先加载图片

2>再根据图片大小设定图片的位置,设定显示图片的空间大小

使用ajax来渲染:

1>页面先尝试获取页面的大小,并设定显示图片的空间(当前图片还没有获取到,不知道图片的大小)

2>通过ajax获取图片内容

改进上传操作,上传成功之后,自动跳转到主页index.html  HTTP重定向

实现删除图片,浏览器给服务器发送一个DELETE/image?imageId=xxx这样的请求就可以了(ajax完成)

拓展:

(1)简单的防盗链机制(通过一定的机制来限制其他人来使用图片)

可以判定当前请求的referer爱段(HTTP请求协议中的header部分),是不是在我们代码指定的白名单中,如果是,就可以访问。

referer-->表示当前请求的上一个页面的地址

再代码中用一个hashSet存一下允许访问的Referer就可以了,展示图片的时候判断一下是否再hashSet中存在即可。

(2)优化磁盘空间

应用到MD5,如果两个图片内容完全一样,就在磁盘上存一份就可以了。通过MD5可以判断两个图片内容是否一样。

图片文件虽然是二进制数据,但是本质上也是字符串,针对图片内容计算MD5。

如果两个图片内容相同,得到的MD5一定是相同的,反之,近似认为MD5相同,原图内容一定相同。

理论上使是有可能两个图片的内容不同,MD5相同,但实际上出现概率极低(MD5自身算法设计上引起的特性)

  • MD5的特点:
  • (1)不管原串多长,得到的MD5值是一个固定长度;
  • (2)原串哪怕变动一点点(一个字节),MD5值就会变动很大;
  • (3)计算MD5值的过程很简单,但是通过MD5值无法推测出原字符的;

实现思路:

上传图片的时候,先判定新图片的MD5在数据库中是否存在,如果已经存在了,就不用把图片内容写到磁盘上,如果不存在就写到磁盘上。

1>该上传代码的逻辑,磁盘文件名用md5值来表示

2>修改ImageDao新增一个接口,能按照MD5查找数据库内容

3>修改上传图片的逻辑,根据MD5判定当前图片是是否要写磁盘

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FPGA 纯VHDL解码 IMX214 MIPI 视频,2路视频拼接输出,提供vivado工程源码和技术支持

目录 1、前言免责声明 2、我这里已有的 MIPI 编解码方案3、本 MIPI CSI2 模块性能及其优越性4、详细设计方案设计原理框图IMX214 摄像头及其配置D-PHY 模块CSI-2-RX 模块Bayer转RGB模块伽马矫正模块VDMA图像缓存Video Scaler 图像缓存HDMI输出 5、vivado工程详解PL端FPGA硬件设…

无涯教程-JavaScript - INFO函数

描述 INFO函数返回有关当前操作环境的信息。 语法 INFO (type_text) 争论 Argument描述Required/OptionalType_text 指定要返回的信息类型的文本。 下表给出了Type_text的值和相应的返回信息。 Required Type_text 返回的信息"目录" 当前目录或文件夹的路径。&qu…

【Proteus仿真】【STM32单片机】四驱寻迹避障小车

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 系统运行后&#xff0c;LCD1602显示红外、超声波检测状态和距离、小车运行状态。可通过K1键可手动切换模式&#xff0c;寻迹、避障、蓝牙遥控&#xff1b;也可通过蓝牙发送指令切换模式&#xff1b; 当处…

系统架构设计之道,论如何构建一个资金账户系统

&#x1f449;导读 资金账户是互联网和金融业务中非常常见的系统&#xff0c;尤其是在电商、支付等业务中必不可少。资金账户系统本身其核心模块的整体架构往往并不复杂&#xff0c;但其对于资金安全和可用性的要求非常高&#xff0c;导致建设好一个资金账户系统并不容易。本文…

【Spring Boot】有这一文就够了

作者简介 前言 作者之前写过一个Spring Boot的系列&#xff0c;包含自动装配原理、MVC、安全、监控、集成数据库、集成Redis、日志、定时任务、异步任务等内容&#xff0c;本文将会一文拉通来总结这所有内容&#xff0c;不骗人&#xff0c;一文快速入门Spring Boot。 专栏地址…

MySQL安装validate_password_policy插件

功能介绍 validate_password_policy 是插件用于验证密码强度的策略。该参数可以设定三种级别&#xff1a;0代表低&#xff0c;1代表中&#xff0c;2代表高。 validate_password_policy 主要影响密码的强度检查级别&#xff1a; 0/LOW&#xff1a;只检查密码长度。 1/MEDIUM&am…

YashanDB:潜心实干,数据库核心技术突破没有捷径可走

都说数据库是三大基础软件中的一块硬骨头&#xff0c;技术门槛高、研发周期长、工程要求高&#xff0c;市场长期被几大巨头所把持。 因此&#xff0c;实现突破一直是中国数据库产业的夙愿。自上个世纪80年代起&#xff0c;中国数据库产业走过艰辛坎坷的四十余载&#xff0c;终…

vue组件库开发,webpack打包,发布npm

做一个像elment-ui一样的vue组件库 那多好啊&#xff01;这是我前几年就想做的 但webpack真的太难用&#xff0c;也许是我功力不够 今天看到一个视频&#xff0c;早上6-13点&#xff0c;终于实现了&#xff0c;呜呜 感谢视频的分享-来龙去脉-大家可以看这个视频&#xff1a;htt…

美东一公司的郁闷面试题

说是题目可以用不同的语言&#xff0c;但是貌似 Java 是多线程的&#xff0c;用 Java 写肯定容易不少。 但&#xff0c;觉得这个题目用多线程简直是有点脱了裤子放屁。 完整题目内容 题目的网站内容如下&#xff1a; Please complete the following challenge in one of th…

【自动驾驶决策规划】POMDP之Introduction

文章目录 前言Markov PropertyMarkov ChainHidden Markov ModelMarkov Decision ProcessPartially Observable Markov Decision ProcessBackground on Solving POMDPsPOMDP Value Iteration Example 推荐阅读与参考 前言 本文是我学习POMDP相关的笔记&#xff0c;由于个人能力…

2024字节跳动校招面试真题汇总及其解答(一)

1. 【算法题】重排链表 给定一个单链表 L 的头节点 head ,单链表 L 表示为: L0 → L1 → … → Ln - 1 → Ln请将其重新排列后变为: L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → … 不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。 示例 1: 输入:hea…

Kafka3.0.0版本——消费者(自动提交 offset)

目录 一、自动提交offset的相关参数二、消费者&#xff08;自动提交 offset&#xff09;代码示例 一、自动提交offset的相关参数 官网文档 参数解释 参数描述enable.auto.commi默认值为 true&#xff0c;消费者会自动周期性地向服务器提交偏移量。auto.commit.interval.ms如果…

基于视觉重定位的室内AR导航APP的大创项目思路(2):改进的项目思路——建图和定位分离

文章目录 一、建图二、定位首先是第一种方法&#xff1a;几何方法其次是第二种方法&#xff1a;图像检索方法最后是第三种方法&#xff1a;深度学习方法 前情提要&#xff1a; 是第一次做项目的小白&#xff0c;文章内的资料介绍如有错误&#xff0c;请多包含&#xff01; 一、…

华为云云耀云服务器L实例评测|初始化centos镜像到安装nginx部署前端vue、react项目

文章目录 ⭐前言⭐购买服务器&#x1f496; 选择centos镜像 ⭐在控制台初始化centos镜像&#x1f496;配置登录密码 ⭐在webstorm ssh连接 服务器⭐安装nginx&#x1f496; wget 下载nginx&#x1f496; 解压运行 ⭐添加安全组⭐nginx 配置⭐部署vue&#x1f496; 使用默认的ng…

【文件上传-配置文件】crossdomain.xml跨域策略配置文件上传

目录 一、0x00 前言 二、基础知识 1、Flash 2、crossdomain.xml文件 3、crossdomain.xml格式 4、crossdomain.xml相关参数 三、漏洞利用 1、方法&#xff1a; 2、上传漏洞配置文件 一、0x00 前言 在很多地方都会见查是否跨域 比如某些特定的步骤、CSRF、flash跨域劫…

SimpleCG程序交互操作

前言 之前所有示例程序都是属于展示型的&#xff0c;只是作为展示板输出使用&#xff0c;不涉及键盘和鼠标的输入交互&#xff0c;下面我们开始接触具有交互功能的程序。 没有交互功能的程序可以满足一定需求,不过大部分的程序是不能脱离交互功能的。程序依据使用者的操作进行相…

PbootCMS在搭建网站

1、打开网站 https://www.pbootcms.com/ 2、点击 “本站” 下载最新的网站代码 3、在本地laragon/www下创建目录&#xff08;hejuwuye&#xff09;&#xff0c;并将代码放进去 4、创建本地数据库&#xff0c;数据库名称为&#xff1a; hejuwuye&#xff0c;然后将static/bac…

第三方软件测试机构有哪些测试服务软件测试报告收费标准是怎样的?

软件验收机构 一、什么是第三方软件测试机构? 第三方软件测试机构是区别于软件开发公司以及软件需求方的第三方机构&#xff0c;软件企业将软件测试外包给第三方软件测试机构已经成为了行业发展趋势。既省心省力&#xff0c;又降低企业成本&#xff0c;得出的软件测试结果以…

《机器学习核心算法》分类算法 - 朴素贝叶斯 MultinomialNB

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;小白零基础《Python入门到精通》 朴素贝叶斯 1、朴素贝叶斯API2、朴素贝叶斯算法实际应用2.1、获取数据集2.2、划分…

EasyPHP-Devserver-17安装和配置mantisBT

文章目录 1、准备工作2、安装easyphp2.1 http://127.0.0.1 无法访问 3、安装mantisBT和phpMyAdmin3.1 配置浏览器的访问url和端口号&#xff08;配置局域网内可访问&#xff09;3.2 安装mantis 4、Administrator 注册新用户时设置登录密码5、附件上传6、邮件配置 文章参考自&am…