一:
对于springMVC的controller,有时候会需要记录里面接口映射的信息。比如:
@Controller public class RoleManagementController { ...... /* * 初始化角色页面 */ @RequestMapping(value = "rolesList.s", method = RequestMethod.GET) @TestAno(name = "角色列表页面", remark = "角色列表页面") public String rolesListGet(Model model) { ...... }
这时,我需要读取映射值等信息。我们可以在web.xml文件中添加一个servlet:
<servlet> <servlet-name>testInitialServlet</servlet-name> <servlet-class>com.yc.web.TestInitialServlet</servlet-class> <load-on-startup>10</load-on-startup> <init-param> <param-name>switcher</param-name> <param-value>true</param-value> </init-param> </servlet>
二:
如果有需要过滤掉的接口映射,可以首先配置一个过滤文件moduleFilter.xml:
<?xml version="1.0" encoding="UTF-8"?> <filter-modules> <item type="package" value="com.yc.test1" /> <item type="class" value="com.yc.test2.web.Test" /> <item type="url" value="/test1.s" /> <item type="url" value="/test2.s" /> </filter-modules>
在处理类TestInitialServlet
中通过如下方法处理:
private Set<String> initFilteredModuleList(ApplicationContext context) { Set<String> hsFilterUrls = new HashSet<String>(); try { Document document = new SAXReader().read(this.getClass().getClassLoader().getResourceAsStream("moduleFilter.xml")); List<Element> filteredItems = (List<Element>)document.selectNodes("//filter-modules/item"); for(Element item : filteredItems) { String type = item.attributeValue("type"); String value = item.attributeValue("value"); if("url".equals(type)) { hsFilterUrls.add(value); } else if("class".equals(type)) { Class clazz = Class.forName(value); Method[] methods = clazz.getMethods(); for(Method method : methods) { if(method.isAnnotationPresent(RequestMapping.class)) { RequestMapping mapping = method.getAnnotation(RequestMapping.class); for(String url : mapping.value()) { hsFilterUrls.add("/" + url); } } } } else if("package".equals(type)) { List<Class> classList = ReflectionUtil.getClassesByPackageName(value); for(Class clazz : classList) { Method[] methods = clazz.getMethods(); for(Method method : methods) { if(method.isAnnotationPresent(RequestMapping.class)) { RequestMapping mapping = method.getAnnotation(RequestMapping.class); for(String url : mapping.value()) { hsFilterUrls.add("/" + url); } } } } } } } catch (DocumentException e) { logger.error("parse xml file faied!!!", e); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return hsFilterUrls; }
当然还需要引入相应jar包:
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.WebApplicationContext;
上述方法就是解析moduleFilter.xml
文件得到可过滤掉的接口映射并保存。
三:
接下来,我们又可能附加一些controller没有的一些接口映射。这时候依然可把它们保存在一个xml文件中,比如initInfo.xml:
<?xml version="1.0" encoding="UTF-8"?> <init-info> <modules> <module name="测试1" url="/test1.s" remark="test1" /> <module name="测试2" url="/test2.s" remark="test2" /> </modules> </init-info>
四:
此时,我们既有了要过滤的映射,也有了要附加的映射,那我们只需要扫描所有controller的mapping,并去掉要过滤的映射、加上要附加的映射就是了。整个类文件TestInitialServlet
.java如下:
public class TestInitialServlet extends HttpServlet { @Override public void init(ServletConfig config) throws ServletException { String switcher = config.getInitParameter("switcher"); if("true".equals(switcher)) { ApplicationContext context = (ApplicationContext)config.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); Set<String> filterModuleList = initFilteredModuleList(context); initModuleList(context, filterModuleList); } } private Set<String> initFilteredModuleList(ApplicationContext context) { Set<String> hsFilterUrls = new HashSet<String>(); try { Document document = new SAXReader().read(this.getClass().getClassLoader().getResourceAsStream("moduleFilter.xml")); List<Element> filteredItems = (List<Element>)document.selectNodes("//filter-modules/item"); for(Element item : filteredItems) { String type = item.attributeValue("type"); String value = item.attributeValue("value"); if("url".equals(type)) { hsFilterUrls.add(value); } else if("class".equals(type)) { Class clazz = Class.forName(value); Method[] methods = clazz.getMethods(); for(Method method : methods) { if(method.isAnnotationPresent(RequestMapping.class)) { RequestMapping mapping = method.getAnnotation(RequestMapping.class); for(String url : mapping.value()) { hsFilterUrls.add("/" + url); } } } } else if("package".equals(type)) { List<Class> classList = ReflectionUtil.getClassesByPackageName(value); for(Class clazz : classList) { Method[] methods = clazz.getMethods(); for(Method method : methods) { if(method.isAnnotationPresent(RequestMapping.class)) { RequestMapping mapping = method.getAnnotation(RequestMapping.class); for(String url : mapping.value()) { hsFilterUrls.add("/" + url); } } } } } } } catch (DocumentException e) { logger.error("parse xml file faied!!!", e); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return hsFilterUrls; } private void initModuleList(ApplicationContext context, Set<String> filterModuleList) { logger.info("now begin initial module list"); Map<String, Object> map = context.getBeansWithAnnotation(Controller.class); Map<String, Modules> serial2DBMap = new HashMap<String, Modules>(); for(String beanName : map.keySet()) { Object bean = map.get(beanName); Method[] methods = bean.getClass().getMethods(); for(Method method : methods) { if(method.isAnnotationPresent(RequestMapping.class)) { RequestMapping mapping = method.getAnnotation(RequestMapping.class); String[] urls = mapping.value(); String name = null; String remark = null; if(method.isAnnotationPresent(TestAno.class)) { TestAno security = method.getAnnotation(TestAno.class); name = security.name(); remark = security.remark(); } for(String url : urls) { if(filterModuleList.contains("/" + url)) { logger.info("filtered url: [" + url + "]"); continue; } logger.info("initial module url: [/" + url + "], name: [" + name + "], remark: [" + remark + "]"); Modules module = new Modules(); module.setModuleName(name == null ? "/" + url : name); module.setModuleUrl("/" + url); module.setRemark(remark); module.setStatus(CommonCondition.STATUS_TYPE_NORMAL); serial2DBMap.put("/" + url, module); } } } } try { Document document = new SAXReader().read(this.getClass().getClassLoader().getResourceAsStream("initInfo.xml")); List<Element> moduleNodes = (List<Element>)document.selectNodes("//init-info/modules/module"); for(Element moduleNode : moduleNodes) { String moduleName = moduleNode.attributeValue("name"); String moduleUrl = moduleNode.attributeValue("url"); if(filterModuleList.contains(moduleUrl)) { logger.info("filtered url: [" + moduleUrl + "]"); continue; } String remark = moduleNode.attributeValue("remark"); Modules module = new Modules(); module.setModuleName(moduleName); module.setModuleUrl(moduleUrl); module.setRemark(remark); module.setStatus(CommonCondition.STATUS_TYPE_NORMAL); serial2DBMap.put(moduleUrl, module); } } catch (DocumentException e) { logger.error("parse xml file faied!!!", e); } dao.serialModuleList2DB(serial2DBMap); logger.info("initial module list finish"); } }
五:
上述代码中包含一个Modules类,该类是一个持久化对象类,可根据实际需求进行替换。
另外,我们自建了一个annotation---“TestAno”,对它的定义如下:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) public @interface TestAno { public String name(); public String remark(); }
根据上述步骤,我们就实现了从配置文件读要过滤的映射和要添加的映射,并扫描controller中的映射,影响保存。后面就可以自己写方法来进行数据库存储,或者别的操作了!