事务
事务介绍:
就是一件事情,操作要不全部成功,要不全部失败。
mysql里的事务操作
通过一个命令(show variables like ‘autocommit‘;)
得到 autocommit=on;意思是事务 都自动提交
每一条sql都是一个事务
手动事务的操作:(☆)
start transaction; 开始事务(不管是否自动提交)
commit;提交事务
rollback;事务回滚
通过以下命令,可以设置事务为手动提交
set autocommit=off;
注意:一旦设置手动提交后,不要使用start transaction再开启事务了,这时开启的是新事务
java里的事务操作
Connection接口里面的方法:☆
void setAutoCommit(boolean autoCommet):设置事务是否自动提交
void commit():提交事务
void rollback():事务回滚
Savepoint setSavePoint():设置一个还原点
void rollback(savepoint):还原到哪个还原点
public class AccountDemo { public static void main(String[] args) { //aaa->bbb转钱 Connection conn=null; PreparedStatement ps=null; ResultSet rs=null; Savepoint p=null; try { conn=JDBCUtils.getConnection(); //手动开启事务 conn.setAutoCommit(false); //先给a减钱 String sql="update account set money =money-? where name=?"; ps=conn.prepareStatement(sql); ps.setString(1, "500"); ps.setString(2, "aaa"); int i=ps.executeUpdate(); System.out.println(i); //设置还原点 p=conn.setSavepoint(); /*if(i==1){ throw new RuntimeException(); }*/ //给b加钱 sql="update account set money =money+? where name=?"; ps=conn.prepareStatement(sql); ps.setString(1, "500"); ps.setString(2, "bbb"); i=ps.executeUpdate(); System.out.println(i); } catch (Exception e) { e.printStackTrace(); //回滚事务 try { conn.rollback(p); } catch (SQLException e1) { e1.printStackTrace(); } }finally{ //提交事务 try { conn.commit(); } catch (SQLException e) { e.printStackTrace(); } JDBCUtils.closeResources(conn, ps, rs); } } }
事务的特性:(☆)
ACID
原子性:atomicity 要么全部成功,要么全部失败
一致性:consistency 事务执行之后,数据库状态与其它业务规则保持一致。例如:转账,总钱数不变
隔离性:isolation 在并发操作中,不同事务之间应该隔离开来,使每个并发中的事务不会相互干扰。
持久性:durability 一旦事务提交或回滚后,必须持久化到数据库中
隔离性:
若不考虑隔离性,会出现的问题:
脏读:读取到别的事务没有提交的数据
不可重复读:在一个事务中,两次查询的结果不一致(内容 update)
虚读(幻读):在一个事务中,两次查询的结果不一致(条数,针对insert delete操作)
数据库的隔离级别:
read uncommitted:读未提交,最低的级别,上面的情况都可以发生
read committed:读已提交,可以避免脏读
repeatable read:可重复读,可以避免不可重复读
serializable:串行化,最高的等级,可以避免所有问题。
演示几种问题:
设置数据库的隔离级别:
set session transactioin isolation level 级别;
查看当前的隔离级别:
select @@tx_isolation;
mysql默认的隔离级别:repeatable read☆
oracle扩展的隔离级别:read committed☆
安全性:
serializable>repeatable read>read committed>read uncommitted
效率:反之
案例:
转账案例
解决service层需要传入connection参数:
Map<Thread,Connection> map
第一次开始事务的时候,先获取map.get(Thread.currentThread()) == ThreadLocal.get()
获取一个connection,开启事务,最后map.put(Thread.currentThread(),connection) == ThreadLocal.set()
在dao层可以直接使用,map.get(Thread.currentThread())就可以获取绑定的链接
执行的流程:
account.jsp:接收用户信息
accountServlet:接收参数,调用service,页面的跳转
accountService:
1.开启事务
conn.startTransaction() ThreadLocal作用:将当前的链接和当前的线程绑定起来
2.开始转账
3.一旦出现异常 获取当前线程绑定的链接调用rollBack()
4.最后,提交事务,获取当前线程绑定的链接调用commit(),然后关闭链接,最后和当前线程解绑
accountDao:
转入
转出
account.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <h1><font color="red">${msg }</font></h1> <form method="post" action="${pageContext.request.contextPath }/account"> <table border="1"> <tr> <td>汇款人:</td> <td><input type="text" name="fromuser"></td> </tr> <tr> <td>收款人:</td> <td><input type="text" name="touser"></td> </tr> <tr> <td>转账金额:</td> <td><input type="text" name="money"></td> </tr> <tr> <td colspan="2"><input type="submit"></td> </tr> </table> </form> </body> </html>
JDBCUtil:
public class JDBCUtils_ { static final String DRIVERCLASSNAME; static final String URL; static final String USER; static final String PASSWORD; static{ /** * ResourceBundle:用于加载properties文件 * ResourceBundle bundle=ResourceBundle.getBundle(文件名称); * 通过bundle的getString(key)就可以获取指定value * String url=bundle.getString("url"); */ ResourceBundle bundle=ResourceBundle.getBundle("jdbc"); //不需要后缀名 DRIVERCLASSNAME=bundle.getString("driverClassName"); URL=bundle.getString("url"); USER=bundle.getString("user"); PASSWORD=bundle.getString("password"); } static{ try { Class.forName(DRIVERCLASSNAME); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private static ThreadLocal<Connection> tl=new ThreadLocal<Connection>(); /** * 获取链接 * @return 链接 * @throws SQLException */ public static Connection getConnection() throws SQLException{ //第一次开启事务,先获取 Connection conn=tl.get(); if(conn==null){ //创建一个 conn= DriverManager.getConnection(URL,USER,PASSWORD); //和当前线程绑定 tl.set(conn); } return conn; } /** * 开启事务 * @throws SQLException */ public static void startTransaction() throws SQLException{ getConnection().setAutoCommit(false); } /** * 事务回滚 * @throws SQLException */ public static void rooBack() throws SQLException{ getConnection().rollback(); } /** * 事务提交及关闭 * @throws SQLException */ public static void coommitAndClose() throws SQLException{ Connection conn=getConnection(); conn.commit(); conn.close(); tl.remove();//将链接移除 } /** * 做增删改的时候调用 * @param conn * @param st */ public static void closeResources(Connection conn,Statement st){ if(st!=null){ try { st.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * 做查询时调用 * @param conn * @param st * @param rs */ public static void closeResources(Connection conn,Statement st,ResultSet rs){ closeResources(st,rs); if(conn!=null){ try { conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void closeResources(Statement st,ResultSet rs){ if(rs!=null){ try { rs.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(st!=null){ try { st.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
AccountServlet:
public class AccountServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /* * 接收参数 * 调用service */ } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //0.设置编码 request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); //1.接收参数 String fromUser=request.getParameter("fromuser"); String toUser=request.getParameter("touser"); String money=request.getParameter("money"); //2.调用service AccountService accountService=new AccountService(); try { accountService.account(fromUser, toUser, money); } catch (MyException e) { e.printStackTrace(); //添加消息,页面跳转 request.setAttribute("msg", e.getMessage()); request.getRequestDispatcher("/account.jsp").forward(request, response); return; } //3.页面跳转 response.getWriter().print("转账成功"); } }
AccountService:
public class AccountService_ { public void account(String fromUser,String toUser,String money){ //开始事务 try { JDBCUtils_.startTransaction(); AccountDao_ accountDao=new AccountDao_(); //出 accountDao.accountOut( fromUser, money); //如 accountDao.accountIn(toUser,money); } catch (SQLException e) { e.printStackTrace(); //回滚 try { JDBCUtils_.rooBack(); } catch (SQLException e1) { e1.printStackTrace(); } } catch (MyException e) { e.printStackTrace(); }finally{ //提交 try { JDBCUtils_.coommitAndClose(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
AccountDao:
public class AccountDao_ { public void accountOut(String fromUser, String money) throws MyException { Connection conn=null; PreparedStatement ps=null; ResultSet rs=null; try { conn=JDBCUtils_.getConnection(); String sql="upate account set money=money-? where name=?"; ps.setString(1, money); ps.setString(2, fromUser); int i=ps.executeUpdate(); if(i!=1){ throw new MyException("转出失败"); } } catch (SQLException e) { e.printStackTrace(); try { JDBCUtils_.rooBack(); } catch (SQLException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } }finally{ try { JDBCUtils_.coommitAndClose(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public void accountIn(String toUser, String money) throws MyException, SQLException { Connection conn=null; PreparedStatement ps=null; ResultSet rs=null; try { conn=JDBCUtils_.getConnection(); String sql="upate account set money=money+? where name=?"; ps.setString(1, money); ps.setString(2, toUser); int i=ps.executeUpdate(); if(i!=1){ throw new MyException("转入失败"); } } catch (SQLException e) { e.printStackTrace(); try { JDBCUtils_.rooBack(); } catch (SQLException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } }finally{ JDBCUtils_.coommitAndClose(); } } }
Exception:
public class MyException extends Exception{ public MyException() { super(); // TODO Auto-generated constructor stub } public MyException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); // TODO Auto-generated constructor stub } public MyException(String message, Throwable cause) { super(message, cause); // TODO Auto-generated constructor stub } public MyException(String message) { super(message); // TODO Auto-generated constructor stub } public MyException(Throwable cause) { super(cause); // TODO Auto-generated constructor stub } }
连接池:
连接池的优点:
1.提高了链接的复用性
2.节省了创建链接、销毁链接的时间,提高了性能
规范:
连接池都应该是DataSource的实现,datasource是一个规范,javax.sql包的一个接口
获取链接:
getConnection()
关闭的时候:
conn.close()
常见的连接池:
dbcp(理解):apache组织的
c3p0(☆):c3p0
tomcat内置的连接池(了解)
dbcp的使用:
1.导入jar包 commons-dbcp-1.4.jar(核心) 和commons-pool-1.5.6.jar(依赖)
2.编写代码(两种方式)
第一种方式:源码中配置
第二种方式:配置文件
dbcp.properties driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/day14 username=root password=moujinling321 DBCPDemo public class DBCPDemo { public static void main(String args[]) throws Exception { //method1(); method2(); } private static void method2() throws Exception { /* * 方式二:配置文件 */ BasicDataSourceFactory factory=new BasicDataSourceFactory(); Properties p=new Properties(); p.load(new FileInputStream("src/dbcp.properties")); DataSource ds=factory.createDataSource(p); Connection conn=ds.getConnection(); String sql="select * from account limit 1"; PreparedStatement ps=null; ResultSet rs=null; ps=conn.prepareStatement(sql); rs=ps.executeQuery(); while(rs.next()){ System.out.println(rs.getString(1)+":"+rs.getString(2)); } rs.close(); ps.close(); conn.close(); } private static void method1() throws SQLException{ /* * 方式一:源码中配置 */ BasicDataSource ds=new BasicDataSource(); ds.setDriverClassName("com.mysql.jdbc.Driver"); ds.setUrl("jdbc:mysql://localhost:3306/day14"); ds.setUsername("root"); ds.setPassword("moujinling321"); Connection conn=ds.getConnection(); String sql="select * from account"; PreparedStatement ps=null; ResultSet rs=null; ps=conn.prepareStatement(sql); rs=ps.executeQuery(); while(rs.next()){ System.out.println(rs.getString(1)+":"+rs.getString(2)); } rs.close(); ps.close(); conn.close(); } }
c3p0的使用:
项目中使用
自动回收空闲的链接
使用步骤:
1.导入jar包 c3p0-0.9.1.2.jar
2.编码
方式1:编码中编写配置(理解)
方式2:配置文件
c3p0.properties c3p0.jdbcUrl=jdbc:mysql://localhost:3306/day14 c3p0.driverClass=com.mysql.jdbc.Driver c3p0.user=root c3p0.password=moujinling321 C3P0Demo public class C3P0Demo { public static void main(String[] args) throws PropertyVetoException, SQLException { //method1(); method2(); } //第二种方式:配置文件(自动查找) private static void method2() throws SQLException { ComboPooledDataSource ds= new ComboPooledDataSource(); Connection conn=ds.getConnection(); String sql="select * from account limit 1"; PreparedStatement ps=null; ResultSet rs=null; ps=conn.prepareStatement(sql); rs=ps.executeQuery(); while(rs.next()){ System.out.println(rs.getString(1)+":"+rs.getString(2)); } rs.close(); ps.close(); conn.close(); } //第一种方式:源码中配置 private static void method1() throws PropertyVetoException, SQLException { ComboPooledDataSource ds= new ComboPooledDataSource(); ds.setDriverClass("com.mysql.jdbc.Driver"); ds.setJdbcUrl("jdbc:mysql://localhost:3306/day14"); ds.setUser("root"); ds.setPassword("moujinling321"); Connection conn=ds.getConnection(); String sql="select * from account"; PreparedStatement ps=null; ResultSet rs=null; ps=conn.prepareStatement(sql); rs=ps.executeQuery(); while(rs.next()){ System.out.println(rs.getString(1)+":"+rs.getString(2)); } rs.close(); ps.close(); conn.close(); } }
注册要求:用户名相同不能注册
regist.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>bookStore 商城-商品信息展示</title> </head> <body> <!-- head 一行两列的表格--> <%@include file="/public/head.jsp" %> <!-- menu 一行一列的表格--> <%@include file="/public/menu.jsp" %> <!-- search 一行一列的表格 --> <div id="search"> <table width="100%" bgcolor="#B6B684"> <tr align="right"> <td> search <input type="text"/> <input type="button" value="搜索"/> </td> </tr> </table> </div> <!-- content --> <div id="content"> <form action="${pageContext.request.contextPath}/regist" method="post"> <table align="center" bgcolor="#FFFFF4" width="60%"> <tr> <td> <h1>新会员注册<font color="red">${regist_msg }</font></h1> <table align="center"> <tr> <td align="right" >会员邮箱:</td> <td> <input type="text" name="email"/> </td> <td align="left"> <font color="#ff0000">${map.email_msg }</font> </td> </tr> <tr> <td align="right">会员名:</td> <td> <input type="text" name="username" class="txtinput"/> </td> <td align="left"> <font color="#ff0000"></font> </td> </tr> <tr> <td align="right">密码:</td> <td> <input type="password" name="password" class="txtinput"/> </td> <td align="left"> <font color="#ff0000"></font> </td> </tr> <tr> <td align="right">重复密码:</td> <td> <input type="text" name="repassword"/> </td> </tr> <tr> <td align="right">性别:</td> <td> <input type="radio" name="sex" value="男"/>男 <input type="radio" name="sex" value="女"/>女 </td> <td></td> </tr> <tr> <td align="right">联系电话:</td> <td> <input type="text" name="telephone"/> </td> </tr> <tr> <td align="right">个人介绍:</td> <td> <input type="textarea" name="introduce"/> </td> </tr> </table> <h1>注册校验</h1> <table align="center" width="80%" cellspacing="2"> <tr> <td align="right">输入校验码:</td> <td> <input type="text" name="checkcode" class="txtinput"/> </td> <td>${requestScope["code.msg"] }</td> <!-- code.msg,单独不可以写进去,.表示get。用域对象表示出来 --> </tr> <tr> <td> </td> <td colspan="2"> <img src="${pageContext.request.contextPath }/code" id="imgId" alt="验证码" class="txtinput" style="height:30px"/> <a href="javascript:void(0)" onclick="changeCode()">看不清?换一张</a> <!-- 表示这个链接不做跳转动作,执行onClick事件。 --> </td> </tr> <tr> <td align="center" colspan="3"> <input value="同意并提交" style="background:orange;height:30px;width:100px;text-align:center;" type="submit"/> </td> </tr> </table> </td> </tr> </table> </form> </div> <!-- foot 两行两列的表格--> <div id="foot"> <table width="100%" bgcolor="#EFEEDC"> <tr> <td rowspan="2" align="center"> <img src="images/case1/logo.png" alt="图书商城"/> </td> <td>CONTACT US</td> </tr> <tr> <td> copyright 2008©rightBookStore All Rights RESERVED </td> </tr> </table> </div> <table width="100%"> <tr> <td></td> </tr> </table> </body> <script type="text/javascript"> function changeCode(){ var imgObj=document.getElementById("imgId"); imgObj.src="${pageContext.request.contextPath}/code?i="+Math.random(); } </script> </html>
RegistServlet
package web.servlet; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.beanutils.BeanUtils; import domain.User; import exception.UserRegistException; import service.UserService; public class RegistServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); request.setCharacterEncoding("utf-8"); /* * 作用:首先判断验证码 * 若验证码不一致,返回错误信息(regist.jsp) 提示信息(验证码错误) request * 验证码一致,封装参数,调用userservice */ //1.获取验证码 //1.1获取页面上验证码 String code=request.getParameter("checkcode"); //1.2获取session域中的验证码 String sessionCode=(String) request.getSession().getAttribute("session_code"); request.getSession().removeAttribute("session_code"); //验证码一次性 //2.判断验证码 //输入验证码不正确 if(!sessionCode.equalsIgnoreCase(code)){ //加入错误信息,页面跳转 request.setAttribute("code.msg", "验证码输入错误"); request.getRequestDispatcher("/regist.jsp").forward(request,response); return; } //3.获取参数 User user=new User(); try { BeanUtils.populate(user, request.getParameterMap()); } catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } //3.1数据校验 //验证邮件 Map<String,String> map=user.validate(); if(map!=null && map.size()>0){ //有错误信息 request.setAttribute("map", map); request.getRequestDispatcher("/regist.jsp").forward(request, response); return; } //4.调用userservice UserService userService=new UserService(); //可能抛自定义异常 try { userService.regist(user); } catch (UserRegistException e) { e.printStackTrace(); //有异常,添加错误信息,跳转到注册页面 request.setAttribute("regist_msg", e.getMessage()); request.getRequestDispatcher("/regist.jsp").forward(request, response); } //5.页面跳转,提示信息 //5.1将user放到session中 request.getSession().setAttribute("user", user); //5.2提示信息 页面跳转 response.setHeader("refresh", "3;url="+request.getContextPath()+"/success.jsp"); response.getWriter().print("注册成功,3秒之后跳转到首页!"); } }
UserService
public class UserService { UserDaoImpl userDao=new UserDaoImpl(); /** * 用户注册 * @param user 用户信息 * @throws UserRegistException */ public void regist(User user) throws UserRegistException { try { //开启事务 DataSourceUtils.startTransaction(); /* * 首先判断数据库中有没有同名的 * 若有,返回true,不能注册,提示信息 * 若无,可以添加 */ boolean flag=userDao.findUserByUsername(user); if(!flag){//flag=false //调用userdao的adduser方法 userDao.addUser(user); }else{ throw new UserRegistException("该用户名已被占用"); } } catch (SQLException e) { e.printStackTrace(); try { DataSourceUtils.rollBack(); } catch (SQLException e1) { e1.printStackTrace(); } throw new UserRegistException("网络异常!!"); }finally{ //提交事务 try { DataSourceUtils.commitAndClose(); } catch (SQLException e) { e.printStackTrace(); } } } }
UserDao
public class UserDaoImpl implements UserDao{ /** * 添加用户 * @param user 用户信息 * @throws UserRegistException * @throws SQLException */ public void addUser(User user) throws UserRegistException { //使用JDBC操作数据库 Connection conn=null; PreparedStatement ps=null; ResultSet rs=null; try { conn=DataSourceUtils.getConnection(); //编写sql //username,password,sex,telephone,email,introduce String sql="insert into user values(null,?,?,?,?,?,?)"; //创建语句执行者 ps=conn.prepareStatement(sql); //设置参数 ps.setString(1, user.getUsername()); ps.setString(2, user.getPassword()); ps.setString(3, user.getSex()); ps.setString(4, user.getTelephone()); ps.setString(5, user.getEmail()); ps.setString(6, user.getIntroduce()); //执行sql int i=ps.executeUpdate(); if(i==0){ throw new UserRegistException("注册失败"); } //处理结果 System.out.println(i); } catch (SQLException e) { // 数据库异常 e.printStackTrace(); throw new UserRegistException("网络异常,请稍后再试"); }finally{ //释放资源 DataSourceUtils.closeResources(ps, rs); } } /** * 通过用户名查找用户 * 若存在返回true * 若不存在返回false */ public boolean findUserByUsername(User user) { //使用JDBC操作数据库 Connection conn=null; PreparedStatement ps=null; ResultSet rs=null; try { conn=DataSourceUtils.getConnection(); String sql="select * from user where username=? limit 1"; ps=conn.prepareStatement(sql); ps.setString(1, user.getUsername()); rs=ps.executeQuery(); return rs.next(); } catch (SQLException e) { e.printStackTrace(); }finally{ DataSourceUtils.closeResources(ps, rs); } return false; } }
User
public class User { private Integer id; private String email; private String username; private String password; private String sex; private String introduce; private String telephone; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getIntroduce() { return introduce; } public void setIntroduce(String introduce) { this.introduce = introduce; } public String getTelephone() { return telephone; } public void setTelephone(String telephone) { this.telephone = telephone; } public User(Integer id, String email, String username, String password, String sex, String introduce, String telephone) { super(); this.id = id; this.email = email; this.username = username; this.password = password; this.sex = sex; this.introduce = introduce; this.telephone = telephone; } public User() { super(); } @Override public String toString() { return "User [id=" + id + ", email=" + email + ", username=" + username + ", password=" + password + ", sex=" + sex + ", introduce=" + introduce + ", telephone=" + telephone + "]"; } public Map<String, String> validate() { //创建Map Map<String,String> map=new HashMap(); //验证邮箱 /* * 首先验证邮箱是否为空 * 若为空,提示邮箱不能为空 * 若不为空,继续验证邮箱是否符合格式 * 若不符合,提示邮箱格式不争取 * */ if(isNull(email)){ map.put("email_msg", "邮箱不能为空"); }else if(!checkEmail(email)){ map.put("email_msg", "邮箱格式不合法"); } return map; } /** * 判断邮箱格式 * 若符合格式,返回true * 若不符合格式,返回false * @param value * @return bolean */ private boolean checkEmail(String value) { if(value==null){ return false; } //[email protected] String reg="^\\[email protected]\\w+(\\.\\w+)+$"; return value.matches(reg); } /** * 验证是否为空 * 若为空返回Null * 若不为空返回false * @param value * @return boolean */ private boolean isNull(String value) { //^\s*& if(value==null){ return true; } return value.matches("^\\s*$"); } }