今天主要是分页的学习、搜索用户、登录事件的拦截。
分页的实现
点击用户管理的时候,页面上显示所有的用户。现在实现分页功能,使得每一页只显示五个用户信息。要实现分页,则需要知道:数据库中信息总数量、总页数、当前页、每一页显示的数目、每一页显示的信息集合。
首先新建一个PageInfo实体类,该类五个属性:size(每一页显示的数目)、totalCount(总数目)、totalPage(总页数)、currentPage(当前页)、List集合用来存储每一页显示的对象。
public class PageInfo<T> {
private List<T> list;
private int totalCount;
private int size;
private int totalPage;
private int currentPage;
public PageInfo() {
}
public PageInfo(List<T> list, int totalCount, int size, int totalPage, int currentPage) {
this.list = list;
this.totalCount = totalCount;
this.size = size;
this.totalPage = totalPage;
this.currentPage = currentPage;
}
public List<T> getList() {
return list;
}
public void setList(List<T> list) {
this.list = list;
}
public int getTotalCount() {
return totalCount;
}
public void setTotalCount(int totalCount) {
this.totalCount = totalCount;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public int getTotalPage() {
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
}
因为我们每页查询5条,同时我们需要当前页,所以我们可以对controller层扽findAll()方法进行修改,同时修改service层的fingdAll()方法
@Override
public PageInfo<User> findAll(int currentPage,String username) {
PageInfo pageInfo=new PageInfo();
int totalCount=userDao.getTotalCount(username);
pageInfo.setTotalCount(totalCount);
double d=totalCount/5.0;
int tp=(int)Math.ceil(d);
pageInfo.setTotalPage(tp);
pageInfo.setSize(5);
if(currentPage<1){
pageInfo.setCurrentPage(1);
}
else if(currentPage>tp){
pageInfo.setCurrentPage(tp);
}
else
pageInfo.setCurrentPage(currentPage);
//
int start=(pageInfo.getCurrentPage()-1)*5;
List<User> userlist=userDao.findAll(start,5,username);
pageInfo.setList(userlist);
return pageInfo;
}
在dao层,修改findAll()为findAll(@Param(“start”)int start, @Param(“size”)int size),同时在dao层得到数据库中的总数量,同时在UserMapper.xml写SQL语句
<select id="findAll" parameterType="int" resultType="user">
select * from tb_user
<if test="username!=null and username!=''">
where username like concat("%",#{username},"%")
</if>
limit #{start},#{size}
</select>
</div>
<!-- /.box-body -->
<div class="box-tools pull-right">
<ul class="pagination">
<li><a href="/user/findAll.do" aria-label="Previous">首页</a></li>
<li><a href="/user/findAll.do?currentPage=${pageInfo.currentPage-1}">上一页</a></li>
<c:forEach begin="1" end="${pageInfo.totalPage}" var="pageNum">
<li><a href="/user/findAll.do?currentPage=${pageNum}">${pageNum}</a></li>
</c:forEach>
<li><a href="/user/findAll.do?currentPage=${pageInfo.currentPage+1}">下一页</a></li>
<li><a href="/user/findAll.do?currentPage=${pageInfo.totalPage}" aria-label="Next">尾页</a></li>
</ul>
</div>
</div>
搜索
搜索实际上是一个模糊查询,还是属于查询,所以这次继续在findAll()上进行修改。(在分页管理上进行修改)
首先dao层的findAll方法添加一个参数:username,同时将对应的SQL语句进行修改。
<select id="findAll" resultType="user">
select * from tb_user
<if test="username!=null and username!='' ">
where username like concat("%",#{username},"%")
</if>
limit #{start},#{size}
</select>
dao层的getTotalCount()也添加一个参数:String:username,其他的findAll()也添加上该参数。
这个时候运行,会发现发现搜索用户可以显示出搜索的结果,但是点击下一页的时候会显示所有的用户。所以,这个时候需要在controller层的findAll()添加一个会话对象session,和一个int型的参数type.当type=1的时候表示进行查询,则把传进来的username放入session中,type=2表示查询所有的用户,此时将username从session中remove出去。
@RequestMapping("findAll.do")
public ModelAndView findAll(@RequestParam(defaultValue = "1") int currentPage, String username,
@RequestParam(defaultValue = "0") int type,
HttpSession session){//当前页可以通过页面传进来
//type=1表示传进来了username,表示查询, =2表示查询所有
if(type==1){
session.setAttribute("searchname",username);
}else if(type==0){
username=(String) session.getAttribute("searchname");
}else if(type==2){
//点击用户管理的时候,重新查询所有的用户
session.removeAttribute("searchname");
}
PageInfo<User> pageInfo = userService.findAll(currentPage,username);//查到所有的用户
//视图解析器
ModelAndView modelAndView = new ModelAndView();
//跳转界面,跳转到用户管理,在pages文件夹下,这里直接写文件名
modelAndView.setViewName("user-list");
//把查询到的对象添加进去
modelAndView.addObject("pageInfo",pageInfo);
return modelAndView;
}
过滤器
在url中输入localhost:8080/user/findAll.do发现也能跳转到用户管理页面,但是这个时候用户并没有登录,所以这个时候需要设置过滤器对登陆事件进行拦截。
首先新建包filter,该层下新建类LoginFilter,该类实现Filter接口,doFilter方法如下:
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//判断用户是否登录,如果登录则继续执行,没有登陆跳转到登陆界面
//放到session里边,有用户则登录,没有则跳转到登陆姐买你需要登录
HttpServletRequest request=(HttpServletRequest) servletRequest;
HttpServletResponse response=( HttpServletResponse) servletResponse;
HttpSession session = request.getSession();
User user=(User) session.getAttribute("user");
//获得请求路径
String url=request.getRequestURL().toString();
//路径里没有login.do则跳转到登陆界面,这样不会死循环
if(user==null && url.indexOf("login.do")==-1){
//跳转到登陆
response.sendRedirect("../login.jsp");
}
else{
filterChain.doFilter(request,response);
}
}
然后到web,xml文件中写映射,和之前写的类似。这样写完之后再运行项目,这次就只能先登录才能查看用户列表,如果不登陆的话则会跳转到登录页面。
<filter>
<filter-name>loginFilter</filter-name>
<filter-class>com.zr.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loginFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
权限的管理以及角色的添加
实现角色管理功能。角色分为管理员和用户。点击用户列表右边的添加角色,可以进入到user-update.jsp页面,从而给用户添加角色。
建立对应的实体类
public class Role {
private int id;
private String rolename;
private String roledesc;
public Role(){}
public Role(int id, String rolename, String roledesc) {
this.id = id;
this.rolename = rolename;
this.roledesc = roledesc;
}
public void setId(int id) {
this.id = id;
}
public void setRolename(String rolename) {
this.rolename = rolename;
}
public void setRoledesc(String roledesc) {
this.roledesc = roledesc;
}
public int getId() {
return id;
}
public String getRolename() {
return rolename;
}
public String getRoledesc() {
return roledesc;
}
@Override
public String toString() {
return "Role{" +
"id=" + id +
", rolename='" + rolename + '\'' +
", roledesc='" + roledesc + '\'' +`
'}';
}
}
public class UserRole {
private int userId;
private int roleId;
public void setUserId(int userId) {
this.userId = userId;
}
public void setRoleId(int roleId) {
this.roleId = roleId;
}
public int getUserId() {
return userId;
}
public int getRoleId() {
return roleId;
}
@Override
public String toString() {
return "UserRole{" +
"userId=" + userId +
", roleId=" + roleId +
'}';
}
}
改写登录,期望得到的结果是,管理员登陆进去之后能显示角色管理,但是普通用户登录就不显示角色管理。则需要在登陆的时候通过id来确定角色。通过userServiceImpl的login()方法来得到id,再通过该id在user_role里查找roleId,来确定角色。
@RequestMapping("login.do")
public ModelAndView login(User user,HttpSession session){
//调用service层
//视图解析器
//得到id.判断角色
int id= userService.login(user.getUsername(),user.getPassword());
ModelAndView modelAndView = new ModelAndView();
if(id!=-1){
//跳转到成功页面
//根据id去user_role表里边查角色,得到id的集合
List<Integer> roleIds=roleService.findRoleByUserId(id);
//放置用户信息
session.setAttribute("user",user);
session.setAttribute("roleIds",roleIds);
modelAndView.setViewName("main");
}else{
modelAndView.setViewName("../failer");
}
return modelAndView;
}
userServiceImpl的login()方法改写为:
@Override
public int login(String username, String password) {
User user = userDao.findUserByname(username);
if(user!=null&&user.getPassword().equals(password)){
return user.getId();
}
return -1; //表示用户不存在
}
新建IRoleDao,在service层新建IRoleService接口和相对应的实现类。其他实现和之前的类似。
在登录部分添加了权限之后,接下来实现给添加角色功能。
在主页面点击“添加角色”进入到user-role-add.jsp页面,首先在controller层实现这个页面跳转。
@RequestMapping("toAddRole.do")
public ModelAndView toAddRole(int id){
//根据id把没有的角色查出来
//查询出来一个集合
List<Role> roleList= roleService.findNotRoleByUserId(id);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("roles",roleList);
modelAndView.setViewName("user-role-add");
modelAndView.addObject("id",id);
return modelAndView;
}
sql语句:
<select id="findNotRoleByUserId" parameterType="int" resultType="role">
select * from tb_role where id not in (select roleId from user_role where userId = #{id})
</select>
下面实现添加角色:
在user-role-add.jsp文件中找到“保存”按钮,发现此按钮点击事件对应的是addRole()方法。
在下边的js代码中找到该方法,通过location.href="/user/addRole.do?roleIds="+roleList.toString()+"&userId="+userId;来获得用需要添加的角色的id(存在List集合中)和用户id,在controller层调用service层的addRole,将roleId,userId封装到UserRole的对象中
以下是controller层的代码,因为可能会同时添加多个角色,则就会有多个roleId,通过逗号分隔。
@RequestMapping("addRole.do")
public String addRole(String roleIds,String userId){
//根据逗号来切割
String[] strs=roleIds.split(",");
List<Integer> ids=new ArrayList<>();
for(String s:strs){
ids.add(Integer.parseInt(s));//强转
}
roleService.addRole(ids,Integer.parseInt(userId));
return "redirect:findAll.do";
}
service层:
@Override
public void addRole(List<Integer> ids,int userId) {
///需要一条一条的添加
for(int i:ids){
UserRole userRole = new UserRole();
//把值塞进去给对象
userRole.setRoleId(i);
userRole.setUserId(userId);
//调用dao层插入到数据库
//应该插入到表user_role里边
roleDao.insertRole(userRole);
}
}
添加的角色保存到数据库表user_role中,sql语句:
<insert id="insertRole" parameterType="com.zr.bean.UserRole">
insert into user_role(userId,roleId) values (#{userId},#{roleId})
</insert>