首页 文章 精选 留言 我的

精选列表

搜索[系统详情],共10018篇文章
优秀的个人博客,低调大师

Linux系统CentOS6、CentOS7手动修改IP地址

CentOS_v6 1.打开文件 sh 复制代码 vi /etc/sysconfig/network-scripts/ifcfg-eth0 2.编辑 sh 复制代码 BOOTPROTO=static DNS1=10.0.0.1 IPADDR=10.0.0.70 NETMASK=255.255.255.0 GATEWAY=10.0.0.1 3.保存退出 sh 复制代码 :x 4.重启网络服务 sh 复制代码 service network restart 5.查看修改结果 sh 复制代码 ifconfig CentOS_v7 1.查看网络接口 sh 复制代码 nmcli dev status 2.打开文件(eno16777728为刚刚查看接口的名称) sh 复制代码 vi /etc/sysconfig/network-scripts/ifcfg-ens32 vi /etc/sysconfig/network-scripts/ifcfg-ens192 3.编辑 sh 复制代码 BOOTPROTO=static DNS1=10.0.0.1 IPADDR=10.0.0.70 NETMASK=255.255.255.0 GATEWAY=10.0.0.1 4.保存退出 sh 复制代码 :x 5.重启网络服务 sh 复制代码 service network restart 6.查看修改结果 sh 复制代码 ip addr

优秀的个人博客,低调大师

在线答题系统 WTS 1.0.2 发布,可查看答题卡详情

当前版本v1.0.2 更新内容: 优化:通过内存队列保存提交的答案,也可以配置为数据库中缓存答案 功能:允许用户查看原始试卷 功能:答题室的答题权限,支持通过组织机构和岗位绑定 bugfix:移动端提交答卷时显示完成题数在队列中的沒有加载出来 bugfix:移动端不显示答卷查询按钮(移动端只显示成绩不显示答卷)

优秀的个人博客,低调大师

Java中的jdbc使用详情

简介 JDBC(Java DataBase Connectivity)是Java与数据库的接口规范,由Java 语言编写的类和接口组成,大致分为两类:针对Java程序员的JDBC API和针对数据库开发商的低层的JDBC driver API。而JDBC驱动程序由实施了这些接口的类组成。 JDBC库包括通常与数据库使用相关的操作有: 连接数据库 创建SQL语句 在数据库中执行SQL语句 查看和修改结果记录 一、环境介绍 在mysql中创建一个库shen,并创建user表和插入表的数据。 新建一个Java工程jdbc,并导入数据驱动。 二、详细步骤 1、加载数据库驱动 //1.加载驱动(开发推荐的方式) Class.forName("com.mysql.jdbc.Driver"); 注意:如果连接的是SQL server //1.加载驱动 Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver"); 2、建立连接 1、数据库URL URL用于标识数据库的位置,程序员通过URL地址告诉JDBC程序连接哪个数据库,URL的写法为: jdbc:mysql:[]//localhost:3306/shen ?参数名:参数值 常用数据库URL地址的写法: Oracle:jdbc:oracle:thin:@localhost:1521:shen SqlServer:jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=shen MySql:jdbc:mysql://localhost:3306/shen 注意:如果是localhost:3306,mysql可以简写为jdbc:mysql:///sid(尽量不这样) 2、Connection Jdbc程序中的Connection,它用于代表数据库的链接,Collection是数据库编程中最重要的一个对象,客户端与数据库所有交互都是通过connection对象完成的,创建方法为: Connection conn = DriverManager.getConnection(url,user,pass); 这个对象的常用方法: 方法 描述 createStatement() 创建向数据库发送sql的statement对象。 prepareStatement(sql) 创建向数据库发送预编译sql的PrepareSatement对象。 prepareCall(sql) 创建执行存储过程的callableStatement对象。 setAutoCommit(boolean autoCommit) 设置事务是否自动提交。 commit() 在链接上提交事务。 rollback() 在此链接上回滚事务。 String url = "jdbc:mysql://localhost:3306/shen"; String username = "shen"; String password = "Anxin062039"; Connection conn = null; //2.获取与数据库的链接 conn = DriverManager.getConnection(url, username, password); 3、执行SQL语句 1、Statement Jdbc程序中的Statement对象用于向数据库发送SQL语句,创建方法为: ​ Statement st = conn.createStatement(); Statement对象常用方法: 方法 含义 executeQuery(String sql) 用于向数据发送查询语句。 executeUpdate(String sql) 用于向数据库发送insert、update或delete语句 execute(String sql) 用于向数据库发送任意sql语句 addBatch(String sql) 把多条sql语句放到一个批处理中。 executeBatch() 向数据库发送一批sql语句执行。 Statement st = null; //3.获取用于向数据库发送sql语句的statement st = conn.createStatement(); //4.向数据库发sql String sql = "select id,name,password,email,birthday from users"; st.executeQuery(sql); 2、PreperedStatement PreperedStatement是Statement的孩子,它的实例对象可以通过调用: ​ PreperedStatement st = conn.preparedStatement() PreperedStatement st = null; String sql = "select * from users where name=? and password=?"; //3.获取用于向数据库发送sql语句的Preperedstatement st = conn.preparedStatement(sql);//在此次传入,进行预编译 st.setString(1, username); st.setString(2, password); //4.向数据库发sql st.executeQuery();//在这里不需要传入sql 比较:相对于Statement对象而言 PreperedStatement可以避免SQL注入的问题。 ​ 如:String sql="select * from admin where loginname='"+loginName+"' and loginpwd='"+loginPwd+"'"; ​ 在应用中: ​ -》请输入账号: ​ 333 ​ -》请输入密码: ​ wer'or'1'='1 ​ 实际上发送:select * from admin where loginname='333' and loginpwd='wer'or'1'='1',登录成功! Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。PreparedStatement 可对SQL进行预编译,从而提高数据库的执行效率。 并且PreperedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写。 4、获取结果 Jdbc程序中的ResultSet用于代表Sql语句的执行结果。Resultset封装执行结果时,采用的类似于表格的方式,ResultSet 对象维护了一个指向表格数据行的游标,初始的时候,游标在第一行之前,调用ResultSet.next() 方法,可以使游标指向具体的数据行,进行调用方法获取该行的数据。 1、获取行 ResultSet提供了对结果集进行滚动的方法: next():移动到下一行 Previous():移动到前一行 absolute(int row):移动到指定行 beforeFirst():移动resultSet的最前面。 afterLast() :移动到resultSet的最后面。 2、获取值 ResultSet既然用于封装执行结果的,所以该对象提供的都是用于获取数据的get方法: 获取任意类型的数据 getObject(int index) getObject(string columnName) 获取指定类型的数据,例如: getString(int index) getString(String columnName) 附加: 常用数据类型转换: SQL类型 Jdbc对应方法 返回类型 bit(1),bit(n) getBoolean,getBytes() Boolean,byte[] tinyint getByte() Byte smallint getShort() Short int getInt Int bigint getLong() Long char,varchar,longvarchar getString String text(clob) blob getClob(),getblob() Clob,blob date getDate() java.sql.Date time getTime() java.sql.Time timestamp getTimestamp java.sql.Timestamp ResultSet rs = null; //4.向数据库发sql,并获取代表结果集的resultset String sql = "select id,name,password,email,birthday from users"; rs = st.executeQuery(sql); //5.取出结果集的数据 rs.afterLast(); rs.previous(); System.out.println("id=" + rs.getObject("id")); System.out.println("name=" + rs.getObject("name")); System.out.println("password=" + rs.getObject("password")); System.out.println("email=" + rs.getObject("email")); System.out.println("birthday=" + rs.getObject("birthday")); 或者: //循环取出(id) while(rs.next()) { String id=rs.getString(1);//1代表数据库中表的列数,id在第一列也可以("id")!!! System.out.println(id+" "); } 5、释放资源 Jdbc程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是ResultSet, Statement和Connection对象。 注意:为确保资源释放代码能运行,资源释放代码也一定要放在finally语句中。 //6.关闭链接,释放资源 if(rs!=null){ try{ rs.close(); }catch (Exception e) { e.printStackTrace(); } rs = null; } if(st!=null){ try{ st.close(); }catch (Exception e) { e.printStackTrace(); } } if(conn!=null){ try{ conn.close(); }catch (Exception e) { e.printStackTrace(); } } 三、基本操作 1、DDL /** * 在java中使用ddl语句(credate,drop,backup...) */ package com.shen.study2; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; public class Test1 { public static void main(String[] args) { // TODO Auto-generated method stub Test1 test=new Test1(); } public Test1() { this.lianjie(); } public void lianjie() { //定义需要的对象 PreparedStatement ps=null; Connection ct=null; ResultSet rs=null; try { //初始化对象 //1.加载驱动 Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver"); //2.得到连接(1433表示sql server的默认端口) ct=DriverManager.getConnection("jdbc:microsoft:sqlserver://localhost:1433;databaseName=shen","sa","Anxin062039"); //3.创建Preparestatement,创建数据 ps=ct.prepareStatement("create database vvv"); // ps=ct.prepareStatement("create table xxx");//创建表 // ps=ct.prepareStatement("backup database shen to disk='F:/123.bak'");//备份数据库 //如果执行的是ddl语句 boolean b=ps.execute(); if(b) { System.out.println("创建成功!"); }else { System.out.println("失败"); } } catch (Exception e) { // TODO: handle exception }finally { //关闭资源 try { //为了程序健壮 if(ps!=null) ps.close(); if(ct!=null) ct.close(); } catch (Exception e2) { // TODO: handle exception } } } } 2、CRUD 实例:user public class User { private int id; private String name; private String password; private String email; private Date birthday; //相关的get和set } 连接工具:JdbcUtils import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class JdbcUtils { private static String driver = null; private static String url = null; private static String username = null; private static String password = null; static{ try{ InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties"); Properties prop = new Properties(); prop.load(in); driver = prop.getProperty("driver"); url = prop.getProperty("url"); username = prop.getProperty("username"); password = prop.getProperty("password"); Class.forName(driver); }catch (Exception e) { throw new ExceptionInInitializerError(e); } } public static Connection getConnection() throws SQLException{ return DriverManager.getConnection(url, username,password); } public static void release(Connection conn,Statement st,ResultSet rs){ if(rs!=null){ try{ rs.close(); }catch (Exception e) { e.printStackTrace(); } rs = null; } if(st!=null){ try{ st.close(); }catch (Exception e) { e.printStackTrace(); } } if(conn!=null){ try{ conn.close(); }catch (Exception e) { e.printStackTrace(); } } } } 资源文件:db.properties #driver=com.mysql.jdbc.Driver #url=jdbc:mysql://localhost:3306/shen #username=shen #password=Anxin062039 注意:前面添加#,表示注释。如果改成SQL server直接更改这里即可 功能实现:Demo import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import org.junit.Test; import cn.itcast.utils.JdbcUtils; //使用jdbc对数据库增删改查 public class Demo { @Test public void insert(){ Connection conn = null; Statement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); st = conn.createStatement(); String sql = "insert into users(id,name,password,email,birthday) values(4,'xxx','123','xx@sina.com',to_date('1980-09-09','YYYY-MM-DD'))"; int num = st.executeUpdate(sql); //update if(num>0){ System.out.println("插入成功!!"); } }catch (Exception e) { e.printStackTrace(); }finally{ JdbcUtils.release(conn, st, rs); } } @Test public void delete(){ Connection conn = null; Statement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); String sql = "delete from users where id=4"; st = conn.createStatement(); int num = st.executeUpdate(sql); if(num>0){ System.out.println("删除成功!!"); } }catch (Exception e) { }finally{ JdbcUtils.release(conn, st, rs); } } @Test public void update(){ Connection conn = null; Statement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); String sql = "update users set name='wuwang',email='wuwang@sina.com' where id=3"; st = conn.createStatement(); int num = st.executeUpdate(sql); if(num>0){ System.out.println("更新成功!!"); } }catch (Exception e) { }finally{ JdbcUtils.release(conn, st, rs); } } @Test public void find(){ Connection conn = null; Statement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); String sql = "select * from users where id=1"; st = conn.createStatement(); rs = st.executeQuery(sql); if(rs.next()){ System.out.println(rs.getString("name")); } }catch (Exception e) { }finally{ JdbcUtils.release(conn, st, rs); } } } 四、常见操作 1、处理大数据 如下内容都借助CRUD中的内容 1.存取文本文件(.txt文件) clob用于存储大文本(mysql中无clob,存储大文本采用的是Text) 数据库为: create table testclob ( id int primary key auto_increment, resume text ); public class Demo1 { @Test public void add() { Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); String sql = "insert into testclob(resume) values(?)" st = conn.prepareStatement(sql); //Reader reader = new InputStreamReader(Demo1.class.getClassLoader().getResourceAsStream("1.txt")); String path = Demo1.class.getClassLoader().getResource("1.txt").getPath();//1.txt文件在src下 File file = new File(path); st.setCharacterStream(1, new FileReader(file), (int) file.length());//将该文件添加 int num = st.executeUpdate(); if(num>0){ System.out.println("插入成功!!"); } }catch (Exception e) { e.printStackTrace(); }finally{ JdbcUtils.release(conn, st, rs); } } @Test public void read(){ Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); String sql = "select resume from testclob where id=1"; st = conn.prepareStatement(sql); rs = st.executeQuery(); if(rs.next()){ System.out.println("haha"); Reader reader = rs.getCharacterStream("resume"); char buffer[] = new char[1024]; int len = 0; FileWriter out = new FileWriter("c:\\1.txt"); while((len=reader.read(buffer))>0){ out.write(buffer, 0, len) } out.close(); reader.close(); } }catch (Exception e) { e.printStackTrace(); }finally{ JdbcUtils.release(conn, st, rs); } } } 2.存取二进制文件(图片,视频) 数据库: create table testblob ( id int primary key auto_increment, image longblob ); public class Demo2 { @Test public void add(){ Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); String sql = "insert into testblob(image) values(?)"; st = conn.prepareStatement(sql); String path = Demo2.class.getClassLoader().getResource("01.jpg").getPath(); st.setBinaryStream(1, new FileInputStream(path), (int) new File(path).length()); int num = st.executeUpdate(); if(num>0){ System.out.println("插入成功!!"); } }catch (Exception e) { e.printStackTrace(); }finally{ JdbcUtils.release(conn, st, rs); } } @Test public void read(){ Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); String sql = "select image from testblob where id=?"; st = conn.prepareStatement(sql); st.setInt(1, 1); rs = st.executeQuery(); if(rs.next()){ InputStream in = rs.getBinaryStream("image"); int len = 0; byte buffer[] = new byte[1024]; FileOutputStream out = new FileOutputStream("c:\\1.jpg"); while((len=in.read(buffer))>0){ out.write(buffer,0, len); } in.close(); out.close(); } }catch (Exception e) { e.printStackTrace(); }finally{ JdbcUtils.release(conn, st, rs); } } } 2、批量处理SQL 数据库: create table testbatch ( id int primary key, name varchar2(20) ); 1.通过Statement @Test public void testbatch1(){ Connection conn = null; Statement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); String sql1 = "insert into testbatch(id,name) values(1,'aaa')"; String sql2 = "insert into testbatch(id,name) values(2,'bbb')"; String sql3 = "delete from testbatch where id=1"; st = conn.createStatement(); st.addBatch(sql1); st.addBatch(sql2); st.addBatch(sql3); st.executeBatch(); st.clearBatch(); }catch (Exception e) { e.printStackTrace(); }finally{ JdbcUtils.release(conn, st, rs); } } 2.通过preparedstatement @Test public void testbatch2(){ long starttime = System.currentTimeMillis(); Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); String sql = "insert into testbatch(id,name) values(?,?)"; st = conn.prepareStatement(sql); for(int i=1;i<10000008;i++){ //i=1000 2000 st.setInt(1, i); st.setString(2, "aa" + i); st.addBatch(); if(i%1000==0){ st.executeBatch(); st.clearBatch(); } } st.executeBatch(); }catch (Exception e) { e.printStackTrace(); }finally{ JdbcUtils.release(conn, st, rs); } long endtime = System.currentTimeMillis(); System.out.println("程序花费时间:" + (endtime-starttime)/1000 + "秒!!"); } 3、获取自动生成的主键 数据库: create table test1 ( id int primary key auto_increment,//id自动生成 name varchar(20) ); public class Demo4 { /** * 获取自动生成的主键 */ public static void main(String[] args) { Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); String sql = "insert into test1(name) values(?)"; st = conn.prepareStatement(sql); st.setString(1, "aaa");//在插入name时数据库会自动生成id st.executeUpdate(); rs = st.getGeneratedKeys();//获取生成的主键 if(rs.next()){ System.out.println(rs.getInt(1)); } }catch (Exception e) { e.printStackTrace(); }finally{ JdbcUtils.release(conn, st, rs); } } } 4、调用存储过程 public class Demo5 { /* *jdbc调用存储过程 create procedure p_course_insert @c_no nvarchar(50), @c_name nvarchar(50), @t_name nvarchar(50) as insert into t_course(c_no,c_name,t_name) values(@c_no,@c_name,@t_name) */ public static void main(String[] args) { Connection conn = null; CallableStatement cs = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); cs = conn.prepareCall("{call p_course_inser(?,?,?)}"); cs.setString(1, "xxxxx"); cs.registerOutParameter(2, Types.VARCHAR); cs.execute(); String result = cs.getString(2); System.out.println(result); }catch (Exception e) { e.printStackTrace(); }finally{ JdbcUtils.release(conn, cs, rs); } } } 5、使用事务 1.普通事务的操作 /** * 模似转帐 create table account( id int primary key auto_increment, name varchar(40), money float )character set utf8 collate utf8_general_ci; insert into account(name,money) values('aaa',1000); insert into account(name,money) values('bbb',1000); insert into account(name,money) values('ccc',1000); */ public static void main(String[] args) { Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); conn.setAutoCommit(false); //start transaction,开启事务 String sql1 = "update account set money=money-100 where name='aaa'"; st = conn.prepareStatement(sql1); st.executeUpdate(); String sql2 = "update account set money=money+100 where name='bbb'"; st = conn.prepareStatement(sql2); st.executeUpdate(); conn.commit();//提交 System.out.println("成功!!!"); //log4j }catch (Exception e) { e.printStackTrace();//如果程序出错手动回滚 }finally{ JdbcUtils.release(conn, st, rs); } } 2.设置事务回滚点 public static void main(String[] args) { Connection conn = null; PreparedStatement st = null; ResultSet rs = null; Savepoint sp = null; try{ conn = JdbcUtils.getConnection(); conn.setAutoCommit(false); //start transaction String sql1 = "update account set money=money-100 where name='aaa'"; st = conn.prepareStatement(sql1); st.executeUpdate(); sp = conn.setSavepoint();//在这里设置事务回滚点 String sql2 = "update account set money=money+100 where name='bbb'"; st = conn.prepareStatement(sql2); st.executeUpdate(); int x = 1/0; String sql3 = "update account set money=money+100 where name='ccc'"; st = conn.prepareStatement(sql3); st.executeUpdate(); conn.commit(); }catch (Exception e) { try { conn.rollback(sp);//回滚到该事务点,即该点之前的会正常执行(sql1) conn.commit(); //回滚了要记得提交,如果没有提交sql1将会自动回滚 } catch (SQLException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } e.printStackTrace(); }finally{ JdbcUtils.release(conn, st, rs); } } 3.设置事务隔离级别 conn = JdbcUtils.getConnection(); conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);//避免脏读 conn.setAutoCommit(false); /* Serializable:可避免脏读、不可重复读、虚读情况的发生。(串行化) Repeatable read:可避免脏读、不可重复读情况的发生。(可重复读) Read committed:可避免脏读情况发生(读已提交)。 Read uncommitted:最低级别,以上情况均无法保证。(读未提交) */ 五、使用数据库连接池 1、原因 1.传统连接方法 缺点: 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长。假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出、拓机。 2.数据库连接池 2、开源连接池 1.DBCP 数据库连接池 工具类如下:JdbcUtils_DBCP import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; import javax.sql.DataSource; import org.apache.commons.dbcp.BasicDataSourceFactory; public class JdbcUtils_DBCP { private static DataSource ds = null; static{ try{ InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcpconfig.properties"); Properties prop = new Properties(); prop.load(in); BasicDataSourceFactory factory = new BasicDataSourceFactory(); ds = factory.createDataSource(prop); System.out.println(ds); }catch (Exception e) { throw new ExceptionInInitializerError(e); } } public static Connection getConnection() throws SQLException{ return ds.getConnection(); } public static void release(Connection conn,Statement st,ResultSet rs){ if(rs!=null){ try{ rs.close(); }catch (Exception e) { e.printStackTrace(); } rs = null; } if(st!=null){ try{ st.close(); }catch (Exception e) { e.printStackTrace(); } } if(conn!=null){ try{ conn.close(); }catch (Exception e) { e.printStackTrace(); } } } } 2.C3P0 数据库连接池 连接工具类:JdbcUtils_C3p0(自己在这里更改) import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; import javax.sql.DataSource; import org.apache.commons.dbcp.BasicDataSourceFactory; import com.mchange.v2.c3p0.ComboPooledDataSource; public class JdbcUtils_C3P0 { private static ComboPooledDataSource ds = null; static{ try{ ds = new ComboPooledDataSource(); ds.setDriverClass("com.mysql.jdbc.Driver"); ds.setJdbcUrl("jdbc:mysql://localhost:3306/day16"); ds.setUser("root"); ds.setPassword("root"); ds.setInitialPoolSize(10);//最初连接数 ds.setMinPoolSize(5);//最小连接数 ds.setMaxPoolSize(20);//最大连接数 }catch (Exception e) { throw new ExceptionInInitializerError(e); } } public static Connection getConnection() throws SQLException{ return ds.getConnection(); } public static void release(Connection conn,Statement st,ResultSet rs){ if(rs!=null){ try{ rs.close(); }catch (Exception e) { e.printStackTrace(); } rs = null; } if(st!=null){ try{ st.close(); }catch (Exception e) { e.printStackTrace(); } } if(conn!=null){ try{ conn.close(); }catch (Exception e) { e.printStackTrace(); } } } } 也可以将配置信息放在xml文件中(src下):c3p0-config.xml <?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <default-config> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/day16</property> <property name="user">root</property> <property name="password">root</property> <property name="acquireIncrement">5</property> <property name="initialPoolSize">10</property> <property name="minPoolSize">5</property> <property name="maxPoolSize">20</property> </default-config> <named-config name="mysql"> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/day16</property> <property name="user">root</property> <property name="password">root</property> <property name="acquireIncrement">5</property> <property name="initialPoolSize">10</property> <property name="minPoolSize">5</property> <property name="maxPoolSize">20</property> </named-config> <named-config name="oracle"> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/day16</property> <property name="user">root</property> <property name="password">root</property> <property name="acquireIncrement">5</property> <property name="initialPoolSize">10</property> <property name="minPoolSize">5</property> <property name="maxPoolSize">20</property> </named-config> </c3p0-config> 这样JdbcUtils_C3p0可以改为: /* ds = new ComboPooledDataSource(); ds.setDriverClass("com.mysql.jdbc.Driver"); ds.setJdbcUrl("jdbc:mysql://localhost:3306/day16"); ds.setUser("root"); ds.setPassword("root"); ds.setInitialPoolSize(10);//最初连接数 ds.setMinPoolSize(5);//最小连接数 ds.setMaxPoolSize(20);//最大连接数 */ ds = new ComboPooledDataSource(""mysql"");//如果默认()

优秀的个人博客,低调大师

Android RecyclerView 动画展开item显示详情

stackoverflow上看到这个问题,答主给了个demohttp://stackoverflow.com/questions/27446051/recyclerview-animate-item-resize 看懂了之后发个博,记录一下,刚开始看别人代码好难受,就这么3个文件看了一晚上。。 效果如下 res文件 main_activity文件就是一个recyclerview main_item是两个textview 一个标题一个详细信息 MainActivity就是加载了一个RecyclerView public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_activity); final RecyclerView rv = (RecyclerView) findViewById(R.id.rv); final LinearLayoutManager layoutManager = new LinearLayoutManager(this); rv.setLayoutManager(layoutManager); final MainAdapter adapter = new MainAdapter(); rv.setAdapter(adapter); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 MainAdapter中new了一个keepOne对象,点进去看这个类,有两个方法:bind和toggle,其中的bind是在MainAdapter中的onBindViewHolder()方法中调用,而toggle是响应viewholder的点击事件 public static class KeepOneH<VH extends RecyclerView.ViewHolder & Expandable> { // opened为-1表示所有item是关闭状态,open为pos值的表示pos位置的item为展开的状态 private int _opened = -1; public void bind(VH holder, int pos) { if (pos == _opened) // 3 // 直接显示expandView 无动画 ExpandableViewHoldersUtil.openH(holder, holder.getExpandView(), false); else // 直接关闭expandView 无动画 ExpandableViewHoldersUtil.closeH(holder, holder.getExpandView(), false); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @SuppressWarnings("unchecked") // 响应点击事件的方法 public void toggle(VH holder) { // 如果点击的就是开着的item,就关闭该item并把opened置-1 // ???TODO if (_opened == holder.getPosition()) { _opened = -1; // 关闭expandView 有动画 ExpandableViewHoldersUtil.closeH(holder, holder.getExpandView(), true); } // 如果点击其他本来关闭着的item,则把opened值换成当前pos,把之前开的item给关掉 else { int previous = _opened; _opened = holder.getPosition(); // 展开expandView 有动画 ExpandableViewHoldersUtil.openH(holder, holder.getExpandView(), true); // 用动画关闭之前的item final VH oldHolder = (VH) ((RecyclerView) holder.itemView.getParent()).findViewHolderForPosition(previous); if (oldHolder != null) ExpandableViewHoldersUtil.closeH(oldHolder, oldHolder.getExpandView(), true); } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 点进openH和closeH方法进去看 // 4 public static void openH(final RecyclerView.ViewHolder holder, final View expandView, final boolean animate) { // animate参数为true,则有动画效果 if (animate) { expandView.setVisibility(View.VISIBLE); // 5 // 改变高度的动画,具体操作点进去看 final Animator animator = ViewHolderAnimator.ofItemViewHeight(holder); // 扩展的动画结束后透明度动画开始 animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { final ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(expandView, View.ALPHA, 1); alphaAnimator.addListener(new ViewHolderAnimator.ViewHolderAnimatorListener(holder)); alphaAnimator.start(); } }); animator.start(); } // animate参数为false,则直接设置为可见 else { expandView.setVisibility(View.VISIBLE); expandView.setAlpha(1); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 openH方法接收3个参数, 第一个是viewholder. 第二个是展开部分的view,由holder.getExpandView()方法获取。这里定义了一个接口 public static interface Expandable { public View getExpandView(); } 1 2 3 1 2 3 在MainAdapter中传入infos这个Textview @Override public View getExpandView() { return infos; } 1 2 3 4 1 2 3 4 第三个是一个标记,true时有动画,false时直接设置其展开或者是关闭的状态。所以在bind()方法中调用的openH()都是false,而toggle()中调用的设置为true。 openH方法中 具体动画的操作为ViewHolderAnimator.ofItemViewHeight(holder) public static Animator ofItemViewHeight(RecyclerView.ViewHolder holder) { View parent = (View) holder.itemView.getParent(); if (parent == null) throw new IllegalStateException("Cannot animate the layout of a view that has no parent"); // 测量扩展动画的起始高度和结束高度 int start = holder.itemView.getMeasuredHeight(); holder.itemView.measure(View.MeasureSpec.makeMeasureSpec(parent.getMeasuredWidth(), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); int end = holder.itemView.getMeasuredHeight(); // 6 final Animator animator = LayoutAnimator.ofHeight(holder.itemView, start, end); // 设定该item在动画开始结束和取消时能否被recycle animator.addListener(new ViewHolderAnimatorListener(holder)); // 设定结束时这个item的宽高 animator.addListener(new LayoutParamsAnimatorListener(holder.itemView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); return animator; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 可以看出 具体展开的动画在LayoutAnimator.ofHeight(holder.itemView, start, end);中,ViewHolderAnimator只是测量参数,设定监听两个监听事件 1设定在动画开始结束和取消状态下是否可以被回收 public ViewHolderAnimatorListener(RecyclerView.ViewHolder holder) { _holder = holder; } @Override public void onAnimationStart(Animator animation) { _holder.setIsRecyclable(false); } @Override public void onAnimationEnd(Animator animation) { _holder.setIsRecyclable(true); } @Override public void onAnimationCancel(Animator animation) { _holder.setIsRecyclable(true); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 2.设定在动画结束后view的高和宽分别为warp_content,match_parent. public static class LayoutParamsAnimatorListener extends AnimatorListenerAdapter { private final View _view; private final int _paramsWidth; private final int _paramsHeight; public LayoutParamsAnimatorListener(View view, int paramsWidth, int paramsHeight) { _view = view; _paramsWidth = paramsWidth; _paramsHeight = paramsHeight; } @Override public void onAnimationEnd(Animator animation) { final ViewGroup.LayoutParams params = _view.getLayoutParams(); params.width = _paramsWidth; params.height = _paramsHeight; _view.setLayoutParams(params); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 再深入一层看展开的动画 public class LayoutAnimator { public static class LayoutHeightUpdateListener implements ValueAnimator.AnimatorUpdateListener { private final View _view; public LayoutHeightUpdateListener(View view) { _view = view; } @Override public void onAnimationUpdate(ValueAnimator animation) { final ViewGroup.LayoutParams lp = _view.getLayoutParams(); lp.height = (int) animation.getAnimatedValue(); _view.setLayoutParams(lp); } } public static Animator ofHeight(View view, int start, int end) { final ValueAnimator animator = ValueAnimator.ofInt(start, end); animator.addUpdateListener(new LayoutHeightUpdateListener(view)); return animator; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 是用ValueAnimator.ofInt生成一系列高度值,然后监听动画的变化,不断设定view的高度值 http://blog.csdn.net/gulumi_mmga/article/details/46683437 本文转自 一点点征服 博客园博客,原文链接:http://www.cnblogs.com/ldq2016/p/5825015.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

高级渗透测试对公司网站漏洞检测详情

天气逐渐变凉,但渗透测试的热情温度感觉不到凉,因为有我们的存在公开分享渗透实战经验过程,才会让这个秋冬变得不再冷,近期有反映在各个环境下的目录解析漏洞的检测方法,那么本节由我们高级渗透架构师来详细的讲解平常用到的web环境检测点和网站漏洞防护办法。 3.14.1. IIS 3.14.1.1. IIS 6.0 后缀解析 /xx.asp;.jpg目录解析 /xx.asp/xx.jpg (xx.asp目录下任意解析)默认解析 xx.asa xx.cer xx.cdxPROPFIND 栈溢出漏洞PUT漏洞 WebDAV任意文件上传3.14.1.2. IIS 7.0-7.5 / Nginx <= 0.8.37 在Fast-CGI开启状态下,在文件路径后加上 /xx.php ,则 xx.jpg/xx.php 会被解析为php文件 3.14.1.3. 其他 在支持NTFS 8.3文件格式时,可利用短文件名猜解目录文件 3.14.2. Nginx 3.14.2.1. Fast-CGI关闭 在Fast-CGI关闭的情况下, Nginx 仍然存在解析漏洞:在文件路径(xx.jpg)后面加上 %00.php , 即 xx.jpg%00.php 会被当做 php 文件来解析 3.14.2.2. Fast-CGI开启 在Fast-CGI开启状态下,在文件路径后加上 /xx.php ,则 xx.jpg/xx.php 会被解析为php文件 3.14.2.3. CVE-2013-4547 "a.jpgx20x00.php" 3.14.3. Apache 3.14.3.1. 后缀解析 test.php.x1.x2.x3 ( x1,x2,x3 为没有在 mime.types 文件中定义的文件类型)。Apache 将从右往左开始判断后缀, 若x3为非可识别后缀,则判断x2,直到找到可识别后缀为止,然后对可识别后缀进行解析 3.14.3.2. .htaccess 当AllowOverride被启用时,上传启用解析规则的.htaccess 3.14.3.3. CVE-2017-15715 %0A绕过上传黑名单 3.14.4. lighttpd xx.jpg/xx.php 3.14.5. Windows Windows不允许空格和点以及一些特殊字符作为结尾,创建这样的文件会自动取出,所以可以使用 xx.php[空格] , xx.php., xx.php/, xx.php::$DATA 可以上传脚本文件 3.15. Web Cache欺骗攻击 3.15.1. 简介 网站通常都会通过如CDN、负载均衡器、或者反向代理来实现Web缓存功能。通过缓存频繁访问的文件,降低服务器响应延迟。 例如,网站 htttp://域名 配置了反向代理。对于那些包含用户个人信息的页面,如 http://域名/home.php ,由于每个用户返回的内容有所不同,因此这类页面通常是动态生成,并不会在缓存服务器中进行缓存。通常缓存的主要是可公开访问的静态文件,如css文件、js文件、txt文件、图片等等。此外,很多最佳实践类的文章也建议,对于那些能公开访问的静态文件进行缓存,并且忽略HTTP缓存头。 Web cache攻击类似于RPO相对路径重写攻击,都依赖于浏览器与服务器对URL的解析方式。当访问不存在的URL时,如 http://域名/home.php/non-existent.css ,浏览器发送get请求,依赖于使用的技术与配置,服务器返回了页面 http://域名/home.php 的内容,同时URL地址仍然是 http://域名/home.php/non-existent.css,http头的内容也与直接访问 http://域名/home.php 相同,cacheing header、content-type(此处为text/html)也相同。 3.15.2. 漏洞成因 当代理服务器设置为缓存静态文件并忽略这类文件的caching header时,访问 http://域名/home.php/no-existent.css 时,会发生什么呢?整个响应流程如下: 浏览器请求 http://域名/home.php/no-existent.css ;服务器返回 http://域名/home.php 的内容(通常来说不会缓存该页面);响应经过代理服务器;代理识别该文件有css后缀;在缓存目录下,代理服务器创建目录 home.php ,将返回的内容作为 non-existent.css 保存。3.15.3. 漏洞利用 攻击者欺骗用户访问 http://域名/home.php/logo.png? ,导致含有用户个人信息的页面被缓存,从而能被公开访问到。更严重的情况下,如果返回的内容包含session标识、安全问题的答案,或者csrf token。这样攻击者能接着获得这些信息,因为通常而言大部分网站静态资源都是公开可访问的。 3.15.4. 漏洞存在的条件 漏洞要存在,至少需要满足下面两个条件: web cache功能根据扩展进行保存,并忽略caching header;当访问如 http://域名/home.php/non-existent.css 不存在的页面,会返回 home.php 的内容。3.15.5. 漏洞防御 防御措施主要包括3点: 设置缓存机制,仅仅缓存http caching header允许的文件,这能从根本上杜绝该问题;如果缓存组件提供选项,设置为根据content-type进行缓存;访问 http://域名/home.php/non-existent.css 这类不存在页面,不返回 home.php 的内容,而返回404或者302。对图片上传目录进行脚本权限限制,对上传扩展这里做过滤判断。如果缓存组件提供选项,设置为根据content-type进行缓存;对get url的地址进行waf的安全过滤,如果对这些安全防护部署以及渗透测试不熟悉的话,建议可以像专业的网站安全公司来处理解决。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册