实验四基于MVC模式的Web系统开发(第4次实验,4学时,综合性)一、实验目的和要求1理解MVC设计模式。2.掌握基于MVC(Servlet+JSP+JavaBean相结合)开发JavaWeb系统。二、实验内容基于MVC(Servlet+JSP+JavaBean相结合)实现用户的登录注册功能。要求:用户信息至少包含:用户名和密码,用户名不能重复,注册时要求用户输入两次密码确认。三、实验原理MVC(JavaBean+JSP+Servlet相结合)适合开发复杂的Web应用,在这种模式下,Servlet负责处理用户请求并响应,JSP负责数据显示和与用户交互,JavaBean负责具体业务逻辑的处理。现在往往还引入DAO层(数据访问层),负责数据库的基本CRUD访问操作。分层架构的代码基本是按照【域模型层(domain)】→【数据访问层(dao、dao.impl)】→【业务处理层(service、service.impl)】一→【表现层(web.controller、web.UI、web.filter、web.listener)】→【工具类(util)】一→【测试类(junit.test)】的顺序进行编写的。四、实验步骤1.创建数据库testdb和tbuser数据表。2.创建工程DynamicWebProject。3.导入相关jar包(MySQL驱动,istl,DBCP,DBUtils)。4.建包(ycu.jsj.test4.entity,dao,service,servlet和util)。5.创建实体类User,IUserdao接口,Userdaolmpl实现类,UserService业务类,UserSerlvet,过滤器类EncodingFilter和LoginFilter,工具类JdbcUtils。6.页面的编写(login.jsp,regist.jsp)。7.创建公共页面(index.jsp和404.jsp)。五、参考程序1.ycu.jsj.test4.entity层实体类User.java(省略):其成员变量的名称和类型与tb_user表的字段一一对应。2. ycu.jsj.test4.utils层(1)db.properties配置文件driverclassName=com.mysql.cj.jdbc.Driverurl=jdbc:mysql://localhost:33o6/testdb?usessL=false&serverTimezone=Asia/Shanghai8allowPublicKeyRetrieval=trueusername=rootpassword=123456initialsize=10maxActive=50
1 实验四 基于 MVC 模式的 Web 系统开发 (第 4 次实验,4 学时,综合性) 一、实验目的和要求 1. 理解 MVC 设计模式。 2. 掌握基于 MVC(Servlet+JSP+JavaBean 相结合)开发 Java Web 系统。 二、实验内容 基于 MVC(Servlet+JSP+JavaBean 相结合)实现用户的登录注册功能。 要求:用户信息至少包含:用户名和密码,用户名不能重复,注册时要求用户输入两次密码确认。 三、实验原理 MVC(JavaBean+JSP+Servlet 相结合)适合开发复杂的 Web 应用,在这种模式下,Servlet 负责处理用户请求并响应,JSP 负责数据显示和与用户交互,JavaBean 负责具体业务逻辑 的处理。现在往往还引入 DAO 层(数据访问层),负责数据库的基本 CRUD 访问操作。 分层架构的代码基本是按照【域模型层(domain)】→【数据访问层(dao、dao.impl)】→ 【业务处理层(service、service.impl)】→【表现层(web.controller、web.UI、web.filter、 web.listener)】→【工具类(util)】→【测试类(junit.test)】的顺序进行编写的。 四、实验步骤 1. 创建数据库 testdb 和 tb_user 数据表。 2. 创建工程 Dynamic Web Project。 3. 导入相关 jar 包(MySQL 驱动,jstl,DBCP,DBUtils)。 4. 建包(ycu.jsj.test4.entity,dao,service,servlet 和 util)。 5. 创建实体类 User,IUserdao 接口,UserdaoImpl 实现类,UserService 业务类,UserSerlvet,过滤器类 EncodingFilter 和 LoginFilter,工具类 JdbcUtils。 6. 页面的编写(login.jsp,regist.jsp)。 7. 创建公共页面(index.jsp 和 404.jsp)。 五、参考程序 1. ycu.jsj.test4.entity 层 实体类 User.java(省略):其成员变量的名称和类型与 tb_user 表的字段一一对应。 2. ycu.jsj.test4.utils 层 (1)db.properties 配置文件 driverClassName=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=Asia/Shanghai& allowPublicKeyRetrieval=true username=root password=123456 initialSize=10 maxActive=50
maxIdle=20minIdle=5maxWait=60000connectionProperties=useUnicode=true;characterEncoding=utf8defaultAutoCommit=truedefaultReadOnly=defaultTransactionIsolation=READ COMMITTED(2)本次实现使用DBCP连接池实现数据库连接。所以在该包中创建了JdbcUtils.java类,实现数据库的连接和释放连接:package ycu.jsj.mvcdemo.util,import java.io.InputStream,importjava.sql.Connection.import java.sql.ResultSet,importjava.sql.SQLException,import java.sql.Statement:import java.util.Properties,import javax.sql.DataSource,importorg.apache.commons.dbcp2.BasicDataSourceFactory,publicclass JdbcUtilsprivatestaticDataSourcedataSourcestaticftry InputStreamis=JdbcUtils.class.getResourceAsStream("/dbcpconfig.properties"),Propertiesprops=newProperties();props.load(is);dataSource=BasicDataSourceFactory.createDataSource(props),catch(Exceptione)thrownewRuntimeException(e);31/获取数据源1public staticDataSourcegetDataSourceOreturn dataSource,Ⅱ获取连接publicstaticConnectiongetConnection()throwsSQLExceptionreturndataSource.getConnection(),1/释放连接publicstaticvoidrelease(Connectionconn,Statementst,ResultSetrs)if(rs!=null)try (rs.closeO;catch(Exceptione)e.printStackTraceO;!rs = null,if(st I= null):try (st.close(),catch(Exceptione)e.printStackTraceO;st = null;
2 maxIdle=20 minIdle=5 maxWait=60000 connectionProperties=useUnicode=true;characterEncoding=utf8 defaultAutoCommit=true defaultReadOnly= defaultTransactionIsolation=READ_COMMITTED (2)本次实现使用 DBCP 连接池实现数据库连接。所以在该包中创建了 JdbcUtils.java 类,实现数据库 的连接和释放连接: package ycu.jsj.mvcdemo.util; import java.io.InputStream; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; import javax.sql.DataSource; import org.apache.commons.dbcp2.BasicDataSourceFactory; public class JdbcUtils { private static DataSource dataSource; static{ try { InputStream is = JdbcUtils.class.getResourceAsStream("/dbcpconfig.properties"); Properties props = new Properties(); props.load(is); dataSource = BasicDataSourceFactory.createDataSource(props); } catch (Exception e) { throw new RuntimeException(e); } } //获取数据源 public static DataSource getDataSource(){ return dataSource; } //获取连接 public static Connection getConnection() throws SQLException{ return dataSource.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(); } st = null; }
if(conn /= null)(try conn.closeO),catch(Exceptione)e.printStackTrace0);conn=null;3.ycu.jsj.test4.dao层(1)IUserDao接口:其中的方法实现用户表的基本CRUD操作。package ycu.jsj.test4.dao,import java. util.List,importycu.jsj.test4.entity.User,public interface IUserDaof1获取所有用户信息public List<User>getAllUser();1根据条件获取用户信息publicList<User>getUserByField(Stringusername, String sex),1获取指定ID的用户信息public User getUserById(int id);1获得总记录数,可用于分页处理等public int rowCount();冰**用户名是否可用,用于注册等业务*@paramusername*@return如果返回true表示该用户名已被使用)。如果返回false则尚未被使用)。*/public boolean isExistence(Stringusername)/#+净用于登录等业务*@param username*@return如果返回true表示该登录成功。如果返回false则表示登录失败。*/public boolean isExistence(Stringusername, String userpwd),用于注册等业务public boolean addUser(User user);1用于个人信息的修改public boolean updateUserlnfo(User user);1修改密码public boolean updateByPassword(int id, String password);1/删除一个用户记录public boolean deleteUserByld(int id);(2)Dao泛型类,实现对任意数据表的基本的CRUD操作。package ycu.jsj.test4.dao,import java.sql.Connection,import java.sql.SQLException;import java.util.List,importorg.apache.commons.dbutils.QueryRunner;import org.apache.commons.dbutils.handlers.BeanHandler;importorg.apache.commons.dbutils.handlers.BeanListHandler;importorg.apache.commons.dbutils.handlers.ScalarHandler;
3 if(conn != null){ try { conn.close(); } catch (Exception e) { e.printStackTrace(); } conn = null; } } } 3. ycu.jsj.test4.dao 层 (1)IUserDao 接口:其中的方法实现用户表的基本 CRUD 操作。 package ycu.jsj.test4.dao; import java.util.List; import ycu.jsj.test4.entity.User; public interface IUserDao { //获取所有用户信息 public List<User> getAllUser(); //根据条件获取用户信息 public List<User> getUserByField(String username, String sex); //获取指定 ID 的用户信息 public User getUserById(int id); //获得总记录数,可用于分页处理等 public int rowCount(); /** * 用户名是否可用,用于注册等业务 * @param username * @return 如果返回 true 表示该用户名已被使用)。如果返回 false 则尚未被使用)。 */ public boolean isExistence(String username); /** * 用于登录等业务 * @param username * @return 如果返回 true 表示该登录成功。如果返回 false 则表示登录失败。 */ public boolean isExistence(String username, String userpwd); //用于注册等业务 public boolean addUser(User user); //用于个人信息的修改 public boolean updateUserInfo(User user); //修改密码 public boolean updateByPassword(int id, String password); //删除一个用户记录 public boolean deleteUserById(int id); } (2)Dao 泛型类,实现对任意数据表的基本的 CRUD 操作。 package ycu.jsj.test4.dao; import java.sql.Connection; import java.sql.SQLException; import java.util.List; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; import org.apache.commons.dbutils.handlers.ScalarHandler;
importcom.sun.org.apache.bcel.internal.generic.NEW;import ycu.jsj.test4.util.JdbcUtilsimportycu.jsj.test4.util.ReflectionUtils;**封装了基本的CRUD方法,以供子类继承使用*使用DBUtils的QueryRunner提供其具体的实现*@authorHX*@param<T>当前DAO处理的实体类*使用了DBUtils第三方工具实现对数据库的访问*publicclassDao<T>privateQueryRunner queryRunner=null,private Class<T> type,publicDaoOqueryRunner=newQueryRunner(JdbcUtils.getDataSource()type=ReflectionUtils.getSuperGenericType(getClass(O));1/返回T的一个集合publicList<T>getForList(Stringsql,Object..args)/可变参数:0~n任意类型Connection conn = null;tryconn=JdbcUtils.getConnectionO);return queryRunner.query(sql,newBeanListHandler(type),args);1catch(SQLExceptione)e.printStackTrace(),return null,1finallyJdbcUtils.release(conn),71/返回具体的一个值,例如总人数public <E> E getFor Value(String sql, Object..args)!Connection conn=nulltry (conn=JdbcUtils.getConnection();return queryRunner.query(sql,newScalarHandler(),args)catch(SQLExceptione)e.printStackTraceO),return null;↓finally(JdbcUtils.release(conn);71返回一个T对象publicTget(Stringsql, Object...args)Connection conn=null;try (conn=JdbcUtils.getConnectionO;return queryRunner.query(sql,newBeanHandler(type),args);1catch(SQLExceptione)e.printStackTraceO);
4 import com.sun.org.apache.bcel.internal.generic.NEW; import ycu.jsj.test4.util.JdbcUtils; import ycu.jsj.test4.util.ReflectionUtils; /** * 封装了基本的 CRUD 方法,以供子类继承使用 * 使用 DBUtils 的 QueryRunner 提供其具体的实现 * @author HX * @param <T>当前 DAO 处理的实体类 * 使用了 DBUtils 第三方工具实现对数据库的访问 */ public class Dao<T> { private QueryRunner queryRunner= null; private Class<T> type; public Dao(){ queryRunner = new QueryRunner(JdbcUtils.getDataSource()); type = ReflectionUtils.getSuperGenericType(getClass()); } //返回 T 的一个集合 public List<T> getForList(String sql, Object.args){ //可变参数:0~n 任意类型 Connection conn = null; try { conn = JdbcUtils.getConnection(); return queryRunner.query(sql, new BeanListHandler<>(type), args); } catch (SQLException e) { e.printStackTrace(); return null; } finally { JdbcUtils.release(conn); } } //返回具体的一个值,例如总人数 public <E> E getForValue(String sql, Object.args){ Connection conn = null; try { conn = JdbcUtils.getConnection(); return queryRunner.query(sql, new ScalarHandler<>(), args); } catch (SQLException e) { e.printStackTrace(); return null; } finally { JdbcUtils.release(conn); } } //返回一个 T 对象 public T get(String sql, Object.args){ Connection conn = null; try { conn = JdbcUtils.getConnection(); return queryRunner.query(sql, new BeanHandler<>(type), args); } catch (SQLException e) { e.printStackTrace();
return null,1finallyJdbcUtils.release(conn);1***INSERTUPDATEDELETE*@paramconnection:数据库连接*@paramsql:SQL语句*@param.args:填充占位符的可变参数?public boolean update(String sql, Object..args)(Connection conn = null,;try (conn=JdbcUtils.getConnection();if(queryRunner.execute(sql, args)>0)return true,lelse!returnfalse,1 catch (SQLException e) e.printStackTraceO),returnfalse,finallyJdbcUtils.release(conn),(3)UserDaolmpl类package ycu.jsj.test4.dao,import java.util.List,importycu.jsj.test4.dao.Dao,importycu.jsj.test4.dao.IUserDaoimportycu.js.test4.entity.User:publicclassUserDaolmplextendsDao<User>implementsIUserDao@Overridepublic List<User> getAlIUserO !return getForList("select * from tb user");@Overridepublic List<User>getUserByField(Stringusername, String sex)String sql-"select * from tb user where username like? and sex like?"returngetForList(sql,"%"+username+"%","%"+sex+"%");@Overridepublic User getUserByld(int id) return get("select * from tb user where id=?",id);@OverridepublicintrowCountOreturngetForValue("selectcount(*)fromtb_user");@Override
5 return null; } finally { JdbcUtils.release(conn); } } /** * INSERT UPDATE DELETE * @param connection:数据库连接 * @param sql :SQL 语句 * @param args:填充占位符的可变参数 */ public boolean update(String sql, Object.args){ Connection conn = null; try { conn = JdbcUtils.getConnection(); if(queryRunner.execute(sql, args)>0){ return true; }else{ return false; } } catch (SQLException e) { e.printStackTrace(); return false; } finally { JdbcUtils.release(conn); } } } ( 3 )UserDaoImpl 类 package ycu.jsj.test4.dao; import java.util.List; import ycu.jsj.test4.dao.Dao; import ycu.jsj.test4.dao.IUserDao; import ycu.jsj.test4.entity.User; public class UserDaoImpl extends Dao<User> implements IUserDao { @Override public List<User> getAllUser() { return getForList("select * from tb_user"); } @Override public List<User> getUserByField(String username, String sex) { String sql="select * from tb_user where username like ? and sex like ?"; return getForList(sql, "%" + username + "%", "%" + sex + "%"); } @Override public User getUserById(int id) { return get("select * from tb_user where id=?", id); } @Override public int rowCount() { return getForValue("select count(*) from tb_user"); } @Override