赞
踩
就在上周突然收到一个需求,左侧导航栏要无限级可配置。。。一般左侧导航栏都是三级最多五级很少有需要无限级的,有人可能会问无限级是什么?(再次声明我不卖保健品。。。)无限级导航就是一个无限下级的导航树结构。在这里给大家分享一下我做的demo。温故而知,也方便各位大虾遇到此坑能稳稳跳过。废话不说开始吧。
我们先看一下最终效果图: (正如本人脸一样简洁)
第一步搭建环境:springMVC
Web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1" metadata-complete="true"> <display-name>Archetype Created Web Application</display-name> <!--配置spring上下文--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:config/contextConfigLocation.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- Spring字符集过滤器 --> <filter> <filter-name>SpringEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>SpringEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 添加日志监听器 --> <context-param> <param-name>logbackConfigLocation</param-name> <param-value>classpath:logback.xml</param-value> </context-param> <listener> <listener-class>ch.qos.logback.ext.spring.web.LogbackConfigListener</listener-class> </listener> <!--配置前端控制器--> <servlet> <servlet-name>springMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:config/spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springMVC</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!--web.xml默认配置--> <welcome-file-list> <welcome-file>/WEB-INF/jsp/login.jsp</welcome-file> </welcome-file-list> </web-app>
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.cms</groupId> <artifactId>MyCms</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>MyCms Maven Webapp</name> <url>http://maven.apache.org</url> <properties> <spring.version>4.0.5.RELEASE</spring.version> <mybatis.version>3.2.1</mybatis.version> <slf4j.version>1.6.6</slf4j.version> <log4j.version>1.2.12</log4j.version> <mysql.version>5.1.35</mysql.version> <cxf.version>3.1.6</cxf.version> </properties> <dependencies> <!-- 添加Spring依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <!-- spring-redis实现 --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.6.2.RELEASE</version> </dependency> <!-- redis客户端jar --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.8.0</version> </dependency> <!--web service 依赖--> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>${cxf.version}</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http</artifactId> <version>${cxf.version}</version> </dependency> <!-- Jetty is needed if you're are not using the CXFServlet --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http-jetty</artifactId> <version>${cxf.version}</version> </dependency> <!-- Ehcache实现,用于参考 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-ehcache</artifactId> <version>1.0.0</version> </dependency> <!--spring单元测试依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4.7</version> </dependency> <!-- spring webmvc相关jar --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <!-- mysql驱动包 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <!-- alibaba data source 相关jar包--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>0.2.23</version> </dependency> <!-- alibaba fastjson 格式化对 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.1.41</version> </dependency> <!-- logback start --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.2</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.1.2</version> </dependency> <dependency> <groupId>org.logback-extensions</groupId> <artifactId>logback-ext-spring</artifactId> <version>0.1.1</version> </dependency> <!--mybatis依赖 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${mybatis.version}</version> </dependency> <!-- mybatis/spring包 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.2.0</version> </dependency> <!-- 添加servlet3.0核心包 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.2-b01</version> </dependency> <!-- jstl --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!--单元测试依赖 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.wicketstuff</groupId> <artifactId>wicketstuff-logback</artifactId> <version>7.0.0-M5</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.14</version> </dependency> </dependencies> <!-- https://mvnrepository.com/artifact/org.wicketstuff/wicketstuff-logback --> <build> <defaultGoal>compile</defaultGoal> <finalName>MyCms</finalName> <plugins> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.2</version> <configuration> <verbose>true</verbose> <overwrite>true</overwrite> </configuration> </plugin> </plugins> </build> </project>
spring-mvc.xml
在这里有个自定义的拦截器,是为了验证用户是否登录的。。。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd"> <mvc:annotation-driven> <mvc:message-converters register-defaults="true"> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes" value = "text/plain;charset=UTF-8" /> </bean> </mvc:message-converters> </mvc:annotation-driven> <!-- 扫描controller(controller层注入) --> <context:component-scan base-package="com.cms.controller" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <!-- <mvc:annotation-driven />--> <!--<!– 内容协商管理器 –>--> <!--<!–1、首先检查路径扩展名(如my.pdf);2、其次检查Parameter(如my?format=pdf);3、检查Accept Header–>--> <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean"> <!-- 扩展名至mimeType的映射,即 /user.json => application/json --> <property name="favorPathExtension" value="true"/> <!-- 用于开启 /userinfo/123?format=json 的支持 --> <property name="favorParameter" value="true"/> <property name="parameterName" value="format"/> <!-- 是否忽略Accept Header --> <property name="ignoreAcceptHeader" value="false"/> <property name="mediaTypes"> <!--扩展名到MIME的映射;favorPathExtension, favorParameter是true时起作用 --> <value> json=application/json xml=application/xml html=text/html </value> </property> <!-- 默认的content type --> <property name="defaultContentType" value="text/html"/> </bean> <!-- 静态资源映射 --> <mvc:resources mapping="/css/**" location="/static/css/"/> <mvc:resources mapping="/img/**" location="/static/img/"/> <mvc:resources mapping="/js/**" location="/static/js/"/> <mvc:resources mapping="/layer/**" location="/static/layer/"/> <mvc:resources mapping="/font/**" location="/static/layer/font/"/> <!-- 当在web.xml 中 DispatcherServlet使用 <url-pattern>/</url-pattern> 映射时,能映射静态资源 <mvc:default-servlet-handler />--> <!-- 对模型视图添加前后缀 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/jsp/" p:suffix=".jsp"/> <!--自定义拦截器 验证用户是否登录--> <mvc:interceptors> <!-- 多个拦截器,顺序执行 --> <mvc:interceptor> <mvc:mapping path="/**"/> <mvc:exclude-mapping path="/**/*.css"/> <mvc:exclude-mapping path="/**/*.js"/> <mvc:exclude-mapping path="/**/*.png"/> <mvc:exclude-mapping path="/**/*.gif"/> <mvc:exclude-mapping path="/**/*.jpg"/> <mvc:exclude-mapping path="/**/*.jpeg"/> <bean class="com.cms.util.logInterception"></bean> </mvc:interceptor> </mvc:interceptors> </beans>
mybatis-config.xml
这里咱们用的阿里的数据连接池Druid
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"> <!-- 3.配置数据源 ,使用的alibba的数据库--> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <!-- 基本属性 url、user、password --> <property name="driverClassName" value="${jdbc_driverClassName}"/> <property name="url" value="${jdbc_url}"/> <property name="username" value="${jdbc_username}"/> <property name="password" value="${jdbc_password}"/> <!-- 配置初始化大小、最小、最大 --> <property name="initialSize" value="10"/> <property name="minIdle" value="10"/> <property name="maxActive" value="50"/> <!-- 配置获取连接等待超时的时间 --> <property name="maxWait" value="60000"/> <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="300000" /> <property name="validationQuery" value="SELECT 'x'" /> <property name="testWhileIdle" value="true" /> <property name="testOnBorrow" value="false" /> <property name="testOnReturn" value="false" /> <!-- 打开PSCache,并且指定每个连接上PSCache的大小 如果用Oracle,则把poolPreparedStatements配置为true,mysql可以配置为false。--> <property name="poolPreparedStatements" value="false" /> <property name="maxPoolPreparedStatementPerConnectionSize" value="20" /> <!-- 配置监控统计拦截的filters --> <property name="filters" value="wall,stat" /> </bean> <!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <!-- 自动扫描mapping.xml文件 --> <property name="mapperLocations" value="classpath:com/cms/mapper/*.xml"></property> </bean> <!-- DAO接口所在包名,Spring会自动查找其下的类 ,自动扫描了所有的XxxxMapper.xml对应的mapper接口文件,只要Mapper接口类和Mapper映射文件对应起来就可以了--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.cms.dao" /> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property> </bean> <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx --> <!-- 配置事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!--======= 事务配置 End =================== --> <!-- 配置基于注解的声明式事务 --> <!-- enables scanning for @Transactional annotations --> <tx:annotation-driven transaction-manager="transactionManager" /> </beans>
contextConfigLocation.xml
jdbc_driverClassName =com.mysql.jdbc.Driver jdbc_url=jdbc:mysql://192.168.8.96:3306/qg?useUnicode=true&characterEncoding=utf8 jdbc_username=root jdbc_password=qiaogang
这里使用redis作为mybatis的二级缓存使用
<?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:context="http://www.springframework.org/schema/context" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:soap="http://cxf.apache.org/bindings/soap" xmlns:util="http://www.springframework.org/schema/util" xmlns:cxf="http://cxf.apache.org/core" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd "> <!-- 1.配置jdbc文件 --> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:jdbc.properties</value> <value>classpath:redis.properties</value> </list> </property> </bean> <!-- redis数据源 --> <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxIdle" value="${redis.maxIdle}" /> <property name="maxTotal" value="${redis.maxActive}" /> <property name="maxWaitMillis" value="${redis.maxWait}" /> <property name="testOnBorrow" value="${redis.testOnBorrow}" /> </bean> <!-- Spring-redis连接池管理工厂 --> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}" p:pool-config-ref="poolConfig"/> <!-- 使用中间类解决RedisCache.jedisConnectionFactory的静态注入,从而使MyBatis实现第三方缓存 --> <bean id="redisCacheTransfer" class="com.cms.util.RedisCacheTransfer"> <property name="jedisConnectionFactory" ref="jedisConnectionFactory"/> </bean> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="jedisConnectionFactory" /> <property name="keySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" /> </property> <property name="valueSerializer"> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" /> </property> <property name="hashKeySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/> </property> <property name="hashValueSerializer"> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> </property> </bean> <!-- 2.扫描的包路径,这里不扫描被@Controller注解的类 --><!--使用<context:component-scan/> 可以不在配置<context:annotation-config/> --> <context:component-scan base-package="com.cms.*.*"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <import resource="mybatis-config.xml" /> <import resource="classpath:META-INF/cxf/cxf.xml"></import> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> <jaxws:endpoint id="TestWebService" implementor="com.cms.webService.Impl.TestWebServiceImpl" address="/webSerciceTest_endpoint" /> </beans>mysql数据源
jdbc_driverClassName =com.mysql.jdbc.Driver jdbc_url=jdbc:mysql://192.168.8.96:3306/qg?useUnicode=true&characterEncoding=utf8 jdbc_username=root jdbc_password=qiaogang
redis数据源
# Redis settings redis.host=192.168.8.96 redis.port=6379 redis.pass= redis.maxIdle=300 redis.maxActive=600 redis.maxWait=10000 redis.testOnBorrow=true
generatorConfig.xml(mybatis自动生成器)
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" > <generatorConfiguration> <!-- 出现错误:Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver 解决办法:将本地的MAVEN仓库中的mysql驱动引入进来 --> <classPathEntry location="D:\\mysql.jar"/> <context id="mysqlgenerator" targetRuntime="MyBatis3"> <!--不生成注释--> <commentGenerator> <property name="suppressAllComments" value="true" /> </commentGenerator> <!-- 配置数据库连接 --> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://192.168.16.48:3306/qg" userId="root" password="qiaogang" /> <!-- 指定javaBean生成的位置 --> <javaModelGenerator targetPackage="com.wgs.domain" targetProject="src/main/java" > <!-- 在targetPackage的基础上,根据数据库的schema再生成一层package,最终生成的类放在这个package下,默认为false --> <property name="enableSubPackages" value="true" /> <!-- 设置是否在getter方法中,对String类型字段调用trim()方法 --> <property name="trimStrings" value="true" /> </javaModelGenerator> <!--指定sql映射文件生成的位置 --> <sqlMapGenerator targetPackage="com.cms.mapper" targetProject="src/main/resources" > <property name="enableSubPackages" value="true" /> </sqlMapGenerator> <!-- 指定dao接口生成的位置,mapper接口 --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.cms.dao" targetProject="src/main/java" > <property name="enableSubPackages" value="true" /> </javaClientGenerator> <!-- table表生成对应的DoaminObject --> <table tableName="menu" domainObjectName="menu"></table> </context> </generatorConfiguration>
环境搭建完成,下一步让我看看数据表
user用户表:
菜单表 menu:
我们使用sql获取树形结构,再从前端使用递归渲染菜单。我们来看一下sql的写法(menuMapper.xml)
<?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.cms.dao.menuMapper" > <cache type="com.cms.util.RedisCache"/> <resultMap id="BaseResultMap" type="com.cms.demo.menu" > <id column="mid" property="mid" jdbcType="INTEGER" /> <result column="menuname" property="menuname" jdbcType="VARCHAR" /> <result column="mcode" property="mcode" jdbcType="INTEGER" /> <result column="supercode" property="supercode" jdbcType="INTEGER" /> <result column="u_id" property="uId" jdbcType="INTEGER" /> <result column="is_last" property="isLast" jdbcType="INTEGER" /> </resultMap> <resultMap id="BaseTreeResultMap" type="com.cms.demo.menu" > <id column="mid" property="mid" jdbcType="INTEGER" /> <result column="menuname" property="menuname" jdbcType="VARCHAR" /> <result column="mcode" property="mcode" jdbcType="VARCHAR" /> <result column="url" property="url" jdbcType="VARCHAR" /> <collection column="mid" property="next" javaType="java.util.ArrayList" ofType="com.cms.demo.menu" select="getNextNodeTree"/> </resultMap> <resultMap id="NextTreeResultMap" type="com.cms.demo.menu" > <id column="mid" property="mid" jdbcType="INTEGER" /> <result column="menuname" property="menuname" jdbcType="VARCHAR" /> <result column="mcode" property="mcode" jdbcType="VARCHAR" /> <result column="url" property="url" jdbcType="VARCHAR" /> <collection column="mid" property="next" javaType="java.util.ArrayList" ofType="com.cms.demo.menu" select="getNextNodeTree"/> </resultMap> <sql id="Base_Column_List"> mid,menuname,url,mcode </sql> <select id="getNextNodeTree" flushCache="true" resultMap="NextTreeResultMap"> SELECT <include refid="Base_Column_List"/> FROM menu WHERE supercode = #{id} </select> <select id="getNodeTree" flushCache="true" resultMap="BaseTreeResultMap"> SELECT <include refid="Base_Column_List"/> FROM menu WHERE supercode = 0 </select> </mapper>
这里我们会用到mybatis的一个标签Collection。 Collection主要处理“一对多”类型映射关系,例如,查询部门中有多个员工,就需要使用的到集合:List<employee> emp,这样,就会使用collection进行映射关联查询。在这里的查询其实相当于一个递归操作,先确定superCode为0的父级然后查询其下面的子级然后再查询子级的子级递归循环直到没有子集。
/** *用户登录 * @param userCode 用户名 * @param userPass 密码 * @return 登录成功 */ @RequestMapping(value = "/userLogin",method = RequestMethod.POST,produces = "text/html; charset=utf-8") @ResponseBody public String userLogin(HttpSession session,@RequestParam("usercode") String userCode, @RequestParam("userpassword") String userPass, HttpServletRequest request, HttpServletResponse res) { if(userCode!=null && userPass!=null) { List<CmsUser> list=testservice.userlogin(userCode,userPass); if(list!=null && list.size()>0) { CmsUser cms = list.get(0); session.setAttribute("userid",cms);//写入用户信息 List<Object> lists=testservice.queryTree(); Map<String,Object> map1 = new HashMap<String, Object>(); Map<String,Object> map = new HashMap<String, Object>(); map.put("userid",cms.getUid()); map.put("usercode",cms.getUsercode()); map1.put("next",lists); map.put("extend",map1); String navjs= JSON.toJSON(map).toString();//得到菜单列表的json session.setAttribute("nav",navjs); System.out.println(navjs); ValueOperations<String, Object> value = redisTemplate.opsForValue(); value.set("lp", "hello word"); System.out.println("读取内存====================="+value.get("lp")); return "success"; } else { throw new RuntimeException("用户名密码错误!!"); } }else { throw new RuntimeException("用户名密码为空!"); } }
我呢打印下得到的json串:
{
"extend": {
"next": [{
"mcode": 1000,
"menuname": "基础设置",
"mid": 1,
"next": [{
"mcode": 10001,
"menuname": "用户管理",
"mid": 3,
"next": [],
"url": "http://localhost:8080/Cms/go/test"
}, {
"mcode": 10002,
"menuname": "角色管理",
"mid": 4,
"next": [],
"url": "http://localhost:8080/Cms/go/wb"
}, {
"mcode": 10003,
"menuname": "权限管理",
"mid": 5,
"next": [],
"url": "http://localhost:8080/Cms/"
}, {
"mcode": 10004,
"menuname": "数据统计",
"mid": 6,
"next": [],
"url": "http://localhost:8080/Cms/"
}, {
"mcode": 10004,
"menuname": "字典维护",
"mid": 7,
"next": [],
"url": "http://localhost:8080/Cms/"
}],
"url": "http://localhost:8080/Cms/"
}, {
"mcode": 1001,
"menuname": "物资管理",
"mid": 2,
"next": [{
"mcode": 100101,
"menuname": "物资维护",
"mid": 8,
"next": [{
"mcode": 10010101,
"menuname": "物资分配",
"mid": 9,
"next": [],
"url": "http://localhost:8080/Cms/"
}],
"url": "http://localhost:8080/Cms/"
}],
"url": "http://localhost:8080/Cms/"
}]
},
"userid": 1
}
大家可以看到我们得到json结构,其页面效果为:
我们看一下前端的渲染写法这里我们用的layui:
function gets() { debugger; var isFirstMenu; var data=${nav};//得到数据集 var showlist = $("<ul class=\"layui-nav layui-nav-tree\" lay-filter=\"hbkNavbar\"></ul>"); isFirstMenu=data.extend.next.length; showall(data.extend.next, showlist); $("#view").append(showlist); function showall(menu_list, parent) { for (var menu in menu_list) { if (menu_list[menu].next.length > 0) { console.log(menu_list[menu].next.mcode) if(menu_list[menu].next.mcode!='0') { var lis = $("<dd></dd>"); } var lim = $("<li class=\"layui-nav-item layui-nav-itemed\"></li>") var as = $("<a href=\"javascript\:\;\">"+menu_list[menu].menuname+"</a>"); var dls = $("<dl class=\"layui-nav-child\"></dl>"); lis.appendTo(parent); lim.appendTo(lis); as.appendTo(lim); dls.appendTo(lim); showall(menu_list[menu].next, dls); }else { // console.log(menu_list[menu].url); var dd = $("<dd> <a href=\"javascript:;\" data-id='"+menu_list[menu].mid+"' data-url='"+menu_list[menu].url+"' data-title='"+menu_list[menu].menuname+"'> "+menu_list[menu].menuname+"</a></dd>"); dd.appendTo(parent); } } } }
大家可以仔细阅读一下,前端也是使用递归的方式去渲染的,
我们还是先得到最高节点
然后再递归渲染子节点
大功告成,喜欢的小伙伴可以关注一下咱们的公众号,关注公众号回复“牛牛浪起来“会得到高清电子书
需要源码的同学可以加小编VX"qiaoshiershao"
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。