用户管理底层实现
导入分页工具类:PageSupport.java
封装特性:在set方法中限定传入的数据条件,判断传入数据的正确性
用户列表页面导入:userlist.jsp、rollpage.jsp
功能分析:点击用户管理界面后,首先是全部用户数据,其次是下拉框中用户角色的拉取,最后是所有数据的条目数
(一)全部用户数据的显示
①------------由于还是在需要查询的数据仍然在user表中查出的,因此在UserDao中添加方法:
//获取用户列表
public List<User> getUserList (Connection connection, String username, int userRole, int CurrentPageNo, int PageSize) throws SQLException;
②-----------接着去实现类UserDaoImlp中实现方法:
//用来查询所有用户列表的方法
public List<User> getUserList(Connection connection, String username, int userRole, int CurrentPageNo, int PageSize) throws SQLException {
PreparedStatement ps = null ;
ResultSet rs = null ;
List<User> userList = new ArrayList<User>();
if(connection!=null){
StringBuffer sql = new StringBuffer();
sql.append("select a.*,b.roleName from smbms_user as a,smbms_role as b where a.userRole=b.id ");
List<Object> list = new ArrayList<Object>();
if(!StringUtils.isNullOrEmpty(username)){
sql.append(" and a.userName like ? ");
list.add("%"+username+"%");
}
//System.out.println("==============================传进DAO层的username值是"+username+",而且userRole的值是"+userRole);
if(userRole>0){
sql.append(" and b.id = ?");
list.add(userRole);
}
sql.append(" order by creationDate DESC limit ?,?");
CurrentPageNo = (CurrentPageNo-1)*PageSize;
list.add(CurrentPageNo);
list.add(PageSize);
Object[] params = list.toArray();
System.out.println("这条指令执行的SQL语句是"+sql.toString());
rs = BaseDao.excutequery(connection,sql.toString(),params,rs,ps);
//要把返回的查询结果集,写到List集合中存储
while (rs.next()){
User user = new User();
user.setId(rs.getInt("id"));
user.setUserCode(rs.getString("userCode"));
user.setUserName(rs.getString("userName"));
user.setGender(rs.getInt("gender"));
//这里应该把生日属性传回去后,前台作了和当前时间的判断,转化为了年龄属性,没有仔细看,不过也不复杂
user.setBirthday(rs.getDate("birthday"));
user.setPhone(rs.getString("phone"));
user.setUserRole(rs.getInt("userRole"));
user.setUserRoleName(rs.getString("roleName"));
userList.add(user);
}
BaseDao.close(connection,null,null);
}
return userList;
}
注意,这里存储SQL语句采取了StringBuffer的形式
StringBuffer和Stringbuilder的区别在于:
StringBuffer调用toString方法的时候会从缓冲区取一个tostringCash构造字符串,StringBuilder则是复制字符数组的方式构建新字符串
而且StringBuffer的所有公开方法都是由sychonized关键字修饰的,因此线程安全,但是性能没那么高
而且这段方法注意:因为SQL的变量值是不同的类型,需要先用一个集合装载,再用List.toArray()方法转回去再传
③--------业务层调用DAO层方法:
接口规定方法:
public List<User> getUserList(String username,int userRole,int CurrentPageNo,int PageSize) throws SQLException;
实现类实现方法:
public List<User> getUserList(String username, int userRole, int CurrentPageNo, int PageSize){
List<User> list = new ArrayList<User>();
Connection cnn = null;
cnn = BaseDao.getConnection();
try {
list = userDao.getUserList(cnn,username,userRole,CurrentPageNo,PageSize);
} catch (SQLException e) {
e.printStackTrace();
}finally {
BaseDao.close(cnn,null,null);
}
return list;
}
④-----------控制层调用方法(重点):
public void UserQuery(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//先获取前端传回的参数
String Temp_useryname = req.getParameter("queryname"); //前端页面传进来的用户名参数
String userRole = req.getParameter("queryUserRole"); //前端页面传进来的角色码
String currentpageIndex = req.getParameter("pageIndex"); //前端页面传进来的页码
int queryUserRole = 0; //用于查询的角色码
int QueryPageNo = 1 ; //用于查询用的页码
int pagesize = Constants.PageSize ; //一页能查出多少条
int totalCount = 0; //总计能查出多少条数据
UserService userService = new UserServiceImpl(); //创建业务层对象,准备调用
//设计第一次进入时,页面完全无任何参数传入的情况下如何查询到所有数据
//如果第一次进入,将所有值默认为控制
if(Temp_useryname==null){
Temp_useryname="";
}
if(userRole!=null && !userRole.equals("")){
queryUserRole = Integer.parseInt(userRole); //前端页面第一次进来角色码是空值,因此不会
}
//System.out.println("前台传进来角色码的值是"+userRole+",但是经过方法重赋值后是"+queryUserRole);
if(currentpageIndex!=null){
QueryPageNo = Integer.valueOf(currentpageIndex);
}
//System.out.println("前台传进来页数的值是"+currentpageIndex+",但是经过方法重赋值后是"+QueryPageNo);
//获取用户总数(分页:存在上一页、下一页)
try {
totalCount = userService.getUserCount(Temp_useryname,queryUserRole);
} catch (SQLException e) {
e.printStackTrace();
}
//总页数支持
PageSupport pageSupport = new PageSupport();
pageSupport.setCurrentPageNo(QueryPageNo);
pageSupport.setPageSize(pagesize);
pageSupport.setTotalCount(totalCount);
//控制首页和尾页
if(QueryPageNo<1){
QueryPageNo = 1;
}else if (QueryPageNo>totalCount){
QueryPageNo = totalCount;
}
//填充用户角色下拉框 roleList
RoleService roleService = new RoleServiceImlp();
List<Role> roleList = roleService.getRoleList();
req.setAttribute("roleList",roleList);
//获取用户列表
try {
List<User> list = userService.getUserList(Temp_useryname,queryUserRole,QueryPageNo,pagesize);
// System.out.println("获取到的用户总数是"+totalCount);
// System.out.println("当前的页码是"+QueryPageNo);
// System.out.println("页面大小是"+pagesize);
req.setAttribute("userList",list);
} catch (SQLException e) {
e.printStackTrace();
}
//将查询出的分页信息传递给前端
req.setAttribute("totalCount",totalCount);
req.setAttribute("currentPageNo",QueryPageNo);
req.setAttribute("totalPageCount",pageSupport.getTotalPageCount());
req.setAttribute("queryUserName",Temp_useryname);
req.setAttribute("queryUserRole",queryUserRole);
//返回前端
req.getRequestDispatcher("userlist.jsp").forward(req,resp);
}
这里主要注意由于前端返回的值比较多
1.提交的用户名参数
2.提交的角色码
3.前段规定的当前页码
另外,我们自定义:
4.查询用的用户名参数
5.查询用的角色码
6.页面大小,即一个页面显示的最大数据条数
7.数据总条数(这个在另外一条线中通过请求查出,赋值后可直接使用)
8.页数 (这个由于使用了一个分页支持类,类中有一个getTotalPageCount()方法可以直接调用,
其方法中有一定的算法,提供总数据、页面size可以计算总页数)
分清定义的参数名即可
调用业务层,查询出结果返回的List集合,直接req.setAttribute(“userList”,list);返回给前端即可
查询用户角色全部值
由于这个需求是针对Role表,所以需要在各层单独开一个文件夹,跟User模块分开
一)DAO层
接口:
public interface RoleDao {
//获取角色列表
public List<Role> getRoleList(Connection connection) throws SQLException;
}
实现类:
public List<Role> getRoleList(Connection connection) {
List<Role> list = new ArrayList<Role>();
PreparedStatement ps = null;
ResultSet rs = null;
if(connection!=null){
String sql = "select * from smbms_role ";
Object[] params = {};
try {
rs = BaseDao.excutequery(connection,sql,params,rs,ps);
while (rs.next()){
Role role = new Role();
role.setId(rs.getInt("id"));
role.setRoleCode(rs.getString("roleCode"));
role.setRoleName(rs.getString("roleName"));
list.add(role);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
BaseDao.close(connection,ps,rs);
}
}
return list;
}
二)业务层
接口定义:
//获取角色列表
public List<Role> getRoleList();
实现类:
private RoleDao reoledao;
public RoleServiceImlp(){
reoledao = new RoleDaoImlp();
}
//获取用户角色列表
public List<Role> getRoleList() {
List<Role> list = new ArrayList<Role>();
Connection cnn = null;
cnn = BaseDao.getConnection();
try {
list = reoledao.getRoleList(cnn);
} catch (SQLException e) {
e.printStackTrace();
}finally {
BaseDao.close(cnn,null,null);
}
return list;
}
在创建的业务实现类的时候,一定注意要在无参构造方法中先把Dao层对象先NEW出来,这样可以保证在实现类加载的时候就可以有能使用的DAO层对象,这样对于操作数据也是有利的
三)控制层
//填充用户角色下拉框 roleList
RoleService roleService = new RoleServiceImlp();
List<Role> roleList = roleService.getRoleList();
req.setAttribute("roleList",roleList);
这段其实在上述的UserServlet代码中已有,只是单纯的调用方法,然后将结果通过request返回视图层
查询获取数据总数
一)Dao层
接口定义方法:
//根据用户名或者用户角色查询用户总数
public int getUserCount(Connection connection,String username,int userRole) throws SQLException;
实现类中进行功能实现
public int getUserCount(Connection connection, String username, int userRole) throws SQLException {
PreparedStatement ps = null;
ResultSet rs = null;
int count = 0;
if(connection!=null){
//Stringbuilder也可以
StringBuffer sql = new StringBuffer();
ArrayList<Object> object = new ArrayList<Object>();
sql.append("select count(1) as count from smbms_user a,smbms_role b where a.userRole=b.id");
if(!StringUtils.isNullOrEmpty(username)){
sql.append(" and a.userName like ?");
object.add("%"+username+"%");
}
if(userRole>0){
sql.append(" and b.id = ?");
object.add(userRole);
}
//怎么把list集合转化为数组
Object[] array = object.toArray();
rs = BaseDao.excutequery(connection,sql.toString(),array,rs,ps);
if(rs.next()){
//从SQL结果中获取结果
count = rs.getInt("count");
}
BaseDao.close(connection,ps,rs);
}
return count;
}
这段跟功能一获取全部数据类似,区别是功能一种要求返回全部数据,这里计数只返回一个Int值即可,没有通过集合传递对象的步骤
二)业务层调用
接口方法定义:
//查询记录数
public int getUserCount(String username,int userRole) throws SQLException;
实现类方法实现:
public int getUserCount(String username, int userRole){
Connection cn = null;
int count = 0;
try {
cn = BaseDao.getConnection();
count = userDao.getUserCount(cn,username,userRole);
} catch (SQLException e) {
e.printStackTrace();
}finally {
BaseDao.close(cn,null,null);
}
return count;
}
只需注意,因为这段执行SQL需要抛出异常,但是如果这个Int在里面定义的话就不好返回,需要提一下作用域
三)控制层调用
//获取用户总数(分页:存在上一页、下一页)
try {
totalCount = userService.getUserCount(Temp_useryname,queryUserRole);
} catch (SQLException e) {
e.printStackTrace();
}
传参,执行方法即可。
功能实现总结
①------------整个功能实现的难点均在控制层的调用,参数比较多,定义参数名一定要注意,不要把值传错。
②------------另外刚进这个页面的时候,前端传过来的值都是空的,这个时候方法调用会出问题,
需要判断一下,不符合规范的值需要进行转一下,
这样可以保证在不传值默认状态下查询出全部的数据。
③------------分页的方法比较复杂,需要仔细研究一下下标的问题,数据库中的limit ?,?
第一个是数据起始下标,是从0开始的
第二个就是pagesize了,就是页面一页会显示多少数据