SpringMVC实战crud增删改查

news2025/1/22 12:56:16

一.公共页面的跳转

1.编写页面跳转控制类

package com.YU.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author YU
 * @create 2023-09-07 14:41
 */
@Controller
public class PageController {

    @RequestMapping("/page/{page}")
    public String toPage(@PathVariable("page") String page){
        return page;
    }

    @RequestMapping("/page/{dir}{page}")
    public String toDirPage(
            @PathVariable("dir") String dir,
            @PathVariable("page") String page){
        return dir + "/" + page;
    }
}

 二.后端实现crud

1.利用mybatis插件生成实体模型和mapper接口和xml文件

在生成后的HBookMapper接口中,需要加上@Repository给Spring进行托管

2.编写切面类和工具类

2.1切面类:

package com.YU.aspect;

import com.YU.utils.PageBean;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author YU
 * @create 2023-08-25 17:17
 */
@Aspect //代表当前类为切面类
@Component //代表当前类交给Spring进行管理
public class PagerAspect {
    @Around("execution(* *..*biz.*Pager(..))")
    public Object invoke(ProceedingJoinPoint args) throws Throwable {
        PageBean pageBean = null;
        //获取目标方法的所有参数
        Object[] ars = args.getArgs();
        for (Object param : ars) {
            if(param instanceof PageBean){
                pageBean = (PageBean)param;
                break;
            }
        }

        if(pageBean != null && pageBean.isPagination())
            PageHelper.startPage(pageBean.getPage(),pageBean.getRows());

        Object list = args.proceed();

        if(null != pageBean && pageBean.isPagination()){
            PageInfo pageInfo = new PageInfo((List) list);
            pageBean.setTotal((int) pageInfo.getTotal());
        }
        return list;
    }

}

2.2 工具类

package com.YU.utils;

import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.Map;

public class PageBean implements Serializable {

	private static final long serialVersionUID = 2422581023658455731L;

	//页码
	private int page=1;
	//每页显示记录数
	private int rows=10;
	//总记录数
	private int total=0;
	//是否分页
	private boolean isPagination=true;
	//上一次的请求路径
	private String url;
	//获取所有的请求参数
	private Map<String,String[]> map;
	
	public PageBean() {
		super();
	}
	
	//设置请求参数
	public void setRequest(HttpServletRequest req) {
		String page=req.getParameter("page");
		String rows=req.getParameter("rows");
		String pagination=req.getParameter("pagination");
		this.setPage(page);
		this.setRows(rows);
		this.setPagination(pagination);
		this.url=req.getContextPath()+req.getServletPath();
		this.map=req.getParameterMap();
	}
	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public Map<String, String[]> getMap() {
		return map;
	}

	public void setMap(Map<String, String[]> map) {
		this.map = map;
	}

	public int getPage() {
		return page;
	}

	public void setPage(int page) {
		this.page = page;
	}
	
	public void setPage(String page) {
		if(null!=page&&!"".equals(page.trim()))
			this.page = Integer.parseInt(page);
	}

	public int getRows() {
		return rows;
	}

	public void setRows(int rows) {
		this.rows = rows;
	}
	
	public void setRows(String rows) {
		if(null!=rows&&!"".equals(rows.trim()))
			this.rows = Integer.parseInt(rows);
	}

	public int getTotal() {
		return total;
	}

	public void setTotal(int total) {
		this.total = total;
	}
	
	public void setTotal(String total) {
		this.total = Integer.parseInt(total);
	}

	public boolean isPagination() {
		return isPagination;
	}
	
	public void setPagination(boolean isPagination) {
		this.isPagination = isPagination;
	}
	
	public void setPagination(String isPagination) {
		if(null!=isPagination&&!"".equals(isPagination.trim()))
			this.isPagination = Boolean.parseBoolean(isPagination);
	}
	
	/**
	 * 获取分页起始标记位置
	 * @return
	 */
	public int getStartIndex() {
		//(当前页码-1)*显示记录数
		return (this.getPage()-1)*this.rows;
	}
	
	/**
	 * 末页
	 * @return
	 */
	public int getMaxPage() {
		int totalpage=this.total/this.rows;
		if(this.total%this.rows!=0)
			totalpage++;
		return totalpage;
	}
	
	/**
	 * 下一页
	 * @return
	 */
	public int getNextPage() {
		int nextPage=this.page+1;
		if(this.page>=this.getMaxPage())
			nextPage=this.getMaxPage();
		return nextPage;
	}
	
	/**
	 * 上一页
	 * @return
	 */
	public int getPreivousPage() {
		int previousPage=this.page-1;
		if(previousPage<1)
			previousPage=1;
		return previousPage;
	}

	@Override
	public String toString() {
		return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", isPagination=" + isPagination
				+ "]";
	}
}

3.编写biz层

package com.YU.biz;

import com.YU.model.HBook;
import com.YU.utils.PageBean;

import java.util.List;

public interface HBookbiz {
    int deleteByPrimaryKey(Integer bid);

    int insert(HBook record);

    int insertSelective(HBook record);

    HBook selectByPrimaryKey(Integer bid);

    int updateByPrimaryKeySelective(HBook record);

    int updateByPrimaryKey(HBook record);

    List<HBook> listPager(HBook hBook, PageBean pageBean);
}

注: 

这个方法为查询返回列表方法,包含分页,因为切面类对其进行切面,所以在命名时,必须以Pager结尾

4.配置mapper.xml

<select id="selectBycon" resultType="com.YU.model.HBook" parameterType="com.YU.model.HBook" >
    select
    <include refid="Base_Column_List" />
    from t_mvc_book
    <where>
        <if test="bname != null">
            and bname like concat('%',#{bname},'%')
        </if>
    </where>
  </select>

5.编写相应的接口类(HBookMapper) 

    List<HBook> selectBycon(HBook hBook);

 6.处理controller层发送到biz的请求(配置spring-mvc.xml)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
      http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--1) 扫描com.YU.web及子子孙孙包下的控制器(扫描范围过大,耗时)-->
    <context:component-scan base-package="com.YU"/>

    <!--2) 此标签默认注册DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter -->
    <mvc:annotation-driven />

    <!--3) 创建ViewResolver视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- viewClass需要在pom中引入两个包:standard.jar and jstl.jar -->
        <property name="viewClass"
                  value="org.springframework.web.servlet.view.JstlView"></property>
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--4) 单独处理图片、样式、js等资源 -->
    <!-- <mvc:resources location="/css/" mapping="/css/**"/>
     <mvc:resources location="/js/" mapping="/js/**"/>
     <mvc:resources location="WEB-INF/images/" mapping="/images/**"/>-->
    <!--处理controller层发送请求到biz,会经过切面的拦截处理-->
    <aop:aspectj-autoproxy/>
</beans>

7.编写tag助手标签类

package com.YU.tag;

import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;

import com.YU.utils.PageBean;

public class PageTag extends BodyTagSupport{
	private PageBean pageBean;// 包含了所有分页相关的元素
	
	public PageBean getPageBean() {
		return pageBean;
	}

	public void setPageBean(PageBean pageBean) {
		this.pageBean = pageBean;
	}

	@Override
	public int doStartTag() throws JspException {
//		没有标签体,要输出内容
		JspWriter out = pageContext.getOut();
		try {
			out.print(toHTML());
		} catch (IOException e) {
			e.printStackTrace();
		}
		return super.doStartTag();
	}

	private String toHTML() {
		StringBuffer sb = new StringBuffer();
//		隐藏的form表单---这个就是上一次请求下次重新发的奥义所在
//		上一次请求的URL
		sb.append("<form action='"+pageBean.getUrl()+"' id='pageBeanForm' method='post'>");
		sb.append("	<input type='hidden' name='page'>");
//		上一次请求的参数
		Map<String, String[]> paramMap = pageBean.getMap();
		if(paramMap != null && paramMap.size() > 0) {
			Set<Entry<String, String[]>> entrySet = paramMap.entrySet();
			for (Entry<String, String[]> entry : entrySet) {
//				参数名
				String key = entry.getKey();
//				参数值
				for (String value : entry.getValue()) {
//					上一次请求的参数,再一次组装成了新的Form表单
//					注意:page参数每次都会提交,我们需要避免
					if(!"page".equals(key)) {
						sb.append("	<input type='hidden' name='"+key+"' value='"+value+"' >");
					}
				}
			}
		}
		sb.append("</form>");
		
//		分页条
		sb.append("<ul class='pagination justify-content-center'>");
		sb.append("	<li class='page-item "+(pageBean.getPage() == 1 ? "disabled" : "")+"'><a class='page-link'");
		sb.append("	href='javascript:gotoPage(1)'>首页</a></li>");
		sb.append("	<li class='page-item "+(pageBean.getPage() == 1 ? "disabled" : "")+"'><a class='page-link'");
		sb.append("	href='javascript:gotoPage("+pageBean.getPreivousPage()+")'>&lt;</a></li>");// less than 小于号
//		sb.append("	<li class='page-item'><a class='page-link' href='#'>1</a></li>");
//		sb.append("	<li class='page-item'><a class='page-link' href='#'>2</a></li>");
		sb.append("	<li class='page-item active'><a class='page-link' href='#'>"+pageBean.getPage()+"</a></li>");
		sb.append("	<li class='page-item "+(pageBean.getPage() == pageBean.getMaxPage() ? "disabled" : "")+"'><a class='page-link' href='javascript:gotoPage("+pageBean.nextPage()+")'>&gt;</a></li>");
		sb.append("	<li class='page-item "+(pageBean.getPage() == pageBean.getMaxPage() ? "disabled" : "")+"'><a class='page-link' href='javascript:gotoPage("+pageBean.maxPage()+")'>尾页</a></li>");
		sb.append("	<li class='page-item go-input'><b>到第</b><input class='page-link'");
		sb.append("	type='text' id='skipPage' name='' /><b>页</b></li>");
		sb.append("	<li class='page-item go'><a class='page-link'");
		sb.append("	href='javascript:skipPage()'>确定</a></li>");
		sb.append("	<li class='page-item'><b>共"+pageBean.getTotal()+"条</b></li>");
		sb.append("</ul>");
		
//		分页执行的JS代码
		sb.append("<script type='text/javascript'>");
		sb.append("	function gotoPage(page) {");
		sb.append("		document.getElementById('pageBeanForm').page.value = page;");
		sb.append("		document.getElementById('pageBeanForm').submit();");
		sb.append("	}");
		sb.append("	function skipPage() {");
		sb.append("		var page = document.getElementById('skipPage').value;");
		sb.append("		if (!page || isNaN(page) || parseInt(page) < 1 || parseInt(page) > "+pageBean.getMaxPage()+") {");
		sb.append("			alert('请输入1~"+pageBean.getMaxPage()+"的数字');");
		sb.append("			return;");
		sb.append("		}");
		sb.append("		gotoPage(page);");
		sb.append("	}");
		sb.append("</script>");
		
		return sb.toString();
	}
}

 8.引入tld标签库

<?xml version="1.0" encoding="UTF-8" ?>

<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
    version="2.0">
    
  <description>YU 1.1 core library</description>
  <display-name>YU core</display-name>
  <tlib-version>1.1</tlib-version>
  <short-name>YU</short-name>
  <uri>http://jsp.veryedu.cn</uri>
  
  
  <tag>
    <name>page</name>
    <tag-class>com.YU.tag.PageTag</tag-class>
    <body-content>JSP</body-content>
    <attribute>
        <name>pageBean</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
    </attribute>
  </tag>
  
</taglib>

9.编写controller类

package com.YU.web;

import com.YU.biz.HBookbiz;
import com.YU.model.HBook;
import com.YU.utils.PageBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * @author YU
 * @create 2023-09-07 16:07
 */
@Controller
@RequestMapping("book")
public class HbookController {

    @Autowired
    private HBookbiz hBookbiz;

    //增加
    @RequestMapping("/add")
    public String add(HBook hBook){
         hBookbiz.insertSelective(hBook);
        return "redirect:/book/list";
    }
    //删除
    @RequestMapping("/del/{bid}")
    public String del(@PathVariable("bid")Integer bid){
        hBookbiz.deleteByPrimaryKey(bid);
        return "redirect:/book/list";
    }
    //修改
    @RequestMapping("/edit")
    public String edit(HBook hBook){
        hBookbiz.updateByPrimaryKeySelective(hBook);
        return "redirect:list";
    }
    //查询
    @RequestMapping("/list")
    public String list(HBook hBook, HttpServletRequest request){
//        hbook用来接收前台传递后台的参数
        PageBean pageBean = new PageBean();
        pageBean.setRequest(request);
        List<HBook> hBooks = hBookbiz.listPager(hBook, pageBean);
        request.setAttribute("lst",hBooks);
        request.setAttribute("pageBean",pageBean);
        return "book/list";
    }
    //数据回显
    @RequestMapping("/preSave")
    public String preSave(HBook hBook, Model model){
        if(hBook !=null && hBook.getBid()!=null && hBook.getBid()!=0){
            HBook b = hBookbiz.selectByPrimaryKey(hBook.getBid());
            model.addAttribute("b",b);
        }
        return "book/edit";
    }
}

10.编写前端页面

1.主页面(展示数据进行操作)

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<%@ taglib uri="http://jsp.veryedu.cn" prefix="z"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <link
            href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.css"
            rel="stylesheet">
    <script
            src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/js/bootstrap.js"></script>
    <title>博客列表</title>
    <style type="text/css">
        .page-item input {
            padding: 0;
            width: 40px;
            height: 100%;
            text-align: center;
            margin: 0 6px;
        }

        .page-item input, .page-item b {
            line-height: 38px;
            float: left;
            font-weight: 400;
        }

        .page-item.go-input {
            margin: 0 10px;
        }
    </style>
</head>
<body>
<form class="form-inline"
      action="${pageContext.request.contextPath }/book/list" method="get">
    <div class="form-group mb-2">
        <input type="text" class="form-control-plaintext" name="cname"
               placeholder="请输入班级名称">
        <!-- 			<input name="rows" value="20" type="hidden"> -->
        <!-- 不想分页 -->
        <%--        <input name="pagination" value="false" type="hidden">--%>
    </div>
    <button type="submit" class="btn btn-primary mb-2">查询</button>
    <a class="btn btn-primary mb-2" href="${pageContext.request.contextPath }/book/preSave">新增</a>
</form>

<table class="table table-striped">
    <thead>
    <tr>
        <th scope="col">书籍ID</th>
        <th scope="col">书籍名称</th>
        <th scope="col">书籍价格</th>
<%--        <th scope="col">班级图片</th>--%>
        <th scope="col">操作</th>
    </tr>
    </thead>
    <tbody>
    <c:forEach  var="b" items="${lst }">
        <tr>
            <td>${b.bid }</td>
            <td>${b.bname }</td>
            <td>${b.price }</td>
            <td>
                <a href="${pageContext.request.contextPath }/book/preSave?bid=${b.bid}">修改</a>
                <a href="${pageContext.request.contextPath }/book/del/${b.bid}">删除</a>
            </td>
        </tr>
    </c:forEach>
    </tbody>
</table>
<!-- 这一行代码就相当于前面分页需求前端的几十行了 -->
<z:page pageBean="${pageBean }"></z:page>
${pageBean }
</body>
</html>

2.增加修改界面(操作数据)

<body>
<form action="${pageContext.request.contextPath }/${empty b ? 'book/add' : 'book/edit'}" method="post">
    cid:<input type="text" name="bid" value="${b.bid }"><br>
    bname:<input type="text" name="bname" value="${b.bname }"><br>
    price:<input type="text" name="price" value="${b.price }"><br>
    <input type="submit">
</form>
</body>

3.测试结果

感谢各位大大的收看,各位的支持和三连是博主更新的动力,感谢谢谢谢!!!!

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

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

相关文章

Apache Linki 1.3.1+DataSphereStudio+正常启动+微服务+端口号

我使用的是一键部署容器化版本&#xff0c;官方文章 默认会启动6个 Linkis 微服务&#xff0c;其中下图linkis-cg-engineconn服务为运行任务才会启动,一共七个 LINKIS-CG-ENGINECONN:38681 LINKIS-CG-ENGINECONNMANAGER:9102 引擎管理服务 LINKIS-CG-ENTRANCE:9104 计算治理入…

Linux 中的 chpasswd 命令及示例

chpasswd命令用于更改密码,尽管passwd命令也可以执行相同的操作。但它一次更改一个用户的密码,因此对于多个用户,使用chpasswd 。下图显示了passwd命令的使用。使用passwd我们正在更改来宾用户的密码。首先,您必须输入当前签名用户的密码,然后更改任何其他用户的密码。必须…

文本识别 (OCR)引擎之Tesseract的使用

Tesseract OCR Tesseract概述常见OCR识别平台下载安装配置命令使用语法测试验证 Tesseract的使用安装python库基本使用可能的异常更换语言字体库识别 Tesseract的训练 Tesseract 概述 Tesseract是一个开源文本识别 (OCR)引擎&#xff0c;是目前公认最优秀、最精确的开源OCR系统…

微服务井喷时代,我们如何规模化运维?

随着云原生技术发展及相关技术被越来越多运用到公司生产实践当中&#xff0c;有两种不可逆转的趋势&#xff1a; 1、微服务数量越来越多。原来巨型单体服务不断被拆解成一个个微服务&#xff0c;在方便功能复用及高效迭代的同时&#xff0c;也给运维带来了不少挑战&#xff1a;…

WorkPlus AI助理,基于ChatGPT的企业级知识问答机器人

随着人工智能技术的发展&#xff0c;WorkPlus AI助理以ChatGPT对话能力为基础&#xff0c;将企业数据与人工智能相结合&#xff0c;推出了面向企业的知识问答机器人。这一创新性的解决方案帮助企业高效管理和利用自身的知识资产&#xff0c;助力企业级人工智能的构建。与传统的…

React 入门实例教程

目录 一、HTML 模板 二、ReactDOM.render() 三、JSX 语法 四、组件 五、this.props.children 六、PropTypes 七、获取真实的DOM节点 八、this.state 九、表单 十、组件的生命周期 constructor() componentWillMount() render() componentDidMount() 组件生命周期…

MOV导出序列帧并在Unity中播放

MOV导出序列帧并在Unity中播放 前言项目将MOV变成序列帧使用TexturePacker打成一个图集将Json格式精灵表转换为tpsheet格式精灵表导入Unity并播放总结 鸣谢 前言 收集到一批还不错的MG动画&#xff0c;想要在Unity中当特效播放出来&#xff0c;那首先就得把MOV变成序列帧&…

Say0l的安全开发-弱口令扫描工具-My-crack【红队工具】

写在前面 终于终于&#xff0c;安全开发也练习一年半了&#xff0c;有时间完善一下项目&#xff0c;写写中间踩过的坑。 安全开发的系列全部都会上传至github&#xff0c;欢迎使用和star。 工具链接地址 https://github.com/SAY0l/my-crack 预览 My-Crack 工具介绍 更适合…

Java 毕业设计-基于SpringBoot的在线文档管理系统

基于SpringBoot的在线文档管理系统 博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W,Csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 技术栈简介 文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;sp…

2020年09月 C/C++(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

C/C++编程(1~8级)全部真题・点这里 第1题:铺砖 对于一个2行N列的走道。现在用12,22的砖去铺满。问有多少种不同的方式。 时间限制:3000 内存限制:131072 输入 整个测试有多组数据,请做到文件底结束。每行给出一个数字N,0 <= n <= 250 输出 如题 样例输入 2 8 12 1…

声网agora创建账号

1. 注册声网账号 https://sso2.agora.io/cn/v4/signup/with-sms 2. 创建项目 项目管理 - 创建项目 3. 项目配置 appid: xxxx token: xxxx 4. 开发文档 https://docportal.shengwang.cn/cn/All/code-samples?platformiOS

免费绕过苹果MDM配置锁/密码界面工具-Hackt1vator Unlock

Hackt1vator Unlock Hackt1vator Unlock是一款免费免费绕过苹果MDM配置锁/密码界面工具&#xff0c;帮助那些忘记iCloud账号密码而无法使用的iPhone、iPad的用户绕过 icloud 激活、mdm 和密码锁定&#xff0c;目前工具支持跳过MDM配置锁&#xff0c;支持绕过物主与锁定界面&am…

如何按文件名称自动归类,助您轻松管理文件

在日常工作和生活中&#xff0c;我们经常会遇到大量的文件需要管理。如果这些文件没有得到良好的归类和整理&#xff0c;不仅会浪费我们的时间和精力&#xff0c;还会给我们带来困扰和混乱。今天我们一起来看看怎么按文件名称来自动归类&#xff0c;批量整理文件&#xff0c;让…

postgresql|数据库|数据迁移神器ora2pg的安装部署和初步使用

前言&#xff1a; 有的时候有需求需要迁移Oracle数据库的数据到postgresql&#xff0c;那么&#xff0c;其实可供选择的工具是比较多的&#xff0c;但从迁移效率&#xff0c;准确度这些角度来选择的话&#xff0c;无疑还是GitHub上的开源免费工具ora2pg比较合适的。 ora2pg的…

windows系统下使用crashpad为vs2019项目在崩溃时生成dump文件(步骤超详细)

我们在刚开始项目开发时&#xff0c;经常会因为各种粗心造成各种各样的容易使项目运行时崩溃的代码&#xff0c;比如&#xff0c;给空指针的指向赋值。然而&#xff0c;当项目的文件数非常多时&#xff0c;想找到出错的代码的位置是费事而让人心烦的。crashpad就可以在项目运行…

【Linux】使用 Alist 实现阿里云盘4K播放

一、安装 Alist 官方文档 默认安装在 /opt/alist 中 curl -fsSL "https://alist.nn.ci/v3.sh" | bash -s install自定义安装路径&#xff0c;将安装路径作为第二个参数添加&#xff0c;必须是绝对路径&#xff0c;如果路径以 alist 结尾&#xff0c;则直接安装到给定…

vite+vue 项目使用 electron

创建 vitevue 项目 npm create viteElectron 官方文档 electron 安装 安装 electron npm install --save-dev electron新建 electron 的入口文件&#xff0c;我这里在根目录新建 electron 文件夹&#xff0c;然后新建main.js和preload.js文件 根据官网说明&#xff0c;将以下…

企业架构LNMP学习笔记21

URL重写&#xff1a; ngx_http_rewrite_module 模块用于使用PCRE正则表达式更改请求URI&#xff0c;返回重定向&#xff0c;以及有条件地选择配置。 return 该指令用于结束结束规则的执行并返回状态码给客户端。 403 Forbidden.服务器已经理解请求,但是拒绝执行它 404 Not…

【动手学深度学习】--序列模型

文章目录 序列模型1.序列数据2.统计工具3.自回归模型3.1马尔科夫假设3.2潜变量模型 4.训练5.预测 序列模型 学习视频&#xff1a;序列模型【动手学深度学习v2】 官方笔记&#xff1a;序列模型 1.序列数据 想象一下有人正在看网飞&#xff08;Netflix&#xff0c;一个国外的视…

基于Docker从零到一实操MySql的主从复制

文章目录 一、在Docker上安装&#xff0c;启动MySQL查看docker是否安装成功安装mysql查看mysql镜像进入mysql后台操作docker Volume&#xff08;卷&#xff09;入门 MySql的主从复制1. 创建MySQL主从复制的网络2. 创建MySQL主服务器3. 创建MySQL从服务器4. 配置主从同步5.测试主…