SSM练习第五天

文章目录

  • 第一章:授权操作
    • 第一节:经典权限5张表的关系分析
      • 1、数据库模型关系图
      • 2、用户角色关系表
      • 3、角色权限关系表
      • 4、修改用户SysUser实体
      • 5、修改角色Role实体
      • 6、修改权限Permission实体
    • 第二节:查看用户的角色详情功能
      • 1、页面入口
      • 2、编写Controller
      • 3、编写Service
      • 4、编写Dao
        • 编写userDao
        • 编写RoleDao(user下有role)
        • 编写PermissionDao(Role下有permission)
      • 5、修改前端user-show.jsp
    • 第三节:为用户分配角色-角色列表数据回显
      • 1、页面入口
      • 2、编写Controller
      • 3、页面回显数据(user-role-add.jsp)
    • 第四节:为用户分配角色-更新关系到用户角色中间表
      • 1、页面入口
      • 2、编写Controller
      • 3、编写Service
      • 4、编写Dao
    • 第五节:为角色添加权限数据回显(和user添加role雷同)
      • 1、页面入口
      • 2、编写Controller
      • 3、编写Service
      • 4、编写Dao
      • 5、前端页面(role-permission-add.jsp)
    • 第六节:为角色添加权限-实际保存即往中间表插入记录(和user添加role雷同)
      • 1、页面入口
      • 2、编写Controller
      • 3、编写service
      • 4、编写dao
      • 第七节:为用户设置真正的角色
  • 第二章:授权后的安全控制
    • 第一节:在JSP页面控制菜单权限(不显示UI)
      • 1、spring-security.xml配置文件
    • 第二节:在服务器端控制权限(拦截请求 防止用户直接输入url访问)
      • 1、修改spring-mvc.xml配置
      • 2、在需要进行控制的Controller上添加@Secured注解
      • 3、更换默认403 forbidden界面
  • 第三章:系统日志功能
    • 第一节:AOP记录日志
      • 1、日志表sys_log和实体Log
      • 2、springmvc.xml配置文件中开启aop的自动代理
      • 3、在web.xml中配置监听request对象的监听器
      • 4、编写切面类(切面类内部有增强)
      • 5、Service代码实现
      • 6、Dao代码实现
    • 第二节 查询日志
      • 1、页面入口
      • 2、编写Controller
      • 3、编写service
      • 4、编写dao
      • 5、修改domain
      • 6、修改页面

第一章:授权操作

第一节:经典权限5张表的关系分析

1、数据库模型关系图

SSM练习第五天_第1张图片

2、用户角色关系表

多对多的关系:就是两个一对多
一对多:在一的方向添加一个集合属性即可

-- 用户角色关系表  多对多 引入中间表
CREATE TABLE sys_user_role(
    userId number,
    roleId number,
    PRIMARY KEY(userId,roleId), --联合主键:两个不能同时一样
    FOREIGN KEY (userId) REFERENCES sys_USER(id),
    FOREIGN KEY (roleId) REFERENCES sys_role(id) 
)

3、角色权限关系表

CREATE TABLE sys_role_permission(
    permissionId number,
    roleId number,
    PRIMARY KEY(permissionId,roleId),
    FOREIGN KEY (permissionId) REFERENCES sys_permission(id),
    FOREIGN KEY (roleId) REFERENCES sys_role(id) 
)

4、修改用户SysUser实体

@Data
public class SysUser {
    private Long id;
    private String username;
    private String email;
    private String password;
    private String phoneNum;
    private int status;

    //一个用户对应多个角色
    private List<Role> roles = new ArrayList<>();//new出来 防止空指针
}

5、修改角色Role实体

@Data
public class Role {
    private Integer id;
    private String roleName;
    private String roleDesc;

    //一个角色被多个用户所拥有
    private List<SysUser> users = new ArrayList<>();
    //一个角色拥有多个权限
    private List<Permission> permissions = new ArrayList<>();
}

6、修改权限Permission实体

@Data
public class Permission {
    private Integer id;
    private String permissionName;
    private String url;
    private Integer pid;//写简单的pid 不能写Permission对象 随便想想也是死循环

    //一个权限被多个角色拥有
    private List<Role> roles=new ArrayList<>();
}

第二节:查看用户的角色详情功能

1、页面入口

SSM练习第五天_第2张图片

<a href="${pageContext.request.contextPath}/user/details?userId=${user.id}" class="btn bg-olive btn-xs">详情</a>											

2、编写Controller

    /**
     * 查询某用户的详情功能
     *  用户有哪些角色 角色分别有哪些权限
     * @param userId
     * @return
     */
    @RequestMapping("/details")
    public ModelAndView details(Integer userId){
        LogUtils.print("用户详情:"+userId);
        //查询数据--用户详情
        SysUser user=userService.findById(userId);
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("user",user);
        modelAndView.setViewName("user-show");
        return modelAndView;
    }

3、编写Service

    SysUser findById(Integer userId);
    @Override
    public SysUser findById(Integer userId) {
        return userdao.findById(userId);
    }

4、编写Dao

编写userDao

    @Select("select * from sys_user where id = #{userId}")
    @Results({
            @Result(id=true,property = "id",column = "id"),//主键id 最好都加上 否则后端获取id为null
            @Result(property = "roles",column = "id", //还是本张表主键id,因为是根据本张表主键id关联到role的
                    //根据userId查询角色列表
                    // cn.ahpu.dao.RoleDao.findRolesByUserId
                    many = @Many(select = "cn.ahpu.dao.RoleDao.findRolesByUserId"))
    })
    SysUser findById(Integer userId);

编写RoleDao(user下有role)

	@Select("select r.* from sys_user_role ur,sys_role r where ur.roleid=r.id and ur.userid=#{userId}")
    @Results({
            @Result(id=true,property = "id",column = "id"),//主键id 最好加上 否则id只能用一次 后端查id就是null了
            @Result(property = "permissions",column = "id", //还是本张表主键id,因为是根据本张表主键id关联到role的
                    many = @Many(select = "cn.ahpu.dao.PermissionDao.findPermissionsByRoleId"))
    })
    List<Role> findRolesByUserId(Integer userId);

编写PermissionDao(Role下有permission)

	@Select("select p.* from sys_role_permission rp,sys_permission p where rp.roleid=#{roleId} and rp.permissionid=p.id")
    List<Permission> findPermissionsByRoleId(Integer roleId);

5、修改前端user-show.jsp

<thead>
	<tr>
		<th>名称</th>
		<th>描述</th>
	</tr>
</thead>

<tr data-tt-id="0">
	<td colspan="2">${user.username}</td>
</tr>

<tbody>
	<c:forEach items="${user.roles}" var="role" varStatus="i">
		<tr data-tt-id="${role.id}" data-tt-parent-id="0">
			<td>${role.roleName }</td>
			<td>${role.roleDesc }</td>
		</tr>
		<%--子标签的父id要唯一对应 得用${i.count}}
			若dao中id@Result()里id都单独配置了
			那么id可以多次使用 将i.count全部换成 role.id也不错
		--%>
		<c:forEach items="${role.permissions}" var="permission">
			<tr data-tt-id="${role.id}-${permission.id}" data-tt-parent-id="${role.id}">
				<td>${permission.permissionName}</td>
				<td>${permission.url}</td>
			</tr>
		</c:forEach>
	</c:forEach>
</tbody>

第三节:为用户分配角色-角色列表数据回显

1、页面入口

SSM练习第五天_第3张图片

2、编写Controller

@RequestMapping("/addRoleToUserUI")
    public ModelAndView addRoleToUserUI(Integer userId){
        LogUtils.print("addRoleToUserUI:"+userId);
        //所有角色
        List<Role> roles = roleService.findAll();
        //当前用户拥有的角色 直接将当前用户传过去也行 延迟加载还能起点作用
        SysUser user = userService.findById(userId);
        //方便选中已有的 换种写法
        List<Role> userOwnedRoles = user.getRoles();
        //把该用户拥有的角色id存到list放到前端
        //id变成一个list 前端方便判断该id是否在数组中 el ${fn:contains(ids,id)}
        List<Integer> ids=new ArrayList<>();
        for (Role role : userOwnedRoles) {
            ids.add(role.getId());
        }

        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("roles",roles);
        modelAndView.addObject("ids",ids);
        //真正执行添加业务时需要userId 因此也需要传过去
        modelAndView.addObject("userId",user.getId());//user.getId()而不直接写userId "永远使用最后一次得到的数据"
        modelAndView.setViewName("user-role-add");
        return modelAndView;
    }

3、页面回显数据(user-role-add.jsp)

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<section class="content">
	<input type="hidden" name="userId" value="${userId}"><%--用户id隐藏域--%>
	<table id="dataList"
			class="table table-bordered table-striped table-hover dataTable">
			<thead>
				<tr>
					<th class="" style="padding-right: 0px">
					<input id="selall" 
						type="checkbox" class="icheckbox_square-blue">th>
					<th class="sorting_asc">IDth>
					<th class="sorting">角色名称th>
					<th class="sorting">角色描述th>									
				tr>
			thead>
			<tbody>

				<c:forEach items="${roles}" var="role">
					<tr>
						<td><input name="ids" type="checkbox" value="${role.id}"
							<%--if test="${fn:contains(ids, role.id)}">checked="checked"c:if>--%>
								<%--大神更牛的写法--%>
								${fn:contains(ids, role.id)?"checked":"	"}

						>td>
						<td>${role.id}td>
						<td>${role.roleName }td>
						<td>${role.roleDesc}td>
						
					tr>
				c:forEach>
			tbody>

		table>

第四节:为用户分配角色-更新关系到用户角色中间表

1、页面入口

SSM练习第五天_第4张图片

2、编写Controller

    /**
     * 给指定用户添加指定角色
     * @param userId 需要添加角色的用户id
     * @param ids    添加角色的id数组
     * @return
     */
    @RequestMapping("/addRolesToUser")
    public String addRolesToUser(Integer userId,Integer[] ids){
        userService.addRolesToUser(userId,ids);
        return "redirect:/user/findAll";
    }

3、编写Service

接口

    /**
     * 添加角色列表到用户
     * @param userId
     * @param ids
     */
    void addRolesToUser(Integer userId, Integer[] ids);

实现

    @Override
    public void addRolesToUser(Integer userId, Integer[] ids) {
        //先清空该用户拥有的所有角色
        userdao.delRolesFromUser(userId);

        if(ids!=null){
            for (Integer roleId : ids) {
                userdao.saveRoleToUser(userId,roleId);
            }
        }
    }

4、编写Dao

    /**
     * 清空用户原来有的所有角色
     * @param userId
     */
    @Delete("delete from sys_user_role where userId=#{userId}")
    void delRolesFromUser(Integer userId);

    /**
     * 为用户添加一个角色
     * @param userId
     * @param roleId
     */
    @Insert("insert into sys_user_role values(#{param1},#{param2})")
    void saveRoleToUser(Integer userId, Integer roleId);

第五节:为角色添加权限数据回显(和user添加role雷同)

1、页面入口

SSM练习第五天_第5张图片

<a href="${pageContext.request.contextPath}/role/addPermissionsToRoleUI?roleId=#{role.id}" class="btn bg-olive btn-xs">添加权限a>

2、编写Controller

	/**
     * 添加权限到角色的数据回显
     * @param roleId
     * @return
     */
    @RequestMapping("/addPermissionsToRoleUI")
    public ModelAndView addPermissionsToRoleUI(Integer roleId){
        LogUtils.print(roleId);

        //获取所有权限
        List<Permission> permissions = permissionService.findAll();

        //获取角色已有权限id列表
        Role role = roleService.findById(roleId);
        List<Permission> rolePermissions = role.getPermissions();
        List<Integer> ids=new ArrayList<>();
        for (Permission p : rolePermissions) {
            ids.add(p.getId());
        }

        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("permissions",permissions);
        modelAndView.addObject("ids",ids);
        modelAndView.addObject("roleId",roleId);
        modelAndView.setViewName("role-permission-add");

        return modelAndView;
    }

3、编写Service

    Role findById(Integer roleId);
    @Override
    public Role findById(Integer roleId) {
        return roleDao.findById(roleId);
    }

4、编写Dao

    @Select("select * from sys_role where id=#{roleId}")
    @Results({
            @Result(property = "id",column = "id"),
            @Result(property = "permissions",column = "id",
                    many=@Many(select = "cn.ahpu.dao.PermissionDao.findPermissionsByRoleId",fetchType = FetchType.LAZY)
            )
    })
    Role findById(Integer roleId);

5、前端页面(role-permission-add.jsp)

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<form
	action="${pageContext.request.contextPath}/role/addPermissionToRole.do"
	method="post">
	
	<section class="content"> <input type="hidden" name="roleId"
		value="${roleId}">
		<table id="dataList"
				class="table table-bordered table-striped table-hover dataTable">
				<thead>
					<tr>
						<th class="" style="padding-right: 0px">
						<input id="selall" 
							type="checkbox" class="icheckbox_square-blue">th>
						<th class="sorting_asc">IDth>
						<th class="sorting">权限名称th>
						<th class="sorting">URLth>									
					tr>
				thead>
				<tbody>
					<c:forEach items="${permissions}" var="permission">
						<tr>
							<td><input name="ids" type="checkbox" value="${permission.id}"
									   ${fn:contains(ids, permission.id)?"checked":""}
							>td>
							<td>${permission.id}td>
							<td>${permission.permissionName }td>
							<td>${permission.url}td>
							
						tr>
					c:forEach>
				tbody>

			table>
	 
	<div class="box-tools text-center">
		<button type="submit" class="btn bg-maroon">保存button>
		<button type="button" class="btn bg-default"
			onclick="history.back(-1);">返回button>
	div>
	 section>
	
form>

第六节:为角色添加权限-实际保存即往中间表插入记录(和user添加role雷同)

1、页面入口

SSM练习第五天_第6张图片
SSM练习第五天_第7张图片

2、编写Controller

/**
     * 为角色添加权限 动数据库表
     * @param roleId
     * @param ids
     * @return
     */
    @RequestMapping("/addPermissionsToRole")
    public String addPermissionsToRole(Integer roleId,Integer[] ids){
        LogUtils.print(ids);
        LogUtils.print(roleId);

        roleService.addPermissionsToRole(roleId,ids);
        return "redirect:/role/findAll";
    }

3、编写service

    void addPermissionsToRole(Integer roleId, Integer[] ids);
   /**
     * 为角色roleId 添加 ids这么多的权限
     * @param roleId
     * @param ids
     */
    @Override
    public void addPermissionsToRole(Integer roleId, Integer[] ids) {
        //删除roleId所有权限
        roleDao.delPermissionsFromRole(roleId);

        if(ids!=null){
            for (Integer permissionId : ids) {
                roleDao.savePermissionToRole(roleId,permissionId);
            }
        }

    }

4、编写dao

   @Delete("delete from sys_role_permission where roleid=#{roleId}")
    void delPermissionsFromRole(Integer roleId);

    /**
     * 注意参数顺序
     * @param roleId
     * @param permissionId
     */
    @Insert("insert into sys_role_permission values(#{param2},#{param1})")
    void savePermissionToRole(Integer roleId, Integer permissionId);

第七节:为用户设置真正的角色

修改UserServiceImpl的loadUserByUsername方法,为用户设置真正的角色

/**
     * 通过用户名 得到用户对象
     * 创建用户详情对象,返回
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //根据用户名获取用户(SysUser)对象--同时查询相应角色
        SysUser sysUser = userdao.findByUsername(username);
        if(sysUser==null) return null;
        /* 添加的都是假的角色对象  真正的角色对象需要到数据库内查
        //配置文件里没有指定角色了 需要自己创建角色对象
        //创建角色的集合对象
        Collection authorities=new ArrayList<>();
        //创建临时角色对象  正常情况下应该是数据库角色表中查的
        GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_USER");
        //对象添加到集合中
        authorities.add(grantedAuthority);
        //User是安全框架内实现了UserDetails接口的一个类
        //第三个参数是:角色列表对象 (此处角色名ROLE_USER自己定义 xml里需要这个名字)
        //{noop}前缀表示不加密  该把不加密去掉了*/

        //添加数据库里真正的角色对象
        Collection<GrantedAuthority> authorities=new ArrayList<>();
        //登录时授权给用户 有哪些权限就授予哪些权限
        for (Role role : sysUser.getRoles()) {
            //LogUtils.print(role.getRoleName());
            //创建角色对象
            GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_"+role.getRoleName());
            //添加角色对象到集合
            authorities.add(grantedAuthority);
        }

        //用户名 密码 角色
        UserDetails user = new User(sysUser.getUsername(),sysUser.getPassword(),authorities);
        return user;
    }

userdao.findByUsername(username);,加个一对多结果集映射,否则查不到用户所拥有的权限

//根据用户名查询用户对象 唯一对象(username必须唯一)
    @Select("select * from sys_user where username = #{username} and status=1")
    @Results({
            @Result(id=true,property = "id",column = "id"),//主键id 最好都加上 否则后端获取id为null
            @Result(property = "roles",column = "id", //还是本张表主键id,因为是根据本张表主键id关联到role的
                    many = @Many(select = "cn.ahpu.dao.RoleDao.findRolesByUserId",fetchType = FetchType.LAZY))
    })
    SysUser findByUsername(String username);

第二章:授权后的安全控制

第一节:在JSP页面控制菜单权限(不显示UI)

在JSP页面中使用security:authorize标签,可以控制菜单是否显示。security:authorize标签的 access=“hasAnyRole(‘ROLE_USER’,‘ROLE_ADMIN’)”。因为标签的access使用的是表达式,所以需要将spring- security.xml配置文件的use-expressions设置为true。

1、spring-security.xml配置文件

1、使用表达式改为true: use-expressions=“true”
2、access不能直接写权限名而要写成:access="hasAnyRole(‘ROLE_USER’,‘ROLE_ADMIN’)”
表示拥有’ROLE_USER’,'ROLE_ADMIN’中任意一个权限就初步可以访问/**任意路径(真正目的是啥权限都没有时无法访问本网站任意未放行路径)
3、前端jsp 先加上标签库 然后
系统管理UI用 包裹
基础数据UI用包裹

在这里插入图片描述

jsp:

<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
<security:authorize access="hasRole('ROLE_ADMIN')">
	<li class="treeview"><a href="#"> <i class="fa fa-cogs">i>
			<span>系统管理span> <span class="pull-right-container"> <i
				class="fa fa-angle-left pull-right">i>
		span>
	a>
		<ul class="treeview-menu">
	
			<li id="system-setting"><a
				href="${pageContext.request.contextPath}/user/findAll"> <i
					class="fa fa-circle-o">i> 用户管理
			a>li>
			<li id="system-setting"><a
				href="${pageContext.request.contextPath}/role/findAll"> <i
					class="fa fa-circle-o">i> 角色管理
			a>li>
			<li id="system-setting"><a
				href="${pageContext.request.contextPath}/permission/findAll">
					<i class="fa fa-circle-o">i> 权限管理
			a>li>
			<li id="system-setting"><a
				href="${pageContext.request.contextPath}/pages/syslog-list.jsp"> <i
					class="fa fa-circle-o">i> 访问日志
			a>li>
		ul>li>
security:authorize>

<%--ROLE_ADMIN和ROLE_USER都可以使用 换言之啥权限都没有连基础数据都不能访问--%>
<security:authorize access="hasAnyRole('ROLE_ADMIN','ROLE_USER')">
	<li class="treeview"><a href="#"> <i class="fa fa-cube">i>
			<span>基础数据span> <span class="pull-right-container"> <i
				class="fa fa-angle-left pull-right">i>
		span>
	a>
		<ul class="treeview-menu">
	
			<li id="system-setting"><a
				href="${pageContext.request.contextPath}/product/findAll">
					<i class="fa fa-circle-o">i> 产品管理
			a>li>
			<li id="system-setting"><a
				href="${pageContext.request.contextPath}/order/findAll">
					<i class="fa fa-circle-o">i> 订单管理
			a>li>
		ul>li>
security:authorize>

第二节:在服务器端控制权限(拦截请求 防止用户直接输入url访问)

虽然页面菜单对不同角色显示类不同的菜单,但是如果直接访问服务器端的url还是可以访问到资源信息的,所以好 需要对服务器端的资源进行安全控制。

控制方式就是借助于Spring的AOP,对Controller的的访问进行权限的功能增强。 修改spring-security.xml配置文件,添加aop的自动代理

1、修改spring-mvc.xml配置

添加配置:

 
<aop:aspectj-autoproxy proxy-target-class="true">aop:aspectj-autoproxy>

<security:global-method-security secured-annotations="enabled"/>

没办法提示了,自己手动加: 复制后改下名字即可
SSM练习第五天_第8张图片

2、在需要进行控制的Controller上添加@Secured注解

指定拥有哪些权限时方可访问本Controller,用户任意一个权限即可

@Secured({"ROLE_ADMIN"})
public class UserController
@Secured({"ROLE_ADMIN"})
public class RoleController
@Secured({"ROLE_ADMIN"})
public class PermissionController

@Secured({"ROLE_ADMIN","ROLE_USER"})
public class ProductController

3、更换默认403 forbidden界面

spring-security.xml里加一行配置

<security:access-denied-handler error-page="/failer.jsp"></security:access-denied-handler>

SSM练习第五天_第9张图片

第三章:系统日志功能

第一节:AOP记录日志

1、日志表sys_log和实体Log

sql语句

create sequence log_seq;

CREATE TABLE sys_log(
    id number PRIMARY KEY,
    visitTime DATE,
    username VARCHAR2(50),
    ip VARCHAR2(30),
    method VARCHAR2(200)
)

实体类
SysLog.java

@Data
public class SysLog {
    private Long id;
    private Date visitTime;//访问时间
    private String username;//访问者用户名
    private String ip;//访问者ip
    private String method;//访问的全限定类名.方法
}

2、springmvc.xml配置文件中开启aop的自动代理

之前应该已经加过了

<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>

3、在web.xml中配置监听request对象的监听器

springmvc会自动将httpservletrequest放到IOC容器中 即springmvc不需要加此配置
其他框架不会 其他web层框架想要注入request就必须加此配置

	<!--配置请求监听器:当请求发生时,在容器中创建请求对象-->
  <listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
  </listener>

4、编写切面类(切面类内部有增强)

SSM练习第五天_第10张图片
spring-mvc.xml得多扫描一个包了
在这里插入图片描述

LogAop代码实现

package cn.ahpu.log;

import cn.ahpu.domain.SysLog;
import cn.ahpu.domain.SysUser;
import cn.ahpu.service.LogService;
import cn.ahpu.utils.LogUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * @author 寒面银枪
 * @create 2020-05-16 16:53
 *
 * 注解配置AOP
 * 提供一个类配置为切面类
 *  切面=切入点+通知
 *      通知类型
 *          前置增强:@Before
 *          后置增强:@AfterReturning
 *          最终增强:@After
 *          异常增强:@AfterThrowing
 *          环绕增强:@Around
 *
 */
//注意xml里加上扫描log包
@Component
@Aspect
public class LogController {

    @Autowired
    LogService logService;

    @Autowired
    HttpServletRequest request;//只有springmvc放到IOC中了 换一个框架可能就没了

    @Pointcut("execution(* cn.ahpu.controller.*.*(..))")
    public void pointcut(){}

    /**
     * 环绕增强
     * @param joinPoint 连接点对象--可以执行真实方法--只在环绕增强中使用
     *        连接点就是拦截的方法
     */
    @Around("pointcut()") //织入
    public Object around(ProceedingJoinPoint joinPoint){
        //创建日志对象
        SysLog sysLog = new SysLog();

        //将日志对象封装
        //1.访问时间 visitTime
        sysLog.setVisitTime(new Date());

        //2.访问用户名 username 安全框架内得到 注意是安全框架的User 不是自己写SysUser
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        sysLog.setUsername(user.getUsername());

        //3.访问ip 还是得得到request对象 仔细想想哪里有? IOC容器里肯定有 直接注入一下就行了嘛
        String ipAddr = request.getRemoteAddr();
        sysLog.setIp(ipAddr);

        //4.访问全限定类名
        //被拦截类的全限定类名
        String className = joinPoint.getTarget().getClass().getName();
        //方法名称
        String methodName = joinPoint.getSignature().getName();
        sysLog.setMethod(className+"."+methodName);

        //将日志对象存储到数据库
        LogUtils.print(sysLog);
        logService.save(sysLog);


        try {
            //执行真实的方法--必须返回真实方法返回值 否则所有方法被拦截 返回值都不返回 就不会跳转了
            return joinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }

}

5、Service代码实现

LogService

public interface LogService {
    void save(SysLog sysLog);
}
@Service
public class LogServiceImpl implements LogService {

    @Autowired
    LogDao logDao;

    @Override
    public void save(SysLog log) {
        logDao.save(log);
    }
}

6、Dao代码实现

public interface LogDao {
    @Insert("insert into sys_log values(log_seq.nextval,#{visitTime},#{username},#{ip},#{method})")
    void save(SysLog log);
}

第二节 查询日志

1、页面入口

SSM练习第五天_第11张图片
SSM练习第五天_第12张图片

2、编写Controller

/**
     * 查询所有日志  分页查询
     */
    @RequestMapping("/findAll")
    public ModelAndView findAll(
            @RequestParam(value = "currPage",required = false,defaultValue = "1") Integer currPage,
            @RequestParam(value = "pageSize",required = false,defaultValue = "5") Integer pageSize
    ){
        PageInfo<SysLog> pageHelper = logService.findAllByPageHelper(currPage, pageSize);

        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("pageHelper", pageHelper);
        modelAndView.setViewName("syslog-list");

        return modelAndView;
    }

3、编写service

public interface LogService {

    void save(SysLog sysLog);

    /**
     * 查询所有日志
     * @return
     */
    List<SysLog> findAll();

    /**
     * 分页查询所有
     * @param currPage
     * @param pageSize
     * @return
     */
    PageInfo<SysLog> findAllByPageHelper(Integer currPage, Integer pageSize);
}
    @Override
    public PageInfo<SysLog> findAllByPageHelper(Integer currPage, Integer pageSize) {
        //指定分页参数
        PageHelper.startPage(currPage,pageSize);
        //查询全部 分页参数已经被绑定到当前线程 拦截器根据参数帮你做到拦截
        List<SysLog> logs = logDao.findAll();
        //创建PageInfo对象 控制页面最多显示5个页码
        PageInfo<SysLog> pageInfo = new PageInfo<>(logs, 5);
        //返回
        return pageInfo;
    }

4、编写dao

    @Select("select * from sys_log")
    List<SysLog> findAll();

5、修改domain

加个字段方便访问

@Data
public class SysLog {
    private Long id;
    private Date visitTime;//访问时间
    private String visitTimeStr;
    private String username;//访问者用户名
    private String ip;//访问者ip
    private String method;//访问的全限定类名.方法

    public String getVisitTimeStr() {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String timeStr = sdf.format(visitTime);
        return timeStr;
    }
}

6、修改页面

<table id="dataList"
			class="table table-bordered table-striped table-hover dataTable">
			<thead>
				<tr>
					<th class="" style="padding-right: 0px"><input id="selall"
						type="checkbox" class="icheckbox_square-blue">th>
					<th class="sorting_asc">IDth>
					<th class="sorting">访问时间th>
					<th class="sorting">访问用户th>
					<th class="sorting">访问IPth>
					<th class="sorting">访问方法th>
				tr>
			thead>
			<tbody>
				<c:forEach items="${pageHelper.list}" var="syslog" varStatus="i">
					<tr>
						<td><input name="ids" type="checkbox">td>
						<td>${i.count}td>
						<td>${syslog.visitTimeStr }td>
						<td>${syslog.username }td>
						<td>${syslog.ip }td>
						<td>${syslog.method}td>
					tr>
				c:forEach>
			tbody>

		table>
		

		
		<div class="pull-left">
			<div class="form-group form-inline">
				<div class="btn-group">
					<button type="button" class="btn btn-default" title="刷新"
						onclick="window.location.reload();">
						<i class="fa fa-refresh">i> 刷新
					button>
				div>
			div>
		div>
		<div class="box-tools pull-right">
			<div class="has-feedback">
				<input type="text" class="form-control input-sm"
					placeholder="搜索"> <span
					class="glyphicon glyphicon-search form-control-feedback">span>
			div>
		div>
		
	div>
	

div>



<div class="box-footer">
	<div class="pull-left">
		<div class="form-group form-inline">
			第${pageHelper.pageNum} 页,
			总共${pageHelper.pages} 页,共${pageHelper.total} 条数据。 每页
			<select class="form-control" name="pageSize" id="pageSize" onchange="gotoPage(1)">
				<%--前10个用循环写 方便--%>
				<c:forEach begin="1" end="10" var="i">
					<option value="${i}">${i}option>
				c:forEach>
				<option value="15">15option>
				<option value="20">20option>
				<option value="30">30option>
				<option value="40">40option>
				<option value="50">50option>

			select>div>
	div>

	<div class="box-tools pull-right">
		<ul class="pagination" id="gotoLi">
			<%--超链接里访问js函数 必须加前缀javascript:--%>
			<li><a href="javascript:gotoPage(1)" aria-label="Previous">首页a>li>
			<%--prePage多方便--%>
			<li><a href="javascript:gotoPage(${pageHelper.prePage})">上一页a>li>
			<%--页面上显示几个页码也简单可控了 实在太方便了--%>
			<c:forEach begin="${pageHelper.navigateFirstPage}" end="${pageHelper.navigateLastPage}" var="i">
				<li><a href="javascript:gotoPage(${i})">${i}a>li>
			c:forEach>
			<li><a href="javascript:gotoPage(${pageHelper.nextPage})">下一页a>li>
			<li><a href="javascript:gotoPage(${pageHelper.pages})" aria-label="Next">尾页a>li>
		ul>
	div>

div>

js:

<script type="text/javascript">
        //方法写在外面 会自动执行 注意先得给每个option加上value="xx" 不能没有value属性
        //每页显示几条的数据回显 select option
        $("#pageSize option[value=${pageHelper.pageSize}]").prop("selected","selected");

        //跳转页面
        function gotoPage(currPage) {
            //页面的越界检查此处判断也很方便
            if(currPage<1||currPage>${pageHelper.pages}) return;

            var pageSize=$("#pageSize").val();
            location.href="${pageContext.request.contextPath}/log/findAll?currPage="+currPage+"&pageSize="+pageSize;
        }

	</script>

你可能感兴趣的:(后端框架-SSM,#,ssm实战)