MVC模式分层练习

新建库

新建表

插入点数据

先不用MVC模式写功能,来看下缺点是什么

新建一个空项目

选项项目使用的JDK

自己的IDEA总是要重启下

新建模块

因maven还没教

添加框架支持

添加后项目多了这些

添加些必要依赖  这里注意下,如果导入jar包不对可以重新导入下或者是jar包本身出了问题

添加页面

配置Tomcat

启动

请求地址  因现在没有后端

现在写后端 并测试

解决控制台输出乱码问题

System.out输出乱码

需要用到JDBC连接Mysql数据库

导入Mysql驱动jar包

java web项目  一般会在WEB-INF下有个lib用来放Tomcat内没有,外部引入的依赖

可以创建个lib目录  然后将jar包复制进来

具体代码

package com.bank.web;import com.bank.exception.AppException;
import com.bank.exception.MoneyNotEnoughException;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.sql.*;
import java.util.Locale;/*** 在不使用MVC架构模式的前提下,完成银行账户转账* 分析这个程序存在哪些问题?* @author hrui* @date 2023/8/31 23:06*/
@WebServlet("/transfer")
public class AccountTransferServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取响应流对象resp.setContentType("text/html;charset=UTF-8");PrintWriter writer = resp.getWriter();//获取前端传来的参数String fromActno = req.getParameter("fromActno");String toActno = req.getParameter("toActno");double money = Double.parseDouble(req.getParameter("money"));
//        System.out.println("转出账户:"+fromActno);
//        System.out.println("转入账户:"+fromActno);
//        System.out.println("转账金额:"+fromActno);//编写转账的业务逻辑代码,连接数据库,进行转账操作//1.转账之前要判断转出账户的余额是否充足Connection conn=null;PreparedStatement ps=null;//PreparedStatement ps2=null;ResultSet rs=null;try {//注册驱动Class.forName("com.mysql.cj.jdbc.Driver");//获取连接conn = DriverManager.getConnection("xxx", "xxx", "xxx");conn.setAutoCommit(false);//获取执行对象String sql="select balance from t_act where actno=?";ps = conn.prepareStatement(sql);ps.setString(1, fromActno);//执行sql,返回结果集rs = ps.executeQuery();//获取结果集if(rs.next()){double balance = rs.getDouble("balance");if(balance<money){//余额不足(使用异常处理机制)throw new MoneyNotEnoughException("余额不足");}//程序能到这里,说明余额重组  不需要else//开始转账sql="update t_act set balance=balance-? where actno=?";ps = conn.prepareStatement(sql);ps.setDouble(1, money);ps.setString(2, fromActno);int count = ps.executeUpdate();//模拟异常String str=null;str.toString();sql="update t_act set balance=balance+? where actno=?";ps=conn.prepareStatement(sql);ps.setDouble(1, money);ps.setString(2, toActno);//累计count += ps.executeUpdate();if(count!=2){throw new AppException("app异常,请联系管理员");}}conn.commit();writer.print("转账成功");} catch (ClassNotFoundException | SQLException | MoneyNotEnoughException | AppException e) {try {if(conn!=null) {conn.rollback();}} catch (SQLException e1) {e1.printStackTrace();}e.printStackTrace();writer.print(e.getMessage());}finally {//释放资源,根据JDBC规范 从小到大if(rs!=null){try {rs.close();} catch (SQLException e) {e.printStackTrace();}}if(ps!=null){try {ps.close();} catch (SQLException e) {e.printStackTrace();}}if(conn!=null){try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}}
}

1>负责了数据接收

2>负责了核心业务处理

3>负责了数据库表中的CRUD操作(Create(增) Retrieve(查) Update(改) Delete(删))

4>负责了数据的页面展示

引起的缺点:

代码复用性差  比如查余额,可以抽取出来,单独放到一个方法

代码复用性差的原因,没有职能分工,独立组件的概念,代码之间耦合度高,扩展力差

操作数据库代码和业务逻辑混杂在一起,容易出错,无法专注于业务逻辑书写

下面以MVC的模式对上面代码改进

1.系统为什么要分层?

        希望专人干专事.各司其职.分工明确.这样可以降低耦合,扩展增强.复用增强

2.软件架构中,有一个非常著名的架构模式:MVC模式

M(Model:数据/业务)       V(View:视图/展示)       C(Controller:控制器/核心)

首先是对JDBC的封装

JDBC工具类

package com.bank.utils;import java.sql.*;
import java.util.ResourceBundle;/*** @author hrui* @date 2023/9/1 10:24*/
public class DBUtil {private static ResourceBundle bundle=ResourceBundle.getBundle("resources/jdbc");private static String driver=bundle.getString("driver");private static String url=bundle.getString("url");private static String username=bundle.getString("username");private static String password=bundle.getString("password");//不让创建对象,原因工具类方法一般都静态的,无需外部创建对象//为防止外部创建对象,构造私有化private DBUtil(){}//DBUtil类加载时注册驱动static{try {Class.forName(driver);} catch (ClassNotFoundException e) {e.printStackTrace();}}//没有使用连接池,直接创建的连接对象public static Connection getConnection() throws SQLException {Connection conn= DriverManager.getConnection(url,username,password);return conn;}public static void close(Connection conn, Statement statement, ResultSet rs){if(rs!=null){try {rs.close();} catch (SQLException e) {e.printStackTrace();}}if(statement!=null){try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if(conn!=null){try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}
}

测试连接

封装实体类

package com.bank.mvc;import java.util.Objects;/*** 账户实体类,用于封装账户信息* POJO对象* 有的人也会把这种专门封装数据的对象,称为bean对象(javabean:咖啡豆)* 有的人也会把这种专门分装数据的对象,称为领域模型对象.domain对象.* pojo,bean,domain* @author hrui* @date 2023/9/1 15:34*/
public class Account {private Long id;private String actno;private Double balance;public Account() {}public Account(Long id, String actno, Double balance) {this.id = id;this.actno = actno;this.balance = balance;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getActno() {return actno;}public void setActno(String actno) {this.actno = actno;}public Double getBalance() {return balance;}public void setBalance(Double balance) {this.balance = balance;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Account acount = (Account) o;return id.equals(acount.id) && actno.equals(acount.actno) && balance.equals(acount.balance);}@Overridepublic int hashCode() {return Objects.hash(id, actno, balance);}@Overridepublic String toString() {return "Account{" +"id=" + id +", actno='" + actno + '\'' +", balance=" + balance +'}';}
}

编写DAO层

package com.bank.mvc;import com.bank.utils.DBUtil;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;/*** 负责Acount数据的增删改查* 1.什么是DAO*      Data Access Object(数据访问对象)* 2.DAO实际上是一种设计模式,属于JAVAEE的设计模式之一.(不是23种设计模式)* 3.DAO只负责数据库CRUD,没有任何业务逻辑* 4.没有任何业务逻辑,只负责表中数据增删改查,有一个特殊的称谓:DAO对象* @author hrui* @date 2023/9/1 12:39*/
public class AccountDao {public int insert(Account act){Connection conn=null;PreparedStatement ps=null;int count=0;try {conn= DBUtil.getConnection();String sql="insert into t_act(actno,balance) values (?,?)";ps=conn.prepareStatement(sql);ps.setString(1, act.getActno());ps.setDouble(2, act.getBalance());count=ps.executeUpdate();} catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e);}finally {DBUtil.close(conn,ps,null);}return count;}public int deleteByActno(Long id){Connection conn=null;PreparedStatement ps=null;int count=0;try {conn=DBUtil.getConnection();String sql="delete from t_act where id=?";ps=conn.prepareStatement(sql);ps.setLong(1, id);count = ps.executeUpdate();} catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e);}finally {DBUtil.close(conn,ps,null);}return count;}public int update(Account act){Connection conn=null;PreparedStatement ps=null;int count=0;try {conn=DBUtil.getConnection();String sql="update t_act set balance=? where id=?";ps=conn.prepareStatement(sql);ps.setDouble(1, act.getBalance());ps.setLong(2, act.getId());count = ps.executeUpdate();} catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e);}finally {DBUtil.close(conn,ps,null);}return count;}public Account selectBtActNo(String actno){Connection conn=null;PreparedStatement ps=null;ResultSet rs=null;Account account=new Account();try {conn=DBUtil.getConnection();String sql="select id,actno,balance from t_act where actno=?";ps=conn.prepareStatement(sql);ps.setString(1, actno);rs = ps.executeQuery();if(rs.next()){Long id=rs.getLong("id");String actno1=rs.getString("actno");Double balance=rs.getDouble("balance");account.setId(id);account.setActno(actno1);account.setBalance(balance);}} catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e);}finally {DBUtil.close(conn,ps,null);}return account;}public List<Account> selectAll(){Connection conn=null;PreparedStatement ps=null;ResultSet rs=null;List<Account> list=new ArrayList<>();try {conn=DBUtil.getConnection();String sql="select id,actno,balance from t_act ";ps=conn.prepareStatement(sql);rs = ps.executeQuery();while(rs.next()){Long id=rs.getLong("id");String actno=rs.getString("actno");Double balance=rs.getDouble("balance");Account account=new Account();account.setId(id);account.setActno(actno);account.setBalance(balance);list.add(account);}} catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e);}finally {DBUtil.close(conn,ps,null);}return list;}
}

原先在Servlet里

1>负责了数据接收

2>负责了狠心业务处理

3>负责了数据库表中数据CRUD操作

4>负责了页面数据展示

现在已经一层层分离了

两个异常类

用AccountSAervice来做业务处理

具体业务处理代码

package com.bank.mvc;import com.bank.exception.AppException;
import com.bank.exception.MoneyNotEnoughException;/*** Service:业务* 专门处理Account的业务处理类* 该类只专注业务处理* 主要专注于MVC模式,不需要专注于取什么名字  xxx都可以* @author hrui* @date 2023/9/2 0:49*/
public class AccountService {private AccountDao accountDao=new AccountDao();/*** 完成转账的业务逻辑* @param fromActno* @param toActno* @param money*/public void transfer(String fromActno,String toActno,double money) throws MoneyNotEnoughException, AppException {//查询余额是否充足Account fromAccount = accountDao.selectBtActNo(fromActno);if(fromAccount.getBalance()<money){throw new MoneyNotEnoughException("余额不足");}//程序到这里说明余额够Account toAct=accountDao.selectBtActNo(toActno);//修改余额fromAccount.setBalance(fromAccount.getBalance()-money);toAct.setBalance(toAct.getBalance()+money);//更新数据库int count=accountDao.update(fromAccount);count += accountDao.update(toAct);//count++;if(count!=2){throw new AppException("转账异常");}}}

servlet里做的就是调度

package com.bank.mvc;import com.bank.exception.AppException;
import com.bank.exception.MoneyNotEnoughException;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;/*** 让AcountServlet做为Controller  调度员* 负责调度其他组件* @author hrui* @date 2023/9/1 12:27*/
@WebServlet("/transfer")
public class AccountServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获取前端传来的参数String fromActno = req.getParameter("fromActno");String toActno = req.getParameter("toActno");double money = Double.parseDouble(req.getParameter("money"));//调用业务方法处理业务(调度Model处理业务)AccountService accountService=new AccountService();try {accountService.transfer(fromActno,toActno,money);resp.sendRedirect(req.getContextPath()+"/success.jsp");} catch (MoneyNotEnoughException e) {e.printStackTrace();resp.sendRedirect(req.getContextPath()+"/moneynoenough.jsp");} catch (AppException e) {e.printStackTrace();resp.sendRedirect(req.getContextPath()+"/error.jsp");}}
}

三个页面显示

 

上面代码缺少事务控制,一般事务都在service进行控制

一般来说是在service层去开启事务  提交事务

这里事务管理,做的low的方式就是在业务层获取数据库连接对象,然后传进去,当然这样做的话,在DAO层就不要在finally中关闭事务了.传个null就行,在Service中开启事务,并在Service中提交事务,在Service中的finally中关闭连接

上代码

DAO

package com.bank.mvc;import com.bank.utils.DBUtil;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;/*** 负责Acount数据的增删改查* 1.什么是DAO*      Data Access Object(数据访问对象)* 2.DAO实际上是一种设计模式,属于JAVAEE的设计模式之一.(不是23种设计模式)* 3.DAO只负责数据库CRUD,没有任何业务逻辑* 4.没有任何业务逻辑,只负责表中数据增删改查,有一个特殊的称谓:DAO对象* @author hrui* @date 2023/9/1 12:39*/
public class AccountDao {public int insert(Account act,Connection conn){PreparedStatement ps=null;int count=0;try {String sql="insert into t_act(actno,balance) values (?,?)";ps=conn.prepareStatement(sql);ps.setString(1, act.getActno());ps.setDouble(2, act.getBalance());count=ps.executeUpdate();} catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e);}finally {DBUtil.close(null,ps,null);}return count;}public int deleteByActno(Long id,Connection conn){PreparedStatement ps=null;int count=0;try {String sql="delete from t_act where id=?";ps=conn.prepareStatement(sql);ps.setLong(1, id);count = ps.executeUpdate();} catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e);}finally {DBUtil.close(null,ps,null);}return count;}public int update(Account act,Connection conn){PreparedStatement ps=null;int count=0;try {String sql="update t_act set balance=? where id=?";ps=conn.prepareStatement(sql);ps.setDouble(1, act.getBalance());ps.setLong(2, act.getId());count = ps.executeUpdate();} catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e);}finally {DBUtil.close(null,ps,null);}return count;}public Account selectBtActNo(String actno,Connection conn){PreparedStatement ps=null;ResultSet rs=null;Account account=new Account();try {String sql="select id,actno,balance from t_act where actno=?";ps=conn.prepareStatement(sql);ps.setString(1, actno);rs = ps.executeQuery();if(rs.next()){Long id=rs.getLong("id");String actno1=rs.getString("actno");Double balance=rs.getDouble("balance");account.setId(id);account.setActno(actno1);account.setBalance(balance);}} catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e);}finally {DBUtil.close(null,ps,null);}return account;}public List<Account> selectAll(Connection conn){Connection conn=null;PreparedStatement ps=null;ResultSet rs=null;List<Account> list=new ArrayList<>();try {String sql="select id,actno,balance from t_act ";ps=conn.prepareStatement(sql);rs = ps.executeQuery();while(rs.next()){Long id=rs.getLong("id");String actno=rs.getString("actno");Double balance=rs.getDouble("balance");Account account=new Account();account.setId(id);account.setActno(actno);account.setBalance(balance);list.add(account);}} catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e);}finally {DBUtil.close(null,ps,null);}return list;}
}

Service

package com.bank.mvc;import com.bank.exception.AppException;
import com.bank.exception.MoneyNotEnoughException;
import com.bank.utils.DBUtil;import java.sql.Connection;
import java.sql.SQLException;/*** Service:业务* 专门处理Account的业务处理类* 该类只专注业务处理* 主要专注于MVC模式,不需要专注于取什么名字  xxx都可以* @author hrui* @date 2023/9/2 0:49*/
public class AccountService {private AccountDao accountDao=new AccountDao();/*** 完成转账的业务逻辑* @param fromActno* @param toActno* @param money*/public void transfer(String fromActno,String toActno,double money) throws MoneyNotEnoughException, AppException {//Service层控制事务//开启事务(需要用到Connection对象)Connection conn=null;try {conn = DBUtil.getConnection();conn.setAutoCommit(false);//查询余额是否充足Account fromAccount = accountDao.selectBtActNo(fromActno,conn);if(fromAccount.getBalance()<money){throw new MoneyNotEnoughException("余额不足");}//程序到这里说明余额够Account toAct=accountDao.selectBtActNo(toActno,conn);//修改余额fromAccount.setBalance(fromAccount.getBalance()-money);toAct.setBalance(toAct.getBalance()+money);//更新数据库int count=accountDao.update(fromAccount,conn);count += accountDao.update(toAct,conn);
//        String str=null;
//        str.toString();//或者//count++;  会向用户提示转账失败  但是转账确已经完成   或者1账户减款而2账户没有加的情况if(count!=2){throw new AppException("转账异常");}conn.commit();} catch (SQLException e) {e.printStackTrace();}finally {DBUtil.close(conn,null,null);}}}

 

但上面代码有点low

如何解决Connection传参问题

用ThreadLocal

改造代码

DBUtil

package com.bank.utils;import java.sql.*;
import java.util.ResourceBundle;/*** @author hrui* @date 2023/9/1 10:24*/
public class DBUtil {private static ResourceBundle bundle=ResourceBundle.getBundle("resources/jdbc");private static String driver=bundle.getString("driver");private static String url=bundle.getString("url");private static String username=bundle.getString("username");private static String password=bundle.getString("password");//不让创建对象,原因工具类方法一般都静态的,无需外部创建对象//为防止外部创建对象,构造私有化private DBUtil(){}//DBUtil类加载时注册驱动static{try {Class.forName(driver);} catch (ClassNotFoundException e) {e.printStackTrace();}}private static ThreadLocal<Connection> local=new ThreadLocal<>();//没有使用连接池,直接创建的连接对象public static Connection getConnection() throws SQLException {Connection conn=local.get();if(conn==null) {conn = DriverManager.getConnection(url, username, password);local.set(conn);}return conn;}public static void close(Connection conn, Statement statement, ResultSet rs){if(rs!=null){try {rs.close();} catch (SQLException e) {e.printStackTrace();}}if(statement!=null){try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if(conn!=null){try {conn.close();//注意:关闭连接时候移除  Tomcat是支持线程池的,不从当前线程里移除 有可能下次别人拿到了,但是conn已经关闭local.remove();} catch (SQLException e) {e.printStackTrace();}}}
}

将AccountDao恢复原状,还是从DBUtil里取Connection,但是不需要再传参数,注意finally里面Connection照样传null,原因:还是需要在Service层进行事务控制

package com.bank.mvc;import com.bank.utils.DBUtil;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;/*** 负责Acount数据的增删改查* 1.什么是DAO*      Data Access Object(数据访问对象)* 2.DAO实际上是一种设计模式,属于JAVAEE的设计模式之一.(不是23种设计模式)* 3.DAO只负责数据库CRUD,没有任何业务逻辑* 4.没有任何业务逻辑,只负责表中数据增删改查,有一个特殊的称谓:DAO对象* @author hrui* @date 2023/9/1 12:39*/
public class AccountDao {public int insert(Account act){PreparedStatement ps=null;int count=0;try {Connection  conn= DBUtil.getConnection();String sql="insert into t_act(actno,balance) values (?,?)";ps=conn.prepareStatement(sql);ps.setString(1, act.getActno());ps.setDouble(2, act.getBalance());count=ps.executeUpdate();} catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e);}finally {DBUtil.close(null,ps,null);}return count;}public int deleteByActno(Long id){PreparedStatement ps=null;int count=0;try {Connection  conn= DBUtil.getConnection();String sql="delete from t_act where id=?";ps=conn.prepareStatement(sql);ps.setLong(1, id);count = ps.executeUpdate();} catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e);}finally {DBUtil.close(null,ps,null);}return count;}public int update(Account act){PreparedStatement ps=null;int count=0;try {Connection conn=DBUtil.getConnection();String sql="update t_act set balance=? where id=?";ps=conn.prepareStatement(sql);ps.setDouble(1, act.getBalance());ps.setLong(2, act.getId());count = ps.executeUpdate();} catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e);}finally {DBUtil.close(null,ps,null);}return count;}public Account selectBtActNo(String actno){PreparedStatement ps=null;ResultSet rs=null;Account account=new Account();try {Connection conn=DBUtil.getConnection();String sql="select id,actno,balance from t_act where actno=?";ps=conn.prepareStatement(sql);ps.setString(1, actno);rs = ps.executeQuery();if(rs.next()){Long id=rs.getLong("id");String actno1=rs.getString("actno");Double balance=rs.getDouble("balance");account.setId(id);account.setActno(actno1);account.setBalance(balance);}} catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e);}finally {DBUtil.close(null,ps,null);}return account;}public List<Account> selectAll(){PreparedStatement ps=null;ResultSet rs=null;List<Account> list=new ArrayList<>();try {Connection conn=DBUtil.getConnection();String sql="select id,actno,balance from t_act ";ps=conn.prepareStatement(sql);rs = ps.executeQuery();while(rs.next()){Long id=rs.getLong("id");String actno=rs.getString("actno");Double balance=rs.getDouble("balance");Account account=new Account();account.setId(id);account.setActno(actno);account.setBalance(balance);list.add(account);}} catch (SQLException e) {e.printStackTrace();throw new RuntimeException(e);}finally {DBUtil.close(null,ps,null);}return list;}
}

业务层

package com.bank.mvc;import com.bank.exception.AppException;
import com.bank.exception.MoneyNotEnoughException;
import com.bank.utils.DBUtil;import java.sql.Connection;
import java.sql.SQLException;/*** Service:业务* 专门处理Account的业务处理类* 该类只专注业务处理* 主要专注于MVC模式,不需要专注于取什么名字  xxx都可以* @author hrui* @date 2023/9/2 0:49*/
public class AccountService {private AccountDao accountDao=new AccountDao();/*** 完成转账的业务逻辑* @param fromActno* @param toActno* @param money*/public void transfer(String fromActno,String toActno,double money) throws MoneyNotEnoughException, AppException {try(Connection conn= DBUtil.getConnection()){conn.setAutoCommit(false);//查询余额是否充足Account fromAccount = accountDao.selectBtActNo(fromActno);if(fromAccount.getBalance()<money){throw new MoneyNotEnoughException("余额不足");}//程序到这里说明余额够Account toAct=accountDao.selectBtActNo(toActno);//修改余额fromAccount.setBalance(fromAccount.getBalance()-money);toAct.setBalance(toAct.getBalance()+money);//更新数据库int count=accountDao.update(fromAccount);count += accountDao.update(toAct);
//        String str=null;
//        str.toString();//或者//count++;  会向用户提示转账失败  但是转账确已经完成   或者1账户减款而2账户没有加的情况if(count!=2){throw new AppException("转账异常");}conn.commit();} catch (SQLException e) {e.printStackTrace();throw new AppException("转账异常");}}}

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

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

相关文章

【Linux】线程安全-生产者消费者模型

文章目录 生产者消费者模型123规则应用场景优点忙闲不均生产者和消费者解耦支持高并发 代码模拟 生产者消费者模型 123规则 1个线程安全的队列&#xff1a;只要保证先进先出特性的数据结构都可以称为队列 这个队列要保证互斥&#xff08;就是保证当前只有一个线程对队列进行操…

【数据结构】| 并查集及其优化实现

目录 一. 并查集基本概念处理过程初始化合并查询小结 二. 求并优化2.1 按大小求并2.2 按秩(高度)求并2.3 路径压缩2.4 类的实现代码2.5 复杂度分析 三. 应用LeetCode 128: 最长连续数列LeetCode 547: 省份数量LeetCode 200: 岛屿数量 一. 并查集基本概念 以一个直观的问题来引入…

Linux 通过 Docker 部署 Nacos 2.2.3 服务发现与配置中心

目录 环境准备Nacos 数据库创建Docker 部署 Nacos1. 创建挂载目录2. 下载镜像3. 创建和启动容器4. 访问控制台 导入 Nacos 配置SpringBoot 整合 Nacospom 依赖application.yml 配置 参考官方链接微服务商城源码 环境准备 名称版本IP端口Nacos2.2.3192.168.10.218848、9848MySQ…

一个面向MCU的小型前后台系统

JxOS简介 JxOS面向MCU的小型前后台系统&#xff0c;提供消息、事件等服务&#xff0c;以及软件定时器&#xff0c;低功耗管理&#xff0c;按键&#xff0c;led等常用功能模块。 gitee仓库地址为&#xff08;复制到浏览器打开&#xff09;&#xff1a; https://gitee.com/jer…

十二、分组查询

1、分组查询 &#xff08;1&#xff09;基础语法&#xff1a; select 字段列表 from 表名 [where 条件] group by 分组字段名 [having 分组之后的过滤条件] &#xff08;2&#xff09;注意事项&#xff1a; &#xff08;3&#xff09;理解&#xff1a; select后的“字段列表…

苹果使用3D打印技术制造Apple Watch Series 9手表外壳

据彭博社的马克・古尔曼报道&#xff0c;苹果公司正在使用 3D 打印技术来制造即将推出的部分Apple Watch Series 9 的外壳。这种制造工艺可以节省传统数控加工所需的大量金属材料&#xff0c;同时缩短生产时间。这与之前苹果分析师郭明錤的说法相吻合。 苹果公司自2021年推出Ai…

java八股文面试[多线程]——newWorkStealingPool

newWorkStealingPool是什么&#xff1f; newWorkStealingPool简单翻译是任务窃取线程池。 newWorkStealingPool 是Java8添加的线程池。和别的4种不同&#xff0c;它用的是ForkJoinPool。 使用ForkJoinPool的好处是&#xff0c;把1个任务拆分成多个“小任务”&#xff0c;把这…

如何增强客户支持?用全渠道聊天机器人

您的用户在哪里&#xff1f;您是否想拥有源源不断的客户&#xff1f;全渠道聊天机器人可确保您在他们需要的地方为他们提供一致的客户支持&#xff01; 自技术出现以来&#xff0c;消费者行为已经完全改变。这意味着企业与用户互动和提供客户支持的方式也发生了变化。现在&…

el-select 使用

案例&#xff1a; /* * label : 界面上展示的是哪个字段,我这里需要展示名称 * value : 绑定的字段&#xff0c;一般是id */<el-selectv-model"Form.BillNumber"placeholder"请选择"change"changeValue($event)"><el-optionv-for"…

(第六天)初识Spring框架-SSM框架的学习与应用(Spring + Spring MVC + MyBatis)-Java EE企业级应用开发学习记录

SSM框架的学习与应用(Spring Spring MVC MyBatis)-Java EE企业级应用开发学习记录&#xff08;第六天&#xff09;初识Spring框架 ​ 昨天我们已经把Mybatis框架的基本知识全部学完&#xff0c;内容有Mybatis是一个半自动化的持久层ORM框架&#xff0c;深入学习编写动态SQL&a…

Python:列表推导式

相关阅读 Python专栏https://blog.csdn.net/weixin_45791458/category_12403403.html?spm1001.2014.3001.5482 列表推导式使得创建特定列表的方式更简洁。常见的用法为&#xff0c;对序列或可迭代对象中的每个元素应用某种操作&#xff0c;用生成的结果创建新的列表&#xff…

用树形dp+状压维护树上操作的计数问题:0902T3

发现操作数 k ≤ 6 k\le6 k≤6&#xff0c;可以考虑对操作进行状压。 然后找找性质&#xff0c;发现要么删掉一棵子树&#xff0c;要么进去该子树。可以视为每种操作有两种情况。 然后分讨一下当前该如何转移。 树形dp的顺序&#xff1a; 合并子树考虑当前往上的边的方向 …

使用HTTPS模式建立高效爬虫IP服务器详细步骤

嘿&#xff0c;各位爬虫小伙伴们&#xff01;想要自己建立一个高效的爬虫IP服务器吗&#xff1f;今天我就来分享一个简单而强大的解决方案——使用HTTPS模式建立工具&#xff01;本文将为你提供详细的操作步骤和代码示例&#xff0c;让你快速上手&#xff0c;轻松建立自己的爬虫…

查看GPU占用率

如何监控NVIDIA GPU 的运行状态和使用情况_nvidia 85c_LiBiGo的博客-CSDN博客设备跟踪和管理正成为机器学习工程的中心焦点。这个任务的核心是在模型训练过程中跟踪和报告gpu的使用效率。有效的GPU监控可以帮助我们配置一些非常重要的超参数&#xff0c;例如批大小&#xff0c;…

【数据结构与算法篇】手撕八大排序算法之交换排序

​&#x1f47b;内容专栏&#xff1a; 《数据结构与算法篇》 &#x1f428;本文概括&#xff1a;常见交换排序包括冒泡排序与快速排序&#xff0c;本篇讲述冒泡排序与快速排序的思想及实现、复杂度分析。 &#x1f43c;本文作者&#xff1a; 花 蝶 &#x1f438;发布时间&#…

Mysql的page,索引,Explain Type等基本常识

Mysql的基本问题 Mysql 为什么建议使用自增id&#xff1f; 因为id&#xff08;主键&#xff09;是自增的话&#xff0c;那么在有序的保存用户数据到页中的时候&#xff0c;可以天然的保存&#xff0c;并且是在聚集索引&#xff08;id&#xff09;中的叶子节点可以很好的减少插…

Django报错:SystemCheckError: System check identified some issues解决办法

今天练习django自定义标签时&#xff0c;一开始在APPbook中写了自定义标签book_tags.py 测试成功&#xff0c;之后新建了一个APPblogs&#xff0c;测试在blogs中创建模板使用自定义标签&#xff0c;于是直接把book/templatetags包直接赋值到blogs目录里。在页面里加载自定义标…

84. 柱状图中最大的矩形

84. 柱状图中最大的矩形 C代码&#xff1a;暴力&#xff1a;遍历所有可能 int largestRectangleArea(int* heights, int heightsSize){// 直接遍历所有可能&#xff1a;超出时间限制int ans 0;for (int l 0; l < heightsSize; l) {int minHeight INT_MAX;for (int r l…

OpenCV(八):图像二值化

目录 1.固定值二值化 2.自适应阈值二值化 3.Android JNI完整代码 1.固定值二值化 固定阈值二值化是OpenCV中一种简单而常用的图像处理技术&#xff0c;用于将图像转换为二值图像。在固定阈值二值化中&#xff0c;像素值根据一个预定义的阈值进行分类&#xff0c;大于阈值的…

Redis—常用数据结构

Redis—常用数据结构 &#x1f50e;数据结构与内部编码 Redis 中常用的数据结构包括 Strings—字符串Hashes—哈希表Lists—列表Sets—集合Sorted sets—有序集合 Redis 底层在实现上述数据结构时, 会在源码层面针对上述实现进行特定优化, 以达到节省时间 / 节省空间的效果 …