新职课(chapter5-1)

2023-10-17 06:48
文章标签 chapter5 职课

本文主要是介绍新职课(chapter5-1),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 数据库
    • JDBC
    • SQL注入
    • 两表关系
    • 事务
    • 批处理
    • 工具类
    • 连接池
  • Web
    • Tomcat

数据库

  • 基础的原理就不讲了,直接看Java中的操作
  • 大部分数据库操作都是查询,复杂查询按照套路走
    • 合并查询
    • 内连查询
    • 外连查询

JDBC

  • Java应用通过JDBC API调用驱动,操作对应的数据库
    在这里插入图片描述

  • 核心组件
    在这里插入图片描述

  • 使用步骤(六步)

    • 导包:import java.sql.*
    • 初始化驱动
    • 连接:DriverManager.getConnection()
    • 执行查询
    • 提取数据
    • 关闭连接
    // 在project structure中创建Library引入jar包
    public static void main(String[] args) {Connection conn = null;Statement stat = null;ResultSet result = null;try {// 1. 加载驱动Class.forName("com.mysql.cj.jdbc.Driver");  // 反射获取驱动类String username = "root";String password = "123456";String url = "jdbc:mysql://localhost:3306/flask?serverTimezone=UTC";    // 数据库名称 falsk, 注意格式// 2. 获取连接conn = DriverManager.getConnection(url, username, password);   // Home End// 3. 定义SQLstat = conn.createStatement();result = stat.executeQuery("select * from short_url;");// int effect = stat.executeUpdate("insert into short_url(token, url) values('test2', 'http://porn.com')");// 插入,返回受影响行数// 4. 取结果while (result.next()) {System.out.println("id:"+result.getString("id")+" token:"+result.getString("token"));}// 如果是增删改:// if (effect > 0) {//     System.out.println("执行成功!");// }else {//     System.out.println("执行失败!");// }} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException throwables) {throwables.printStackTrace();} finally {// 5. 关闭连接try {if (result != null) {result.close();}if (stat != null) {stat.close();}if (conn != null) {conn.close();   // 倒序关闭}} catch (SQLException throwables) {throwables.printStackTrace();}}
    }
    

SQL注入

  • 在执行的SQL语句中加入一些特殊字符,让引擎误识别,能绕开权限获取数据,造成数据的不安全
  • 避免SQL注入的方法:创建预状态通道
  • 在使用JDBC的第三步,通过createStatement创建的是状态通道,现在使用PreparedStatement创建预通道
    public static void main(String[] args) {Connection conn = null;Statement stat = null;PreparedStatement pstmt = null;ResultSet result = null;try {// 1. 加载驱动Class.forName("com.mysql.cj.jdbc.Driver");  // 反射获取驱动类String username = "root";String password = "123456";String url = "jdbc:mysql://localhost:3306/flask?serverTimezone=UTC";    // 数据库名称 falsk, 注意格式// 2. 获取连接conn = DriverManager.getConnection(url, username, password);   // Home End// 3. 定义SQL并执行// stat = conn.createStatement();String sql = "select * from short_url where id=?";  // 所有的参数使用 ? 占位pstmt = conn.prepareStatement(sql);String id = "1";// 替换占位符pstmt.setString(1, id); // 使用字符串result = pstmt.executeQuery();// result = stat.executeQuery("select * from short_url;"); // 查询// 4. 取结果while (result.next()) {System.out.println("id:"+result.getString("id")+" token:"+result.getString("token"));}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException throwables) {throwables.printStackTrace();} finally {// 5. 关闭连接try {if (result != null) {result.close();}if (pstmt != null) {stat.close();}if (conn != null) {conn.close();   // 倒序关闭}} catch (SQLException throwables) {throwables.printStackTrace();}}
    }
    
    • 预状态通道会先编译sql语句,再去执行,比statement执行效率高
    • 预状态通道支持占位符?,给占位符赋值的时候,位置从1开始
    • 预状态通道可以防止sql注入,原因:预状态通道在处理值的时候全部以字符串的方式处理

两表关系

  • 数据库通过外键建立两表关系
  • 实体类通过属性的方式建立两表关系,类似对象关系映射ORB
    • 类名=表名
    • 属性名=字段名
  • 使用下面的数据表练习
    CREATE TABLE `student` (
    `stuid` int(11) NOT NULL AUTO_INCREMENT,
    `stuname` varchar(255) DEFAULT NULL,
    `teacherid` int(11) DEFAULT NULL,
    PRIMARY KEY (`stuid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
    INSERT INTO `student` VALUES ('1', 'aaa', '3');
    INSERT INTO `student` VALUES ('2', 'bb', '1');
    INSERT INTO `student` VALUES ('3', 'cc', '3');
    INSERT INTO `student` VALUES ('4', 'dd', '1');
    INSERT INTO `student` VALUES ('5', 'ee', '1');
    INSERT INTO `student` VALUES ('6', 'ff', '2');
    DROP TABLE IF EXISTS `teacher`;
    CREATE TABLE `teacher` (
    `tid` int(11) NOT NULL AUTO_INCREMENT,
    `tname` varchar(255) DEFAULT NULL,
    PRIMARY KEY (`tid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
    INSERT INTO `teacher` VALUES ('1', '张三老师');
    INSERT INTO `teacher` VALUES ('2', '李四老师');
    INSERT INTO `teacher` VALUES ('3', '王五');
    -- teacher表是主表,一个tid对应多个学生,所以后面的Java代码中要多加个集合属性
    
    5
  • 接下来创建对应的类和属性,显然,这些类都是bean
    public class Student {/*学生表是多端,或者说子表*/private int stuid;private String stuname;// 外键列一般不生成方法private int teacherid;public int getStuid() {return stuid;}public void setStuid(int stuid) {this.stuid = stuid;}public String getStuname() {return stuname;}public void setStuname(String stuname) {this.stuname = stuname;}
    }public class Teacher {/*教师表是一端,受学生表外键的约束*/private int tid;private String tname;private List<Student> list=new ArrayList<Student>(); // 新增属性,一对多查询,保存学生信息public int getTid() {return tid;}public void setTid(int tid) {this.tid = tid;}public String getTname() {return tname;}public void setTname(String tname) {this.tname = tname;}public List<Student> getList() {return list;}public void setList(List<Student> list) {this.list = list;}
    }
    
  • 创建dao层,定义一对多的查询接口和实现类(一个老师对应多个学生)
    3
    // TeacherDaoImpl.java
    public class TeacherDaoImpl implements TeacherDao {@Overridepublic Teacher getById(int tid) {Connection conn = null;PreparedStatement pstmt = null;ResultSet result = null;try {// 1. 加载驱动Class.forName("com.mysql.cj.jdbc.Driver");  // 反射获取驱动类String username = "root";String password = "123456";String url = "jdbc:mysql://localhost:3306/flask?serverTimezone=UTC";    // 数据库名称 falsk, 注意格式// 2. 获取连接conn = DriverManager.getConnection(url, username, password);   // Home End// 3. 定义SQL并执行  预通道String sql = "select * from student s, teacher t where s.teacherid=t.tid and tid=?";  // 所有的参数使用 ? 占位pstmt = conn.prepareStatement(sql);pstmt.setInt(1, tid); // 都要使用字符串,数据库引擎会解析result = pstmt.executeQuery();// 4. 取结果Teacher teacher = new Teacher();List<Student> students = new ArrayList<Student>();while (result.next()) {// 取出各自信息,注意顺序teacher.setTid(result.getInt("tid"));teacher.setTname(result.getString("tname"));Student student = new Student();student.setStuid(result.getInt("stuid"));student.setStuname(result.getString("stuname"));students.add(student);}teacher.setList(students);return teacher;} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException throwables) {throwables.printStackTrace();} finally {// 5. 关闭连接try {if (result != null) {result.close();}if (pstmt != null) {pstmt.close();}if (conn != null) {conn.close();   // 倒序关闭}} catch (SQLException throwables) {throwables.printStackTrace();}}return null;}
    }
    
    // test/Teac.java
    public static void main(String[] args) {// 操作数据库都会定义一个dao层,这里的dao和sql包,类似MVC模型的MTeacherDao daot = new TeacherDaoImpl(); // Impl是具体实现,类似List和ArrayListTeacher teacher = daot.getById(1);System.out.println("老师姓名:"+teacher.getTname());// 一查多List<Student> students = teacher.getList();for (Student student:students) {System.out.println("\tsname: "+student.getStuname());}
    }
    
  • 多对一查询(每个学生都带上老师信息),也是类似的,在Student类中增加属性保存老师信息呗
    // 增加属性,多对一查询
    private Teacher teacher;public Teacher getTeacher() {return teacher;
    }public void setTeacher(Teacher teacher) {this.teacher = teacher;
    }
    
    • 一对多:一方中有一个多方的集合
    • 多对一:多方中有一个一方的数据
  • 一对一:用的比较少,就是写SQL的区别,其他一样,两个表都要新增保存对方数据的属性
  • 多对多,例如学生和科目,用到如下表:
    CREATE TABLE `middle` (
    `middleid` int(11) NOT NULL AUTO_INCREMENT,
    `stuid` int(11) DEFAULT NULL,
    `subid` int(11) DEFAULT NULL,
    PRIMARY KEY (`middleid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;INSERT INTO `middle` VALUES ('1', '1', '1');
    INSERT INTO `middle` VALUES ('2', '1', '2');
    INSERT INTO `middle` VALUES ('3', '1', '3');
    INSERT INTO `middle` VALUES ('4', '1', '5');
    INSERT INTO `middle` VALUES ('5', '2', '2');
    INSERT INTO `middle` VALUES ('6', '3', '2');
    INSERT INTO `middle` VALUES ('7', '4', '2');
    INSERT INTO `middle` VALUES ('8', '5', '2');
    INSERT INTO `middle` VALUES ('9', '6', '2');DROP TABLE IF EXISTS `student`;
    CREATE TABLE `student` (
    `stuid` int(11) NOT NULL AUTO_INCREMENT,
    `stuname` varchar(255) DEFAULT NULL,
    `teacherid` int(11) DEFAULT NULL,
    PRIMARY KEY (`stuid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;INSERT INTO `student` VALUES ('1', '张三', '3');
    INSERT INTO `student` VALUES ('2', '李四', '1');
    INSERT INTO `student` VALUES ('3', '王五', '3');
    INSERT INTO `student` VALUES ('4', '赵六', '1');
    INSERT INTO `student` VALUES ('5', '花花', '1');
    INSERT INTO `student` VALUES ('6', '潇潇', '2');DROP TABLE IF EXISTS `subject`;
    CREATE TABLE `subject` (
    `subid` int(11) NOT NULL AUTO_INCREMENT,
    `subname` varchar(255) DEFAULT NULL,
    PRIMARY KEY (`subid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;INSERT INTO `subject` VALUES ('1', 'java');
    INSERT INTO `subject` VALUES ('2', 'ui');
    INSERT INTO `subject` VALUES ('3', 'h5');
    INSERT INTO `subject` VALUES ('4', 'c');
    INSERT INTO `subject` VALUES ('5', 'c++');
    INSERT INTO `subject` VALUES ('6', 'c#');
    
    • 多对多要用到中间表middle;创建对应的类
    • 在Student类和Subject类中增加相应的属性配置
    // 配置多对多,增加属性
    private List<Subject> subjects;public List<Subject> getSubjects() {return subjects;
    }public void setSubjects(List<Subject> subjects) {this.subjects = subjects;
    }
    
    public class Subject {private int subid;private String subname;// 配置多对多,新增学生集合private List<Student> students;public List<Student> getStudents() {return students;}public void setStudents(List<Student> students) {this.students = students;}public int getSubid() {return subid;}public void setSubid(int subid) {this.subid = subid;}public String getSubname() {return subname;}public void setSubname(String subname) {this.subname = subname;}
    }
    
    • dao层定义接口和实现类,并测试
    // 代码很长,这里就放两个SQL
    // select * from student s, subject sub, middle m where s.stuid=m.stuid and sub.subid=m.subid and s.stuid=?
    // select * from subject sub, student s, middle m where s.stuid=m.stuid and sub.subid=m.subid and s.subid=?
    // 剩下的就是JDBC五步骤,分开来看还是用中间表实现了,一对多查询
    

事务

  • 事务特点:ACID(背)
    4
  • 一般设置手动提交
    // 获取连接时
    conn.setAutoCommit(false);  // 不自动提交
    
  • 可以设置保存点 savepoints,回滚时可以指定到某个点,而不是全部失败
    public static void main(String[] args) {Connection conn = null;Statement stat = null;PreparedStatement pstmt = null;Savepoint sp1 = null;try {// 1. 加载驱动Class.forName("com.mysql.cj.jdbc.Driver");  // 反射获取驱动类String username = "root";String password = "123456";String url = "jdbc:mysql://localhost:3306/flask?serverTimezone=UTC";// 2. 获取连接conn = DriverManager.getConnection(url, username, password);conn.setAutoCommit(false);  // 不自动提交// 3. 定义SQL并执行String sql_a = "insert into middle(stuid, subid) values(6, 3)";pstmt = conn.prepareStatement(sql_a);int result = pstmt.executeUpdate();// 设置一个保存点------------------sp1 = conn.setSavepoint("sp1");// 手动失败-----------------------System.out.println(5/0);String sql_b = "insert into middle(stuid, subid) values(2, 3)";pstmt = conn.prepareStatement(sql_b);int result2 = pstmt.executeUpdate();// 手动提交事务conn.commit();// 4. 取结果if (result > 0) {System.out.println("执行成功!");} else {System.out.println("执行失败!");}} catch (Exception e) {// 注意这里要用父类Exception,不然不走这块的的异常e.printStackTrace();try {// conn.rollback(); // 一次性全部回滚conn.rollback(sp1);conn.commit();  // 这次提交的就是回滚点之前的那个插入操作} catch (SQLException throwables) {throwables.printStackTrace();}} finally {// 5. 关闭连接try {if (pstmt != null) {pstmt.close();}if (conn != null) {conn.close();   // 倒序关闭}} catch (SQLException throwables) {throwables.printStackTrace();}}
    }
    
  • 用到事务的地方很多,比如转账,一个减钱,一个加钱

批处理

  • 批量更新数据库数据,我们在预通道方式下测试,相比通道就是多了一个传参的操作,不是直接传SQL到addBatch
    public static void main(String[] args) {Connection conn = null;PreparedStatement pstmt = null;Savepoint sp1 = null;try {// 1. 加载驱动Class.forName("com.mysql.cj.jdbc.Driver");  // 反射获取驱动类String username = "root";String password = "123456";String url = "jdbc:mysql://localhost:3306/flask?serverTimezone=UTC";// 2. 获取连接conn = DriverManager.getConnection(url, username, password);conn.setAutoCommit(false);  // 不自动提交// 3. 定义SQL并执行String sql_a = "insert into teacher(tname) values(?)";pstmt = conn.prepareStatement(sql_a);// 批处理---------------pstmt.setString(1, "Roy");pstmt.addBatch();pstmt.setString(1, "Allen");pstmt.addBatch();pstmt.setString(1, "Andy");pstmt.addBatch();int[] result = pstmt.executeBatch();    // 返回每条语句影响的行数// 设置一个保存点sp1 = conn.setSavepoint("sp1");// 手动提交事务conn.commit();// 4. 取结果for (int i:result) {System.out.println(i);}} catch (Exception e) {// 注意这里要用父类Exception,不然不走这块的的异常e.printStackTrace();try {conn.rollback(sp1);conn.commit();  // 这次提交的就是回滚点之前的那个插入操作} catch (SQLException throwables) {throwables.printStackTrace();}} finally {// 5. 关闭连接try {if (pstmt != null) {pstmt.close();}if (conn != null) {conn.close();   // 倒序关闭}} catch (SQLException throwables) {throwables.printStackTrace();}}
    }
    
  • 可以通过类反射执行上述所有的SQL操作,了解即可

工具类

  • 为了避免每次写一堆重复步骤,封装一个工具类,包含连接库、增删改查的方法
    import java.sql.*;
    import java.util.List;public class DBUtil {//1.定义需要的工具类对象protected Connection connection=null;protected PreparedStatement pps=null;protected ResultSet rs=null;protected int k=0;//受影响的行数private String url="jdbc:mysql://localhost:3306/flask";private String username="root";private String password="123456";//2.加载驱动static{try {Class.forName("com.mysql.cj.jdbc.Driver");} catch (ClassNotFoundException e) {e.printStackTrace();}}//3.获得连接protected Connection getConnection(){try {connection=DriverManager.getConnection(url,username,password);} catch (SQLException e) {e.printStackTrace();}return connection;}//4.创建通道protected PreparedStatement getPps(String sql){try {getConnection();//insert into users values(?,?,?,?,)pps=connection.prepareStatement(sql);} catch (SQLException e) {e.printStackTrace();}return pps;}//5.给占位符赋值 list中保存的是给占位符所赋的值private void setParams(List list){try {if(list!=null&&list.size()>0){for (int i=0;i<list.size();i++) {pps.setObject(i+1,list.get(i));}}} catch (SQLException e) {e.printStackTrace();}}//6.增删改调取的方法protected int update(String sql,List params){try {getPps(sql);setParams(params);k= pps.executeUpdate();} catch (SQLException e) {e.printStackTrace();}return k;}//7.查询时调取protected ResultSet query(String sql, List list){try {getPps(sql);setParams(list);rs=pps.executeQuery();return rs;} catch (SQLException e) {e.printStackTrace();}return null;}// 8. 关闭资源protected void closeall(){try {if (rs != null) {rs.close();}if (pps != null) {pps.close();}if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}
    }
    
  • 在dao层新增接口,并实现
    @Override
    public Student getByStuId(int id) {Student student = new Student();String sql = "select * from student where stuid=?";List list = new ArrayList();list.add(id);   // 预参数集合ResultSet result = query(sql, list);try {if (result.next()) {student.setStuid(result.getInt("stuid"));student.setStuname(result.getString("stuname"));}return student;} catch (Exception e) {e.printStackTrace();} finally {closeAll();}return null;
    }// test.java
    public static void main(String[] args) {TeacherDao daot = new TeacherDaoImpl();Student student = daot.getByStuId(1);	// 单表查询System.out.println(student.getStuname());
    }
    
  • 一般在开发过程中,将固定在工具类中的字符串,放在属性文件
    • 名称必须是xxx.properties
    driver=com.mysql.cj.jdbc.Driver
    url=jdbc:mysql://localhost:3306/flask?serverTimezone=UTC
    user=root
    password=123456
    
    // 修改DBUtil
    private static String url;
    private static String username;
    private static String password;
    private static String driverName;//2.加载驱动
    static{// 有两种方式try {InputStream inputStream = DBUtil.class.getClassLoader().getResourceAsStream("db.properties");Properties properties = new Properties();properties.load(inputStream);driverName = properties.getProperty("driver");url = properties.getProperty("url");username = properties.getProperty("user");password = properties.getProperty("password");Class.forName(driverName);// 第二种方式ResourceBundle bundle = ResourceBundle.getBundle("db");driverName = bundle.getString("driver");url = bundle.getString("url");username = bundle.getString("user");password = bundle.getString("password");Class.forName(driverName);} catch (ClassNotFoundException | IOException e) {e.printStackTrace();}
    }
    

连接池

  • 将数据库连接作为对象存储在内存中,请求数据库时,从连接池中取出一个已建立的空闲连接对象
  • 自定义连接池
    • 需要定义指定的属性和方法
    • 属性: 集合,放置连接
    • 方法: 获取连接方法、回收连接方法
    public class Pool{static LinkedList<Connection> list = new LinkedList<Connection>();static{for (int i = 0; i < 10; i++) {// 在池子里初始化十个连接Connection connection = JDBCUtils.newInstance().getConnection();list.add(connection);}}/*** 从连接池子中获取连接的方式* @return*/public static Connection getConnection(){if (list.isEmpty()) {//JDBCUtils类是自定义类,封装了连接数据库的信息代码Connection connection = JDBCUtils.newInstance().getConnection();list.addLast(connection);}Connection conn = list.removeFirst();return conn;}/*** 返回到连接池子中*/public static void addBack(Connection conn){if (list.size() >= 10) {try {conn.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}else{list.addLast(conn); //10}}/*** 获取连接池子中连接数量的方法*/public static int getSize(){return list.size();}
    }
    
  • Java也定义了接口(规范),让我们实现连接池,具体实现代码如下
    • DataSource 接口有一个弊端,没有提供回收链接的方法,先装饰一下
    public class MyConnection implements Connection {//将被装饰者导入private Connection conn;private LinkedList<Connection> list;public MyConnection(Connection conn, LinkedList<Connection> list) {super();this.conn = conn;this.list = list;}@Overridepublic <T> T unwrap(Class<T> iface) throws SQLException {return conn.unwrap(iface);}@Overridepublic boolean isWrapperFor(Class<?> iface) throws SQLException {return conn.isWrapperFor(iface);}@Overridepublic Statement createStatement() throws SQLException {return conn.createStatement();}@Overridepublic PreparedStatement prepareStatement(String sql) throws SQLException {return conn.prepareStatement(sql);}@Overridepublic CallableStatement prepareCall(String sql) throws SQLException {return null;}@Overridepublic String nativeSQL(String sql) throws SQLException {return null;}@Overridepublic void setAutoCommit(boolean autoCommit) throws SQLException {    }@Overridepublic boolean getAutoCommit() throws SQLException {return false;}@Override基于规范实现的连接池public void commit() throws SQLException {conn.commit();}@Overridepublic void rollback() throws SQLException {conn.rollback();}@Overridepublic void close() throws SQLException {list.addLast(conn);}...
    }
    
    // 实现 DataSource 连接池
    public class DataSourcePool implements DataSource{static LinkedList<Connection> list = new LinkedList<Connection>();static{for (int i = 0; i < 10; i++) {Connection connection = JDBCUtils.newInstance().getConnection();list.add(connection);}}public static int getSize(){return list.size();}@Overridepublic Connection getConnection() throws SQLException {Connection conn = list.removeFirst();MyConnection conn1 = new MyConnection(conn, list);return conn1;}  @Overridepublic PrintWriter getLogWriter() throws SQLException {return null;}@Overridepublic void setLogWriter(PrintWriter out) throws SQLException { }@Overridepublic void setLoginTimeout(int seconds) throws SQLException { }@Overridepublic int getLoginTimeout() throws SQLException {return 0;}@Overridepublic Logger getParentLogger() throws SQLFeatureNotSupportedException {return null;}@Overridepublic <T> T unwrap(Class<T> iface) throws SQLException {return null;}@Overridepublic boolean isWrapperFor(Class<?> iface) throws SQLException {return false;}@Overridepublic Connection getConnection(String username, String password) throwsSQLException {return null;}
    }
    
    7
  • 也就是说,不需要我们写连接池的代码,用上面的某种就可以
  • 试一下DBCP的使用,将commons-dbcp-1.4.jar和commons-pool-1.5.6.jar导入进Modules
    // 重写DBUtils
    public class DBUtil {//1.定义需要的工具类对象protected Connection connection=null;protected PreparedStatement pps=null;protected ResultSet rs=null;protected int k=0;//受影响的行数private static String url;private static String username;private static String password;private static String driverName;private static BasicDataSource basicDataSource = new BasicDataSource();//2.加载驱动static{ResourceBundle bundle = ResourceBundle.getBundle("db");driverName = bundle.getString("driver");url = bundle.getString("url");username = bundle.getString("user");password = bundle.getString("password");basicDataSource.setUsername(username);basicDataSource.setPassword(password);basicDataSource.setUrl(url);basicDataSource.setDriverClassName(driverName);basicDataSource.setInitialSize(15);}//3.获得连接protected Connection getConnection(){try {connection=basicDataSource.getConnection();} catch (SQLException e) {e.printStackTrace();}return connection;}//4.创建通道protected PreparedStatement getPps(String sql){try {getConnection();//insert into users values(?,?,?,?,)pps=connection.prepareStatement(sql);} catch (SQLException e) {e.printStackTrace();}return pps;}//5.给占位符赋值 list中保存的是给占位符所赋的值private void setParams(List list){try {if(list!=null&&list.size()>0){for (int i=0;i<list.size();i++) {pps.setObject(i+1,list.get(i)); // 从1开始}}} catch (SQLException e) {e.printStackTrace();}}//6.增删改调取的方法protected int update(String sql,List params){try {getPps(sql);setParams(params);k= pps.executeUpdate();} catch (SQLException e) {e.printStackTrace();}return k;}//7.查询时调取protected ResultSet query(String sql, List list){// 传入要执行的SQL和参数数组 (预通道)try {getPps(sql);setParams(list);rs=pps.executeQuery();return rs;} catch (SQLException e) {e.printStackTrace();}return null;}// 8. 关闭资源protected void closeAll(){try {if (rs != null) {rs.close();}if (pps != null) {pps.close();}if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}
    }
    
  • dbcp没有自动回收空闲连接的功能,c3p0有自动回收空闲连接功能
  • 在src下创建c3p0-config.xml,配置文件,名称固定;然后导入c3p0-0.9.1.2.jar
    <?xml version="1.0" encoding="UTF-8"?>
    <c3p0-config><default-config><property name="driverClass">com.mysql.cj.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql://localhost:3306/flask?serverTimezone=UTC</property><property name="user">root</property><property name="password">123456</property><!-- 等待连接的超时时间,默认为0,代表无限等待,单位是毫秒 --><property name="checkoutTimeout">30000</property><!-- 检查空闲连接  默认为0 代表不检查 --><property name="idleConnectionTestPeriod">30</property><!-- 初始化连接 --><property name="initialPoolSize">10</property><!-- 最大空闲时间,超过这个时间的连接将被丢弃,默认为0,代表永远不关闭 --><property name="maxIdleTime">50</property><!-- 最大连接数 --><property name="maxPoolSize">100</property><!-- 最小连接数 --><property name="minPoolSize">10</property><!-- preparedStatement的缓存大小 --><property name="maxStatements">200</property><!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。默认值: 3 --><property name="AcquireIncrement">5</property></default-config>
    </c3p0-config>
    
    • 你没看错,db.properties 都不需要了
    // 只需要改两行,不需要static静态代码块了
    ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
    //3.获得连接
    protected Connection getConnection(){try {connection = comboPooledDataSource.getConnection();// connection=basicDataSource.getConnection();} catch (SQLException e) {e.printStackTrace();}return connection;
    }
    
  • 目前,最流行的是阿里开发的德鲁伊,使用过程类似DBCP,需要db.properties
    // druid
    private static DruidDataSource druidDataSource = new DruidDataSource();
    

Web

  • 学习目标
    8
    9

Tomcat

  • 常见的开发模式:BS和CS
    • 浏览器——服务器:通过浏览器访问网站
    • 客户端——服务器:有客户端,不会实时更新代码
  • Tomcat是目前最流行的Java服务器
    • 服务器是部署在操作系统之上的,提供代码运行环境的容器
  • 下载与安装
    • 使用apache-tomcat-8.5.34,免安装,官网
    • 要熟悉解压后每个文件夹的作用
      11
      12
      13
    • 启动:双击bin/startup.bat,如果闪退,可能是8080端口占用;也可能需要修改此文件
      netstat -ano|findstr "8080"	# 找到PID
      tasklist|findstr "PID"# 或者在startup.首行加一句
      SET JAVA_HOME=D:\Java
      
  • 访问看是否启动:http://localhost:8080/
    • 使用shutdown.bat可以关闭
  • 在我们自己编写的项目目录`webapps``下
    • 新建文件夹,相当于创建一个项目
    • 新建HTML页面,测试访问
  • IDEA整合Tomcat
    • 可以大致参考:链接1,链接2
      14
      15
    • 使用链接2,先直接创建普通Java项目
  • 点击启动,自动打开浏览器访问了:http://localhost:8080/demo_war_exploded/
    • 可以在tomcat配置文件中修改端口号
  • 路径太长,一般会在上图中的页面修改,设置Application context为 /
  • 默认打成war包,名称就是Artifact的名称,也是项目名称
    web工程: src: 存放java源代码 .java文件,下设不同packageweb: web资源WEB-INF(受服务器保护,浏览器不能直接访问)lib-存放第三方jar包web.xml 为整个web工程的配置部署描述文件,servlet listener filter session等配置信息index.jsp 在浏览器中输入工程名时,默认访问的资源
    
  • 增加管理员信息:conf/tomcat-users.xml,感觉没啥用
    <role rolename="manager-gui"/>
    <user username="tomcat" password="tomcat" roles="manager-gui"/>
    

这篇关于新职课(chapter5-1)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/223655

相关文章

【Chapter5】死锁与饥饿,计算机操作系统教程,第四版,左万利,王英

文章目录 1.1 什么是死锁1.2 死锁的类型1.2.1 竞争资源引起的死锁1.2.2 进程间通信引起的死锁1.2.3 其他原因引起的死锁 1.3 死锁产生必要条件1.4 死锁的处理策略1.5 死锁的预防1.5.1 破坏资源独占条件1.5.2 破坏不可剥夺条件1.5.3 破坏保持申请条件1.5.4 破坏循环等待条件 1.6 死锁的避免1.6.1 什么是安全序列1.6.2 安全序列、不安全状态

【java程序设计期末复习】chapter5 子类的继承

子类的继承 继承是一种由已有的类创建新类的机制。利用继承,我们可以先创建一个共有属性的一般类,根据该一般类再创建具有特殊属性的新类,新类继承一般类的状态和行为,并根据需要增加它自己的新的状态和行为。由继承而得到的类称为子类,被继承的类称为父类(超类)。 Java不支持多重继承(子类只能有一个父类)。 使用关键字extends来定义一个类的子类,格式如下: class Student e

列出游戏库存的字典功能-用Python自动化无聊的东西-chapter5

想象一下,被征服的龙的战利品被表示为这样的字符串: dragonLoot = ['gold coin', 'dagger', 'gold coin', 'gold coin', 'ruby'] 编写一个名为的函数addToInventory(inventory, addedItems),其中inventory参数是表示玩家的库存的字典(如上一个项目中所示),addedItems参数是一个列表d

记录客人带来的食物的总数-用Python自动化无聊的东西-chapter5

当您模拟更复杂的事情时,您可能会发现需要包含其他字典和列表的字典和列表。列表可用于包含一系列有序的值,并且字典对于将键与值相关联很有用。例如,这是一个使用包含其他字典的字典的程序,以查看谁带来了野餐。该totalBrought()功能可以读取此数据结构,并计算所有客人所携带的物品的总数。 提示:应用到字典中嵌套字典,get()获取。 源代码: allGuests = {'Alice': {'

《机器学习(周志华)》Chapter5 神经网络 课后习题答案

若用线性函数作为神经元激活函数则无法处理复杂的非线性问题。 激活函数在神经网络中的作用 相当于每个神经元都在进行对率回归 学习率控制着梯度下降的搜索步长,学习率过大收敛过程容易发生振荡,学习率过小收敛速度过慢 https://blog.csdn.net/victoriaw/article/details/78075266 https://blo

《机器学习(周志华)》Chapter5 神经网络

一、神经元模型: θ为阀值,输入样本x与权重w相乘再求和若大于阀值θ则兴奋即输出为1,否则抑制输出为0,f为激活函数经典的有Sigmoid函数 二、感知机与多层网络: 感知机由两层神经元组成 若θ设置为常数,则可训练出权重w 多层前馈神经网络: 三、误差逆传播算法 称BP算法,采用链式求导法则求出各层权重及阀值的导数。 假设神经网络的输出为: 则均

Java for the Web With Servlets, JSP, and EJB(Part1-Chapter5)Session Management

文章目录 一、为什么需要Session二、信息管理2.1 Server端不存储信息,直接将信息返回给Client(危险!)2.1.1 Server端返回HTML页面的2.1.2 Server端返回JSON的2.1.2 Server/Client将信息写入Cookie 2.2 Server端存储信息,返回Client端一个凭据(没那么危险)2.2.1 凭据使用Cookie或直接写在URL中2.

Java并发编程实战读书笔记-Chapter5-1

Java并发编程实战读书笔记-Chapter5 5.1 同步容器类5.1.1 同步容器类的问题5.1.2 迭代器ConcurrentModificationException 第4章介绍了构造线程安全类时采用的一些技术,例如将线程安全性委托给现有的线程安全类。委托是创建线程安全类的一个最有效的策略:只需让现有的线程安全类管理所有的状态即可。 Java平台类库包含了丰富的并发基础

【王道数据结构】【chapter5树与二叉树】【P159t15】

设计一个算法将二叉树的叶结点从左到右的顺序连成一个单链表,表头指针为head。二叉树按二叉链表方式存储,链接时用叶结点的右指针来存放单链表指针。 #include <iostream>#include <stack>#include <queue>typedef struct treenode{char data;struct treenode *left;struct treeno

【王道数据结构】【chapter5树与二叉树】【P159t13】

假设二叉树采用二叉链表存储结构,设计一个算法,求非空二叉树b的宽度(即具有节点数最多的那一层的结点个数) #include <iostream>#include <stack>#include <queue>typedef struct treenode{char data;struct treenode *left;struct treenode *right;}treenode