记录Java注解在JavaWeb中的一个应用实例
概述
在学习注解的时候,学了个懵懵懂懂。学了JavaWeb之后,在做Demo项目的过程中,借助注解和反射实现了对页面按钮的权限控制,对于注解才算咂摸出了点味儿来。
需求
以"角色列表"页面为例,该页面包含"新建","编辑","启用/禁用","删除"四个权限。根据用户所属角色的权限,来控制这些按钮是否显示。问题是,如何确定哪些页面下包含哪些按钮?

实现
定义注解
package com.ttpfx.bean;
import java.lang.annotation.*;
@Target(ElementType.METHOD) // 注解的作用对象:只能用于方法
@Retention(RetentionPolicy.RUNTIME) // 注解的级别:运行时有效,可以通过反射获取注解信息
@Repeatable(Buttons.class) // 可重复注解: 一个方法可以有多个Button注解,一个方法的多个Button注解将组成一个Buttons返回
public @interface Button {
    String servlet(); // ServletName
    String action(); // ActionName, 每个action是Servlet中的一个方法,代表一个请求地址:servletName?action=actionName
    String name(); // 按钮名称
}
package com.ttpfx.bean;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Buttons {
    Button[] value(); // Button注解的数组,通过Btuuons.value()获取页面的多个Button
}
在Servlet中使用注解
public class RoleServlet extends BaseServlet {
    private RoleService roleService = new RoleServiceImpl();
    // RoleServlet.index() 对应角色列表页面,访问地址为:/role?action=index
    // 该页面包含"新建","编辑","启用/禁用","删除"四个权限
    @Button(servlet = "role", action = "add", name = "add")
    @Button(servlet = "role", action = "edit", name = "edit")
    @Button(servlet = "role", action = "changeStatus", name = "changeStatus")
    @Button(servlet = "role", action = "delete", name = "delete")
    protected void index(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // ....
    }
}
在BaseServlet中校验页面按钮的权限,并将结果保存在requestScope中
// method:Servlet中的方法, 如上面RoleServlet.index()
private Map<String, Boolean> getButtonPermissions(Method method) {
    // buttonMap是一个以Button.name为key, 以是否有权限的布尔值为value的键值对
    // 该结果会被保存在requestScope中,供jsp页面使用
    Map<String, Boolean> buttonMap = new HashMap<>();
    Button[] buttonAnnotations = null;
    // 页面有一个Button注解的时候可以直接获取
    // 页面有多个Button注解的时候,只能获取到Buttons注解,再通过Buttons.value()方法得到多个Button注解
    Buttons buttonsAnnotation = method.getAnnotation(Buttons.class);
    Button buttonAnnotation = method.getAnnotation(Button.class);
    if (buttonsAnnotation != null) {
        buttonAnnotations = buttonsAnnotation.value();
    } else if (buttonAnnotation != null){
        buttonAnnotations = new Button[] {buttonAnnotation};
    }
    if (buttonAnnotations != null) {
        for (Button button : buttonAnnotations) {
            // 在这里实现对每个按钮的权限验证,将结果put至buttonMap
            // 真正的验证过程已省略
            buttonMap.put(button.name, true);
        }
    }
    return buttonMap;
}
在页面的jsp文件中,控制按钮是否显示
<c:if test="${requestScope.buttonMap.add}">
      <button type="button">新建角色</button>
</c:if>
												
											记录Java注解在JavaWeb中的一个应用实例的更多相关文章
- 12C RAC中的一个数据库实例自动crash并报ORA-27157、ORA-27300等错误
		
rhel7.2上安装12C RAC数据库后,其中一个数据库实例经常会自动crash.查看alert日志发现以下错误信息: Errors in file /d12/app/oracle/diag/rdb ...
 - Confluence 6 从生产环境中恢复一个测试实例
		
请参考 Restoring a Test Instance from Production 页面中的内容获得更多完整的说明. 很多 Confluence 的管理员将会使用生产实例运行完整数据和服务的 ...
 - Java注解(3):一个真实Elasticsearch案例
		
学会了技术就要使用,否则很容易忘记,因为自然界压根就不存在什么代码.变量之类的玩意,这都是一些和生活常识格格不入的东西.只能多用多练,形成肌肉记忆才行. 在一次实际的产品开发中,由于业务需求的缘故,需 ...
 - 关于FastDFS  Java客户端源码中的一个不太明白的地方
		
下面代码是package org.csource.fastdfs下TrackerGroup.java文件中靠近结束的一段代码,我下载的这个源码的版本是1.24. /** * return connec ...
 - Java对象与类中的一个小练习
		
一直在Eclipse里做练习.是做一个练习,执行一个的那种.刚刚学习了Java的对象与类,练习中把类和执行放在同一包下的两个.java文件里面了.是可以执行的.(Get) 相关代码: public c ...
 - Java 从原字符串中截取一个新的字符串 subString()
		
Java 手册 substring public String substring(int beginIndex) 返回一个新的字符串,它是此字符串的一个子字符串.该子字符串从指定索引处的字符开始,直 ...
 - 【错误记录】windows python 路径中的一个转义错误:'rawunicodeescape' codec can't decode bytes in position 112-113: truncated \uXXXX
		
ur"D:\work\结构化\CSV\useful\内容.csv" 报错 编码错误原因,当路径中有\u这种字串时,即使是包含在r"" 中也会进行转义,然后转义出 ...
 - Java父类与子类中静态代码块 实例代码块 静态变量 实例变量 构造函数执行顺序
		
实例化子类时,父类与子类中的静态代码块.实例代码块.静态变量.实例变量.构造函数的执行顺序是怎样的? 代码执行的优先级为: firest:静态部分 second:实例化过程 详细顺序为: 1.父类静态 ...
 - java如何在静态方法中访问类的实例成员
		
类的静态方法是不能直接访问实例的成员的,它只能访问同类的静态成员.访问实例的成员的话,可以参考一下这个方法,那就是把静态方法的参数设置为类的实例,这样通过参数传递的方式就可以访问实例的成员了,例子如下 ...
 
随机推荐
- Spring应用上下文生命周期
			
Spring应用上下文生命周期整体分成四个阶段 ConfigurableApplicationContext#refresh,加载或者刷新持久化配置 ConfigurableApplicationCo ...
 - 力扣1689. 十-二进制数的最少数目-C语言实现-中等难度题
			
题目 传送门 如果一个十进制数字不含任何前导零,且每一位上的数字不是 0 就是 1 ,那么该数字就是一个 十-二进制数 .例如,101 和 1100 都是 十-二进制数,而 112 和 3001 不是 ...
 - LVS : Linux Virtual Server 负载均衡,集群,高并发,robust
			
1 LVS : Linux Virtual Server http://www.linuxvirtualserver.org/ http://www.linuxvirtualserver.org/zh ...
 - React Creating Elements All In One
			
React Creating Elements All In One https://reactjs.org/docs/react-api.html#creating-react-elements h ...
 - OLAP
			
OLAP Online Analytical Processing https://en.wikipedia.org/wiki/Online_analytical_processing 在线分析处理 ...
 - taro defaultProps
			
taro defaultProps https://nervjs.github.io/taro/docs/best-practice.html#给组件设置-defaultprops import Ta ...
 - 负利率时代,NGK DeFi是否会推动资本向加密货币迁徙?
			
2020年,全球经济危机持续,贸易战争以及天灾人祸使得全球各国的经济雪上加霜,为了挽救低迷的经济,美国.欧洲.日本各国央行竞相放水,全球正在滑入负利率时代. 负利率下,资本加速从法币向数字货币迁徙,因 ...
 - Vue3组件(九)Vue + element-Plus + json = 动态渲染的表单控件
			
一个成熟的表单 表单表单,你已经长大了,你要学会: 动态渲染 支持单列.双列.多列 支持调整布局 支持表单验证 支持调整排列(显示)顺序 依据组件值显示需要的组件 支持 item 扩展组件 可以自动创 ...
 - JS数字每三位加逗号的最简单方法
			
<script> function thousands(num){ var str = num.toString(); var reg = str.indexOf("." ...
 - synchronized语法
			
synchronized( ){ } synchronized 关键字是加锁的意思,用它来修饰方法就表示给该方法加了锁,从而达到线程同步的效果;用它来修饰代码块就表示给该代码块加了锁,从而达到线程同步 ...