版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012848709/article/details/82724162
楔子
前一段时间看了一个水平很高的代码,使用了自定义注解和标签,实现了权限的控制和
表单字段的校验
。此处简单模拟一下自定义注解和标签实现权限控制。
code
模式不涉及数据库查询校验,下面是模式的效果。
自定义标签
1:自定义标签
<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.1" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee web-jsptaglibrary_2_1.xsd">
<display-name>权限控制标签</display-name>
<tlib-version>1.0</tlib-version>
<!-- 页面使用引入如下示例 -->
<!-- <%@ taglib uri="/prev-tag" prefix="slp"%> -->
<short-name>slp</short-name>
<uri>/prev-tag</uri> <!-- 也可这样写<uri>http://azhuzi.com/jstl/fake</uri> -->
<tag>
<name>privilege</name>
<tag-class>cn.zhuzi.prev.PrivilegeTag</tag-class>
<body-content>JSP</body-content>
<description>privilege tag</description>
<attribute>
<description>user oprator action</description>
<name>oprator</name> <!-- 属性名字 -->
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
</taglib>
2:标签对应的代码
public class PrivilegeTag extends TagSupport {
// 无法直接使用注解获取spring bean
@Resource
JdbcTemplate jdbcTemplate;
private static final long serialVersionUID = 1L;
/**
* 权限操作名
*/
private String oprator;
@Override
public int doStartTag() throws JspException {
// TODO 获取servletContext(放在次处,仅仅是为了学习 没法使用注解时怎么获取 spring bean)
WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
ServletContext servletContext = webApplicationContext.getServletContext();
String sysTitle = (String) servletContext.getAttribute("title");
System.out.println(sysTitle);
// TODO 获取spring bean (放在次处,仅仅是为了学习 没法使用注解时怎么获取 spring bean)
JdbcTemplate jdbcTemplate = (JdbcTemplate) webApplicationContext.getBean("jdbcTemplate");
List<Map<String, Object>> queryForList = jdbcTemplate.queryForList(" SELECT * FROM `kindle_pub_list`");
for (Map<String, Object> map : queryForList) {
System.out.println(map);
System.out.println(map);
}
// TODO (放在次处,仅仅是为了学习 没法使用注解时怎么获取 spring bean)
KindleBookMapper kindleBookMapper = (KindleBookMapper) webApplicationContext.getBean("kindleBookMapper");
KindleBook selectByPrimaryKey = kindleBookMapper.selectByPrimaryKey(4);
System.out.println(selectByPrimaryKey);
// 从Session中获取该用户具有的权限(此处没用,仅仅是为了模式 标签获取session)
String priStr = (String) pageContext.getSession().getAttribute("sys_role_resource");
// TODO 这是模式的权限
List<String> pri = Arrays.asList("del", "bookquery");
if (pri != null && pri.contains(this.oprator)) {
// TODO 显示
return EVAL_BODY_INCLUDE;
} else {
// TODO 不显示
return SKIP_BODY;
}
}
public String getOprator() {
return oprator;
}
public void setOprator(String oprator) {
this.oprator = oprator;
}
}
3:jsp页面的使用
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<c:set var="proPath" value="${pageContext.request.contextPath}" />
<%@ taglib uri="/prev-tag" prefix="slp"%>
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<slp:privilege oprator="getbook">
<button id="getbook">查找书籍</button>
</slp:privilege>
<slp:privilege oprator="del">
<button id="del">删除书籍</button>
</slp:privilege>
<a href="${proPath}/kindle/book/getById?id=5">查找数据a标签</a>
</body>
4:简单图解上述内容
5:web.xml
有一点我还是不太理解:
为何要在WEB.XML中配置jsp-config,在模拟是,发现不配置也可以。
<!-- 权限标签 -->
<jsp-config>
<taglib>
<taglib-uri>/prev-tag</taglib-uri>
<taglib-location>/WEB-INF/jstl/preRes.tld</taglib-location>
</taglib>
</jsp-config>
自定义注解
上述
自定义标签
实现了JSP页面 控制按钮等 的显示与否
,此处 自定义标签,控制访问时是否放行
。
我是使用的SpringMVC,使用拦截器实现的
1:注解
@Documented//将此注解包含在javadoc中
//RetentionPolicy表示 什么级别保留该注解
// SOURCE 注解编译时丢弃
// CLASS 注解 在class文件中使用,VM会丢弃
// RUNTIME VM运行期间也保存,因此可以通过反射机制获取注解信息
@Retention(RetentionPolicy.RUNTIME)
//METHOD 表示方法 ;TYPE表示类、接口、或者枚举
@Target({ ElementType.METHOD, ElementType.TYPE })
public @interface Prev {
/**
* 权限名称
*
* @return
*/
public String oprator();
/**
* 权限描述
*
* @return
*/
public String decription() default "";
}
2:拦截器
public class PrivilegeInterceptorAdapter extends HandlerInterceptorAdapter {
@Resource
JdbcTemplate jdbcTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object preHandle) throws Exception {
Method currentMethod = getCurrentMethod(preHandle);
Prev pre = currentMethod.getAnnotation(Prev.class);
if (pre == null) {
return true;
} else {
String oprator = pre.oprator();
String decription = pre.decription();
System.out.println("操作权限-->" + decription);
// TODO模拟 从session获取权限
@SuppressWarnings("unchecked")
List<String> privilegeList = (List<String>) request.getSession().getAttribute("privilege");
if (privilegeList.contains(oprator)) {
return true;
} else {
if (request.getHeader("X-Requested-With") != null && request.getHeader("X-Requested-With").equalsIgnoreCase("XMLHttpRequest")) {// 是ajax请求
response.setCharacterEncoding("text/html;charset=UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter writer = response.getWriter();
StringBuffer jsonTip = new StringBuffer("{\"result\":");
jsonTip.append(false).append(",\"tip\":\"您无权操作\"}");
writer.print(jsonTip.toString());
return false;
} else {// 非ajax请求
String content = request.getSession().getServletContext().getContextPath();
// response.sendRedirect(content + "/refuse.html");//转发到页面
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("您无权操作");
return false;
}
}
}
}
private Method getCurrentMethod(Object invocation) throws Exception {
HandlerMethod method = (HandlerMethod) invocation;
//TODO 此处获取的是 controlller 类
Class<?> beanType = method.getBeanType();
System.out.println(beanType.getAnnotation(RequestMapping.class));
//TODO 此处获取的执行的方法
return method.getMethod();
}
}
3:controller方法上使用
@Controller
@RequestMapping("/kindle/book")
public class KindleBookController extends SysBaseController {
@Prev(oprator = "book:del", decription = "删除书籍")
public Object delByID(int id) {
int count = kindleBookService.delByID(id);
return new EuResult(KindleConstants.msg_success);
}
@RequestMapping("getById")
@ResponseBody
@Prev(oprator = "book:get", decription = "查找书籍")
public Object getById(int id) {
KindleBook dic = kindleBookService.getById(id);
return dic;
}
效果图