前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >SSM综合案例之动态权限实战教程

SSM综合案例之动态权限实战教程

作者头像
张哥编程
发布于 2024-12-13 06:23:14
发布于 2024-12-13 06:23:14
8600
代码可运行
举报
文章被收录于专栏:云计算linux云计算linux
运行总次数:0
代码可运行

一、课程目标

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1. 【了解】动态权限配置
2. 【掌握】AOP日志管理

二、动态权限

2.1 将公开权限设置为无需认证即可访问

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!-- 配置不拦截的资源 -->
    <security:http pattern="/login.jsp" security="none"/>
    <security:http pattern="/failer.jsp" security="none"/>
    <security:http pattern="/css/**" security="none"/>
    <security:http pattern="/img/**" security="none"/>
    <security:http pattern="/layui/**" security="none"/>

2.2 配置具体的规则

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!--
        配置具体的规则
        auto-config="true"  不用自己编写登录的页面,框架提供默认登录页面
        use-expressions="true"  是否使用SPEL表达式(否则只能使用USER_角色的形式配置)
    -->
    <security:http auto-config="true" use-expressions="true">
        <!-- 同源策略 如果页面使用iframe需要配置 否则不能使用 -->
        <security:headers>
            <security:frame-options disabled="true"/>
        </security:headers>

        <!-- 定义跳转的具体的页面 -->
        <security:form-login
                login-page="/login.jsp"
                login-processing-url="/login"
                default-target-url="/index.jsp"
                authentication-failure-url="/failer.jsp"
                authentication-success-forward-url="/users/name"
        />
        <security:intercept-url pattern="/**"   access="isAuthenticated()"/>
        <!-- 配置具体的拦截的规则 pattern="请求路径的规则" access="isAuthenticated()" 
        <!-- 权限框架本质是过滤器链 会依次进行权限验证 如果验证通过继续执行  
        该配置 配置的是 除以上不拦截的资源外 所有url请求必须拥有认证的权限(登录后才能访问)
-->
        <!-- 关闭跨域请求 -->
        <security:csrf disabled="true"/>
        <!-- 退出 -->
        <security:logout invalidate-session="true" logout-url="/logout" logout-success-url="/login.jsp" />
    </security:http>

2.3 设置权限数据

2.4 自定义相关过滤器与决策器

自定义决策管理器

权限框架本身是由多个不同功能的过滤器组成的,不同的过滤器负责不同的功能例如认证过滤、静态资源过滤、等 授权过滤也是一样,决策器就是同于判断当前请求的url当前账号是否拥有权限

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.Iterator;
@Service
//决策管理器
public class MyAccessDecisionManager implements AccessDecisionManager {

    // decide 方法是判定是否拥有权限的决策方法,
    //authentication 是释CustomUserService中循环添加到 GrantedAuthority 对象中的权限信息集合.
    //object 包含客户端发起的请求的requset信息,可转换为 HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
    //configAttributes 为MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法返回的结果,此方法是为了判定用户请求的url 是否在权限表中,如果在权限表中,则返回给 decide 方法,用来判定用户是否有此权限。如果不在权限表中则放行。
    @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {

        if(null== configAttributes || configAttributes.size() <=0) {
            return;
        }
        ConfigAttribute c;
        String needRole;
        for(Iterator<ConfigAttribute> iter = configAttributes.iterator(); iter.hasNext(); ) {
            c = iter.next();
            needRole = c.getAttribute();
            for(GrantedAuthority ga : authentication.getAuthorities()) {//authentication 为在注释1 中循环添加到 GrantedAuthority 对象中的权限信息集合
                if(needRole.trim().equals(ga.getAuthority())) {
                    return;
                }
            }
        }
        throw new AccessDeniedException("no right");
    }

    @Override
    public boolean supports(ConfigAttribute attribute) {
        return true;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }
}
自定义权限加载器
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import com.yunhe.javabean.Permission;
import com.yunhe.mapper.PermissionMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Service;

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

@Service
//授权管理器
//用于当前项目要动态配置的权限信息
//从数据库中取出所有的权限信息 进行配置
//这样当客户请求对应权限时进行权限验证(因为不可能将所有的url都过滤)
public class MyInvocationSecurityMetadataSourceService  implements
        FilterInvocationSecurityMetadataSource {

    @Autowired
    //注入权限查询的dao层
    private PermissionMapper permissionMapper;

    private HashMap<String, Collection<ConfigAttribute>> map =null;

    /**
     * 加载权限表中所有权限
     */
    public void loadResourceDefine(){
        map = new HashMap<>();
        Collection<ConfigAttribute> array;
        ConfigAttribute cfg;
        //动态查询当前数据库中所有的权限
        List<Permission> permissions = permissionMapper.selectAll();
        for(Permission permission : permissions) {
            array = new ArrayList<>();
            cfg = new SecurityConfig(permission.getPermissionName());
            //此处只添加了权限的名字,其实还可以添加更多权限的信息,例如请求方法到ConfigAttribute的集合中去。此处添加的信息将会作为MyAccessDecisionManager类的decide的第三个参数。
            array.add(cfg);
            //用权限的getUrl() 作为map的key,用ConfigAttribute的集合作为 value,
            //实际加载存储的结构为 url->[name1,name2....]
            //url是进行请求url拦截使用的  name是进行权限验证使用的
            //也就是说在用户进行授权时 实际加载的是权限名称

            map.put(permission.getUrl(), array);
        }

    }

    //此方法是为了判定用户请求的url 是否在权限表中,如果在权限表中,则返回给 decide 方法,用来判定用户是否有此权限。如果不在权限表中则放行。
    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
        if(map ==null) loadResourceDefine();
        //object 中包含用户请求的request 信息
        HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
        AntPathRequestMatcher matcher;
        String resUrl;
        for(Iterator<String> iter = map.keySet().iterator(); iter.hasNext(); ) {
            resUrl = iter.next();
            matcher = new AntPathRequestMatcher(resUrl);
            if(matcher.matches(request)) {
                return map.get(resUrl);
            }
        }
        return null;
    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }
}
自定义权限拦截器
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
import org.springframework.security.access.intercept.InterceptorStatusToken;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Service;

import javax.servlet.*;
import java.io.IOException;

@Service
//自定义权限拦截器
//FilterSecurityInterceptor是权限框架中用于处理权限验证的过滤器
public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {


    //使用自己定义权限加载器
    @Autowired
    private FilterInvocationSecurityMetadataSource securityMetadataSource;

    //使用自定义的决策管理器
    @Autowired
    public void setMyAccessDecisionManager(MyAccessDecisionManager myAccessDecisionManager) {
        super.setAccessDecisionManager(myAccessDecisionManager);
    }


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        FilterInvocation fi = new FilterInvocation(request, response, chain);
        invoke(fi);
    }


    public void invoke(FilterInvocation fi) throws IOException, ServletException {
//fi里面有一个被拦截的url
//里面调用MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法获取fi对应的所有权限
//再调用MyAccessDecisionManager的decide方法来校验用户的权限是否足够
        InterceptorStatusToken token = super.beforeInvocation(fi);
        try {
//执行下一个拦截器
            fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
        } finally {
            super.afterInvocation(token, null);
        }
    }

    @Override
    public void destroy() {

    }

    @Override
    public Class<?> getSecureObjectClass() {
        return FilterInvocation.class;
    }

    @Override
    public SecurityMetadataSource obtainSecurityMetadataSource() {
        return this.securityMetadataSource;
    }
}

2.5 将自定义权限拦截器配置入权限框架中

在security:http标签中添加

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!-- 配置自定义拦截器 将定义拦截器配置到当前权限框架拦截器链中的指定位置
           将其配置在本身的权限认证过滤器之后执行
          -->
<security:custom-filter ref="myFilterSecurityInterceptor" after="FILTER_SECURITY_INTERCEPTOR"></security:custom-filter>

2.6 配置授权页面

在配置后使用账号登录会出现没有权限403代码页面

如果用户登录进行操作时,直接报403错误用户体检并不好,我们可以制作一个比较好看的页面,告诉用户您用户不足,请联系管理员!

在web.xml中配置

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<error-page>
    <error-code>403</error-code>
    <location>/failer.jsp</location>
  </error-page>

2.7 授权

在书写权限加载器时,我们发现,加载器加载url是用于http请求的过滤匹配,而实际进行权限验证使用的是权限名称,为了方便书写,我们在登录认证时查询权限信息进行授权操作

修改PermissionMapper

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//根据用户id查询权限数据
    public List<Permission> selectByUid(int uid);
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.yunhe.mapper.PermissionMapper">
    <select id="selectByUid" resultType="com.yunhe.javabean.Permission">
        select p.*
        from users u,role r,permission p,users_role ur,role_permission rp
        where u.id=ur.userId and r.id=ur.roleId and r.id=rp.roleId and p.id =rp.permissionId and u.id=#{uid}
    </select>
</mapper>

修改PermissionService

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//根据uid查询权限数据
    public List<Permission> findByUid(int uid);
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
    public List<Permission> findByUid(int uid) {
        return permissionMapper.selectByUid(uid);
    }

修改userService

将我们之前书写写死的角色认证与权限认证查询数据库的形式添加

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //查询数据返回实体类对应数据
        Users users = userMapper.selectByUserName(username);
        if (users != null) {
            //创建springSecurity主体中存储的账号对象并返回(账号,密码,权限列表)
            UserDetails userDetails = new User(users.getUsername(), users.getPassword(), getAuthority(users.getId()));
            return userDetails;
        }
        return null;
    }

    @Autowired
    PermissionService permissionService;
    //获取权限列表
    public List<GrantedAuthority> getAuthority(int uid) {
        List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
        //查询指定用户权限列表
        List<Permission> permissionList = permissionService.findByUid(uid);
        for (Permission p:permissionList ) {
            GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(p.getPermissionName());
            grantedAuthorities.add(grantedAuthority);
        }
        return grantedAuthorities;
    }

三、AOP日志管理

3.1 数据库与表结构

日志表信息描述sysLog

序号

字段名称

字段类型

字段描述

1

id

VARCHAR(32)

主键 无意义uuid

2

vistTime

TIMESTAMP

访问时间

3

username

VARCHAR(32)

操作用户

4

ip

VARCHAR(50)

访问ip

5

url

VARCHAR(50)

访问资源url

6

executionTime

INT

执行时长

7

className

VARCHAR(50)

访问方法所在类

8

methodName

VARCHAR(50)

访问方法

9

args

VARCHAR(50)

访问方法参数列表

sql语句
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CREATE TABLE `syslog` (
  `id` int(70) NOT NULL AUTO_INCREMENT,
  `visitTime` datetime DEFAULT NULL COMMENT '访问时间',
  `username` varchar(50) DEFAULT NULL COMMENT '操作者用户名',
  `ip` varchar(40) DEFAULT NULL COMMENT '访问ip',
  `url` varchar(40) DEFAULT NULL COMMENT '访问资源url',
  `executionTime` int(11) DEFAULT NULL COMMENT '执行时长',
  `className` varchar(255) DEFAULT NULL COMMENT '访问方法类名',
  `methodName` varchar(255) DEFAULT NULL COMMENT '访问方法名',
  `args` varchar(255) DEFAULT NULL COMMENT '访问方法参数',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=181 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
创建实体类
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SysLog {
    private int id;
    private Date visitTime;
    private String visitTimeStr;
    private String username;
    private String ip;
    private String url;
    private Long executionTime;
    private String className;
    private String methodName;
    private String args;

    public String getVisitTimeStr() {
        // 对日期格式化
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        if (null != visitTime) {
            visitTimeStr = dateFormat.format(visitTime);
        }
        return visitTimeStr;
    }
}

3.2 AOP日志处理

导入坐标
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.5</version>
</dependency>
修改applicationContext-tx.xml
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
   http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
   http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
   http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">


    <!-- 定义事务管理器 -->
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!--开启事务注解-->
    <tx:annotation-driven/>

</beans>
修改springmvc-config.xml
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:security="http://www.springframework.org/schema/security"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/mvc
      http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
      http://www.springframework.org/schema/security
      http://www.springframework.org/schema/security/spring-security.xsd">

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


    <!-- 视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/pages/"/>
        <property name="suffix" value=".jsp"/>
        <property name="contentType" value="text/html;charset=UTF-8"/>
    </bean>

    <!-- 开启注解驱动 -->
    <mvc:annotation-driven/>

    <!-- 开启注解扫描包-->
    <context:component-scan base-package="cn.yanqi.ssm.web" />

    <!--开启AOP注解支持,开启AspectJ 注解自动代理机制,扫描含有@Aspect的bean-->
    <aop:aspectj-autoproxy/>

</beans>
编写SysLogMapper
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface SysLogMapper {
    @Insert("insert into syslog (visitTime,username,ip,url,executionTime,classname,methodName,args) values(#{visitTime},#{username},#{ip},#{url},#{executionTime},#{className},#{methodName},#{args})")
    public int insert(SysLog sysLog);
}
编写SysLogService
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface SysLogService {

    public int add(SysLog syslog);

}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Service("sysLogService")
public class SysLogServiceImpl implements SysLogService {

    @Autowired
    SysLogMapper sysLogMapper;
    @Override
    public int add(SysLog syslog) {
        return sysLogMapper.insert(syslog);
    }
}
创建切面类

在aop层创建AOP类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component
@Aspect
public class LogAop {
    //创建一个访问日志的切面类,交给spring管理

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private SysLogService sysLogService;

    private Date visitTime; //开始时间

    //前置通知  主要是获取开始时间,执行的类是哪一个,执行的是哪一个方法  JoinPoint程序执行过程中明确的点
    @Before("execution(* com.yunhe.controller.*.*(..))")
    public void doBefore(JoinPoint jp) throws NoSuchMethodException {
        visitTime = new Date();//当前时间就是开始访问的时间
    }

    //后置通知
    @After("execution(* com.yunhe.controller.*.*(..))")
    public void doAfter(JoinPoint jp) throws Exception {
        long time = new Date().getTime() - visitTime.getTime(); //获取访问的时长
        String className = jp.getTarget().getClass().getSimpleName(); //具体要访问的类
        String methodName = jp.getSignature().getName(); //获取访问的方法的名称
        Object[] args = jp.getArgs();
        String url = request.getRequestURI();
        String ip = request.getRemoteAddr();
        ip = ip.equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip;
        //获取当前操作的用户
        SecurityContext context = SecurityContextHolder.getContext();//从上下文中获了当前登录的用户
        User user = (User) context.getAuthentication().getPrincipal();
        String username = user.getUsername();

        //将日志相关信息封装到SysLog对象
        SysLog sysLog = new SysLog();
        sysLog.setExecutionTime(time); //执行时长
        sysLog.setIp(ip);
        sysLog.setClassName(className);
        sysLog.setMethodName(methodName);
        sysLog.setArgs(Arrays.toString(args));
        sysLog.setUrl(url);
        sysLog.setUsername(username);
        sysLog.setVisitTime(visitTime);

        //调用Service完成操作
        int add = sysLogService.add(sysLog);
    }
}
注意事项

1、要想在AOP类中使用request类获取用户主机的IP地址,我们需要在web.xml配置request的监听器

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<listener>
   <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

2、aop动态代理注解扫描书写在springmvc中

3、aop切面类存放在sop包中,如果书写在controoler可能出现问题

测试

3.3 查询所有日志

编写SysLogMapper
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//根据用户名称与url模糊查询
    public List<SysLog> selectByUsernameAndUrl(@Param("username") String username, @Param("url")String url);
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yunhe.mapper.SysLogMapper">

<select id="selectByUsernameAndUrl" resultType="com.yunhe.javabean.SysLog">
    select * from syslog
    <where>
        <if test="username!='' and username!=null ">
            and username like '%' #{username} '%'
        </if>

        <if test="url!='' and url!=null ">
            and url like '%' #{url} '%'
        </if>
    </where>
    order by id desc
</select>

</mapper>
编写SysLogService
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public List<SysLog> findAll(String username,String url);
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
    public List<SysLog> findAll(String username, String url) {
        return sysLogMapper.selectByUsernameAndUrl(username,url);
    }
编写SysLogController
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Controller
@RequestMapping("/syslog")
public class SysLogController {
    @Autowired
    SysLogService sysLogService;

    @RequestMapping("/findAll")
    public String findAll(HttpServletRequest request, @RequestParam(value = "username",required = false,defaultValue = "") String username,@RequestParam(value = "url",required = false,defaultValue = "") String url,@RequestParam(value = "page",required = false,defaultValue = "1") int page, @RequestParam(value = "limit",required = false,defaultValue = "5")int limit){
        PageHelper.startPage(page,limit);
        List<SysLog> all = sysLogService.findAll(username, url);
        PageInfo<SysLog> pageInfo=new PageInfo<>(all);

        request.setAttribute("pageInfo",pageInfo);
        request.setAttribute("username",username);
        request.setAttribute("url",url);
        return "/syslog/syslog-list";
    }
}
测试
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-10-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
广州 Meetup|Pulsar AI+ 议题征集 | PulsarMeetup 广州 2025 大会正式启动!
本各位热爱 Pulsar 的小伙伴们,Pulsar 2025 年度第一场 Meetup 来啦!干货多多,礼品多多,不容错过!
腾讯云中间件团队
2025/03/17
1310
广州 Meetup|Pulsar AI+ 议题征集 | PulsarMeetup 广州 2025 大会正式启动!
邀请函 | Pulsar Meetup 深圳 2024
Pulsar Meetup 深圳 2024 将于 2024 年 4 月 27 日 周六举办,此次活动由 AscentStream 谙(ān)流科技和腾讯云中间件联合举办。Apache Pulsar 社区和合作伙伴诚邀 Pulsar 和各大社区的小伙伴、广大技术爱好者、架构师和企业代表参与。
腾讯云中间件团队
2024/04/19
2790
邀请函 | Pulsar Meetup 深圳 2024
Pulsar Meetup 深圳 2024 会务介绍
由 AscentStream 谙流科技和腾讯云中间件联合主办的 Pulsar Meetup 深圳 2024 将于 2024年04月27日 14:00-18:00 在深圳腾讯大厦2楼多功能厅,精彩呈现,期待大家多多报名!
腾讯云中间件团队
2024/04/25
2150
Pulsar Meetup 深圳 2024 会务介绍
Pulsar Meetup 深圳 2024 讲师和议题介绍
由 AscentStream 谙流科技和腾讯云中间件联合主办的 Pulsar Meetup 深圳 2024 将于 2024年04月27日 周六 14:00-18:00 在深圳腾讯大厦2楼多功能厅,精彩呈现,期待大家多多报名!
腾讯云中间件团队
2024/04/23
3200
Pulsar Meetup 深圳 2024 讲师和议题介绍
Pulsar Meetup 深圳 2024 大咖推荐
由 AscentStream 谙流科技和腾讯云中间件联合主办的 Pulsar Meetup 深圳 2024 将于 2024年04月27日 14:00-18:00 在深圳腾讯大厦 2 楼多功能厅,精彩呈现,期待大家多多报名!
腾讯云中间件团队
2024/04/28
2870
Pulsar Meetup 深圳 2024 大咖推荐
邀请函|2021 Apache Pulsar Meetup - 深圳站
引言 | Apache Pulsar 是 Apache 软件基金会顶级项目,是下一代云原生分布式消息流平台,集消息、存储、轻量化函数式计算为一体,采用计算与存储分离架构设计,支持多租户、持久化存储、多机房跨区域数据复制,具有强一致性、高吞吐、低延时及高可扩展性等流数据存储特性。GitHub 地址:http://github.com/apache/pulsar/  Apache Pulsar Meetup 深圳站 活动时间:2021年4月17日(本周六)13:30 ~ 18:00 活动地点:深圳市腾讯大
腾讯云开发者
2021/04/15
6860
【邀请函】Apache IoTDB x Apache Pulsar Meetup
>>> 活动介绍 <<< Apache Pulsar 是下一代云原生分布式流数据平台,它源于 Yahoo,2016 年 12 月开源,2018 年 9 月正式成为 Apache 顶级项目,逐渐从单一的消息系统演化成集消息、存储和函数式轻量化计算的流数据平台。 从成为 Apache 顶级项目后,在这一年的时间中,Pulsar 发展势头非常迅速,目前在全球拥有 100+ 的企业级用户,像雅虎、苹果、迪斯尼、Hulu、腾讯、中国移动、中国电信、智联招聘、涂鸦智能、个推等公司都在使用 Pulsar。 Pu
腾讯技术工程官方号
2019/12/30
6600
【邀请函】Apache IoTDB x Apache Pulsar Meetup
速来围观,Apache Pulsar Meetup 深圳站来啦!| 现场精美礼品等你来拿
关于 Apache Pulsar Apache Pulsar 是 Apache 软件基金会顶级项目,是下一代云原生分布式消息流平台,集消息、存储、轻量化函数式计算为一体,采用计算与存储分离架构设计,支持多租户、持久化存储、多机房跨区域数据复制,具有强一致性、高吞吐、低延时及高可扩展性等流数据存储特性。GitHub 地址:http://github.com/apache/pulsar/ Apache Pulsar Meetup 深圳站 活动时间:2021年4月17日(本周六)13:30 ~ 18:
腾讯云中间件团队
2021/04/13
7210
开启行业智变新征程,腾讯云架构师技术沙龙邀你解锁DeepSeek实战应用
从2025开年的惊艳登场,到逐步落地的价值兑现,DeepSeek正以实战为突破点,推动 AI 技术落地的深水区变革。随着其工程化能力与行业场景的深度耦合,DeepSeek已从“技术验证”迈入“场景攻坚”阶段,互联网、金融、制造等行业的标杆案例接连涌现,一场由实战驱动的行业智变浪潮正席卷而来。
TVP官方团队
2025/03/12
1560
开启行业智变新征程,腾讯云架构师技术沙龙邀你解锁DeepSeek实战应用
聚集云原生,可观测性的实践与探索 | 线下技术沙龙
导语 由腾讯云腾源会和 Apache SkyWalking 社区联合主办办,腾讯开源协办的 SkyWalkingDay 线下Meetup活动将于6月26日在北京举行,现场不仅有技术大咖带来满满的技术干货,还有Aripods Pro、腾讯公仔、贴纸等精美礼品,小伙伴们快来报名参加吧! 活动背景 在云原生时代,微服务、容器化、serverless等技术从根本上改变了应用的开发、运维方式。在提升效率的同时,也带来了更复杂的服务关系,如何快速定位问题,提供清晰的链路分析,使得可观测解决方案成为云原生架
腾讯开源
2021/06/25
4530
聚集云原生,可观测性的实践与探索 | 线下技术沙龙
导语 由腾讯云腾源会和 Apache SkyWalking 社区联合举办的 SkyWalkingDay 线下Meetup活动将于6月26日在北京举行,现场不仅有技术大咖带来满满的技术干货,还有Aripods Pro、腾讯公仔、贴纸等精美礼品,小伙伴们快来报名参加吧! 活动背景 在云原生时代,微服务、容器化、serverless等技术从根本上改变了应用的开发、运维方式。在提升效率的同时,也带来了更复杂的服务关系,如何快速定位问题,提供清晰的链路分析,使得可观测解决方案成为云原生架构下非常重要
腾讯技术工程官方号
2021/06/15
4440
成都活动 : 第17届「BQMeetUp - Wiremock实战」报名进行中
Hi 好久不见成都的测试君们!在测试过程中,如果后端依赖曾让你崩溃万分、如果由于后端依赖不稳定的问题曾让你苦不堪言,那么我们新一期的线下测试技术交流活动非常适合你!
ThoughtWorks
2018/07/23
5740
成都活动 : 第17届「BQMeetUp - Wiremock实战」报名进行中
斯人若彩虹,这里有一份属于你的邀请函哦~
全球数字生态大会是腾讯全新升级打造的行业创新大会,已于今年在春城昆明成功举办,目前,腾讯正在筹办全球数字生态大会·城市峰会, 腾讯企点作为产业智连数字化的生力军也在会上大放异彩。这一次,企点君将继续携手全球数字生态大会与您相约魅力之都——上海。 本次峰会专场,企点君也有幸邀请到了各产业领军人物出席,和大家一起探讨产业如何完成数字化转型及破局这一课题,大家是不是期待呢~ 企点产业智连专场 企点君偷偷告诉大家,这两年企点一直专注于企业服务与产业上下游连接两大数字化领域。本次专场,企点会重点发布产业上下游连
腾讯企点
2020/06/10
4170
腾讯云大模型知识引擎×DeepSeek最佳实践有奖征文活动
作者获奖名单公布 获奖名单请移步官网文档查看:https://cloud.tencent.com/document/act 届时会发站内信和短信通知获奖,请获奖
腾讯云开发者社区
2025/02/14
22.9K16
叮咚~ 你的Techo大会云存储专场邀请函到了!
12月19日至20日,由腾讯主办的2020 Techo Park开发者大会将于北京召开。Techo Park 开发者大会是由腾讯发起的面向全球开发者和技术爱好者的年度盛会,作为一个专注于前沿技术研讨的非商业大会,大会致力于开发者的能力成长和实践创新,旨在通过汇聚全球顶尖行业专家和技术爱好者,搭建一个开放、中立、活跃的技术交流平台。今年大会将设置1场主论坛,29场垂直技术分论坛,还有互动展区、圆桌派、动手实验室等趣味性活动。
云存储
2020/12/15
4000
汽车后市场服务营销怎么玩,腾讯企点邀您一起探讨!
12月2日-12月5日,Automechanika Shanghai将在国家会展中心(上海)正式拉开帷幕。作为2020年末最值得令人期待的汽车后市场盛宴,各路汽配行业制造商、经销商、服务商们都将云集上海。那么腾讯企点将在其中输出哪些能力呢? 为更好满足全方位会展体验,Automechanika Shanghai基于腾讯企点领航平台的能力,为此次展会的展商和参展商提供了领先的AMS Live线上平台,通过线下实体展览会与线上平台的全方位联动展示,突破时间和地域的界限,为全球的参展企业和观众缔造耳目一新的
腾讯企点
2020/12/04
5960
赠票!周六广州产品经理线下沙龙来了!
娱乐作为人类的基本需求之一,由它衍生出来的泛娱乐社交产品一直备受消费者的欢迎,同时也是互联网行业投资和创业的一大风口。技术的发展进一步拉近社交的距离,媒介的迭代跟进给泛娱乐产品带来新方向。 在AIGC时代的加持下,社交娱乐产品还能有哪些新玩法?社交娱乐产品的发展?对于所有的社交泛娱乐厂商、创业者、从业者来说:产品的场景迭代创新可以带来哪些新的玩法?如何洞察用户深层次的需求?等等一系列问题都可以在线下沙龙中找到自己想要的答案! 现场学习氛围活跃,嘉宾现场答疑,超多高颜值小伙伴互相学习,成为一名优秀的产品经
腾讯大讲堂
2023/04/28
2750
赠票!周六广州产品经理线下沙龙来了!
下周末,广州产品运营大会会讲什么干货,看这里
2018,多变的一年。 一线城市互联网用户市场趋于饱和,人口红利带来的高增长渗透率消失殆尽,流量革命到来。产品生命周期缩短,运营渠道流量变小。互联网下半场,竞争逐渐回归本源。 短视频,区块链,新零售,人工智能等新兴浪潮此起彼伏,未来,风口和趋势将如何发展? 行业在进步,人才需求在改变。互联网领域服务愈发细分化,人才专业核心技能要求更突出。面对快速变化的时代,不论是产品、运营或技术,都无法独善其身。不努力往前追赶,将终会被淘汰。 今年,我们遇见了6000+位对持续学习、个人成长保持着强烈的欲望的产品汪、
腾讯大讲堂
2018/11/14
9000
下周末,广州产品运营大会会讲什么干货,看这里
重磅邀请函来了!首届“腾讯腾讯云开发者社区开发者大会”免费报名!
2018年12月15日,首届“腾讯云+社区开发者大会”即将在北京隆重举行,腾讯云邀请广大开发者共同探讨云端新技术、新能力。届时,腾讯云将邀请超过40位行业内的技术专家,超过1000名开发者参与本次盛会,分享行业经验,沉淀云端技术。
腾讯云开发者社区
2018/11/21
2.6K0
重磅邀请函来了!首届“腾讯腾讯云开发者社区开发者大会”免费报名!
腾讯云【燎原社】云原生技术实战营全国巡演报名开启啦!首站广州!
腾讯云【燎原社】是腾讯云原生容器产品中心与CNCF基金会及Linux 开源软件学园面向企业CTO技术团队Leader、开发运维架构师等,共同打造的云原生全栈化内容&技术应用的生态交流平台,为用户提供更完善的云原生产品及服务,意在解决企业云原生改造最后一公里问题。 腾讯云【燎原社】已经在全国推出云原生高端闭门会、云原生技术实战营、云原生专家服务等多种服务及活动,获得上千家客户的肯定。 如今,我们全面启动【燎原社】云原生技术实战营2022年全国巡演,邀请更多企业用户一起参与,交流企业云原生上云经验,持续致力帮
腾讯云原生
2022/04/14
8980
腾讯云【燎原社】云原生技术实战营全国巡演报名开启啦!首站广州!
推荐阅读
相关推荐
广州 Meetup|Pulsar AI+ 议题征集 | PulsarMeetup 广州 2025 大会正式启动!
更多 >
LV.1
这个人很懒,什么都没有留下~
目录
  • 一、课程目标
  • 二、动态权限
    • 2.1 将公开权限设置为无需认证即可访问
    • 2.2 配置具体的规则
    • 2.3 设置权限数据
    • 2.4 自定义相关过滤器与决策器
      • 自定义决策管理器
      • 自定义权限加载器
      • 自定义权限拦截器
    • 2.5 将自定义权限拦截器配置入权限框架中
    • 2.6 配置授权页面
    • 2.7 授权
  • 三、AOP日志管理
    • 3.1 数据库与表结构
      • 日志表信息描述sysLog
      • sql语句
      • 创建实体类
    • 3.2 AOP日志处理
      • 导入坐标
      • 修改applicationContext-tx.xml
      • 修改springmvc-config.xml
      • 编写SysLogMapper
      • 编写SysLogService
      • 创建切面类
      • 注意事项
      • 测试
    • 3.3 查询所有日志
      • 编写SysLogMapper
      • 编写SysLogService
      • 编写SysLogController
      • 测试
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档