package com.nis.web.controller.configuration; import com.nis.domain.Page; import com.nis.domain.basics.PolicyGroupInfo; import com.nis.domain.configuration.BaseCfg; import com.nis.domain.configuration.CfgIndexInfo; import com.nis.domain.configuration.ObjGroupCfg; import com.nis.exceptions.CallExternalProceduresException; import com.nis.exceptions.MaatConvertException; import com.nis.util.*; import com.nis.web.controller.BaseController; import com.nis.web.security.UserUtils; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.*; @Controller @RequestMapping("${adminPath}/objgroup") public class ObjectGroupController extends BaseController { @RequestMapping(value = { "/list" }) public String list(Model model, @ModelAttribute("cfg") CfgIndexInfo cfg, HttpServletRequest request, HttpServletResponse response,String tip){ Page searchPage=new Page(request,response,"a"); Page page = objectGroupService.getPolicyListList(searchPage, cfg); model.addAttribute("page", page); if(StringUtils.isNotBlank(tip)){ addMessage("error",model,tip); } initPageCondition(model,cfg); return "/cfg/objgroup/list"; } @RequestMapping(value = { "/form" }) @RequiresPermissions(value = { "objgroup:config" }) public String form(Model model, String ids, CfgIndexInfo entity) { List ipGroups=new ArrayList<>(); List urlGroups=new ArrayList<>(); List subscribeIdGroups=new ArrayList<>(); List domainGroups=new ArrayList<>(); //查询所有可选择(没有被其他配置引用,并且组下有域配置的组,ud_flag=1) ipGroups=policyGroupInfoService.findPolicyGroupInfosByTypeforUD(Constants.IP_OBJ_GROUP_TYPE,1); urlGroups=policyGroupInfoService.findPolicyGroupInfosByTypeforUD(Constants.URL_OBJ_GROUP_TYPE,1); subscribeIdGroups=policyGroupInfoService.findPolicyGroupInfosByTypeforUD(Constants.SUBID_OBJ_GROUP_TYPE,1); domainGroups=policyGroupInfoService.findPolicyGroupInfosByTypeforUD(Constants.DOMAIN_OBJ_GROUP_TYPE,1); if (StringUtils.isNotBlank(ids)) { entity = objectGroupService.getObjectGroupCfg(Long.parseLong(ids), null); initUpdateFormCondition(model, entity); //查询配置引用到的分组,加到对应的组下(维持选中选项) if(MapUtils.isNotEmpty(entity.getUserRegion())){ for(Map.Entry e:entity.getUserRegion().entrySet()){ if(e.getKey().equals("ipGroup")&&StringUtils.isNotBlank(e.getValue().toString())){ List _ipGrpups=policyGroupInfoService.findPolicyByServiceGroupInfoList(e.getValue().toString()); if(CollectionUtils.isNotEmpty(_ipGrpups)){ ipGroups.addAll(_ipGrpups); } }else if(e.getKey().equals("urlGroup")&&StringUtils.isNotBlank(e.getValue().toString())){ List _urlGrpups=policyGroupInfoService.findPolicyByServiceGroupInfoList(e.getValue().toString()); if(CollectionUtils.isNotEmpty(_urlGrpups)){ urlGroups.addAll(_urlGrpups); } }else if(e.getKey().equals("subscribeIdGroup")&&StringUtils.isNotBlank(e.getValue().toString())){ List _subscribeIdGroups=policyGroupInfoService.findPolicyByServiceGroupInfoList(e.getValue().toString()); if(CollectionUtils.isNotEmpty(_subscribeIdGroups)){ subscribeIdGroups.addAll(_subscribeIdGroups); } }else if(e.getKey().equals("domainGroup")&&StringUtils.isNotBlank(e.getValue().toString())){ List _domainGroups=policyGroupInfoService.findPolicyByServiceGroupInfoList(e.getValue().toString()); if(CollectionUtils.isNotEmpty(_domainGroups)){ domainGroups.addAll(_domainGroups); } } } } } else { initFormCondition(model, entity); } model.addAttribute("ipGroups", ipGroups); model.addAttribute("urlGroups", urlGroups); model.addAttribute("subscribeIdGroups", subscribeIdGroups); model.addAttribute("domainGroups", domainGroups); model.addAttribute("_cfg", entity); return "/cfg/objgroup/form"; } @RequestMapping(value = {"saveOrUpdate"}) @RequiresPermissions(value={"objgroup:config"}) public String saveOrUpdate(Model model, HttpServletRequest request, HttpServletResponse response, @ModelAttribute("cfg")CfgIndexInfo cfg, RedirectAttributes redirectAttributes){ try{ String ipGroup=formatMultSelect(request.getParameterValues("ipGroup")), subscribeIdGroup=formatMultSelect(request.getParameterValues("subscribeIdGroup")), domainGroup=formatMultSelect(request.getParameterValues("domainGroup")), urlGroup=formatMultSelect(request.getParameterValues("urlGroup")); Map map = new HashMap(); if(StringUtils.isNotBlank(ipGroup)){ map.put("ipGroup", ipGroup.toString()); } if(StringUtils.isNotBlank(subscribeIdGroup)){ map.put("subscribeIdGroup", subscribeIdGroup.toString()); } if(StringUtils.isNotBlank(domainGroup)){ map.put("domainGroup", domainGroup.toString()); } if(StringUtils.isNotBlank(urlGroup)){ map.put("urlGroup", urlGroup.toString()); } cfg.setUserRegion(map); objectGroupService.saveOrUpdate(cfg); //配置仅保存 if(StringUtil.isEmpty(cfg.getIsValid()) || cfg.getIsValid()!=1) { addMessage(redirectAttributes, "success", "save_success"); }else { //配置直接生效 addMessage(redirectAttributes, "success", "audit_success"); } } catch (MaatConvertException e) { logger.error("对象组配置下发失败:",e); addMessage(redirectAttributes, "error", "request_service_failed"); LogUtils.saveLog(request, null, e, null); } catch (CallExternalProceduresException e) { logger.error("调用外部程序出错:",e); addMessage(redirectAttributes, "error", "call_external_procedures_failed"); LogUtils.saveLog(request, null, e, null); } catch (Exception e) { logger.error("对象组配置保存失败:",e); addMessage(redirectAttributes, "error", "save_failed"); LogUtils.saveLog(request, null, e, null); } return "redirect:" + adminPath +"/objgroup/list?functionId="+cfg.getFunctionId(); } @RequestMapping(value = {"updateValid"}) @RequiresPermissions(value={"objgroup:config"}) public String delete(Integer isAudit,Integer isValid,String ids,Integer functionId, RedirectAttributes redirectAttributes, HttpServletRequest request, HttpServletResponse response, @ModelAttribute("cfg")CfgIndexInfo cfg){ try { if (!StringUtil.isEmpty(ids)) { objectGroupService.updatePolicyValid(isValid,ids,functionId); }else { // 批量删除 Page searchPage = new Page(request, response, "a"); deleteAll(searchPage, functionId, cfg); } addMessage(redirectAttributes, "success", "delete_success"); } catch (Exception e) { logger.error("配置删除失败:", e); if (e instanceof MaatConvertException) { addMessage(redirectAttributes, "error", "request_service_failed"); LogUtils.saveLog(request, null, e, null); } else { addMessage(redirectAttributes, "error", "delete_failed"); LogUtils.saveLog(request, null, e, null); } } return "redirect:" + adminPath +"/objgroup/list?functionId="+functionId; } /** * 界面批量删除当前检索条件下的配置 * @param page * @param functionId * @param entity * @throws Exception */ public void deleteAll(Page page,Integer functionId, Object entity)throws Exception { long start=System.currentTimeMillis(); page.setOrderBy(""); page.setPageSize(Constants.MAAT_JSON_SEND_SIZE); page.setPageNo(1); page.setLastPage(false); CfgIndexInfo searchCfg = new CfgIndexInfo(); // 传递检索条件 if(entity != null && (entity instanceof CfgIndexInfo)) { BeanUtils.copyProperties(entity, searchCfg); searchCfg.setFunctionId(functionId); } BaseCfg batchCfg = new BaseCfg(); batchCfg.setTableName(CfgIndexInfo.getTablename()); batchCfg.setIsValid(-1); batchCfg.setIsAudit(0); batchCfg.setEditTime(new Date()); batchCfg.setEditorId(UserUtils.getUser().getId()); //cfg_index_info表中存有servicdId boolean hasData = true; while(hasData){ page.setPageNo(1); page.setLastPage(false); List list = getDataList(page,searchCfg); //获取主配置表数据 if(CollectionUtils.isNotEmpty(list)){ StringBuffer serviceGroupIds=new StringBuffer(); List baseCfgList=new ArrayList<>(); for (CfgIndexInfo cfg : list) { if(cfg.getUserRegion()!=null){ for (Object val:cfg.getUserRegion().values()) { if(StringUtils.isNotBlank(val.toString())){ if(val.toString().startsWith(",")){ serviceGroupIds.append(val.toString().substring(1)); }else{ serviceGroupIds.append(val.toString()); } } } } BaseCfg baseCfg=new BaseCfg(); BeanUtils.copyProperties(cfg, baseCfg); baseCfgList.add(baseCfg); } if(StringUtils.isNotBlank(serviceGroupIds)&&serviceGroupIds.lastIndexOf(",")==(serviceGroupIds.toString().length()-1)){ serviceGroupIds.deleteCharAt(serviceGroupIds.toString().length()-1); } hasData = objectGroupService.batchDeleteMaatData(page, batchCfg, baseCfgList, hasData,serviceGroupIds.toString()); }else{ hasData = false; } } long end=System.currentTimeMillis(); logger.warn("配置批量删除耗时:"+(end-start)); } public List getDataList(Page searchPage ,CfgIndexInfo searchCfg ){ BaseCfg baseCfg=new BaseCfg<>(); if(!StringUtil.isEmpty(searchCfg)) { BeanUtils.copyProperties(searchCfg, baseCfg); } Page pageResult=new Page(); pageResult=objectGroupService.getPolicyListList(searchPage,searchCfg); return pageResult.getList(); } @RequestMapping(value = {"audit"}) @RequiresPermissions(value={"objgroup:confirm"}) public String audit(Model model,@ModelAttribute("cfg") CfgIndexInfo cfg, Integer isValid, Integer isAudit, String ids, Integer functionId, RedirectAttributes redirectAttributes, HttpServletResponse response, HttpServletRequest request) { Properties props=this.getMsgProp(); if(!StringUtil.isEmpty(ids)){ CfgIndexInfo entity = new CfgIndexInfo(); String[] idArray = ids.split(","); StringBuffer tip=new StringBuffer(); for(String id :idArray){ entity = objectGroupService.getObjectGroupCfg(Long.parseLong(id),null); entity.setIsAudit(isAudit); entity.setIsValid(isValid); entity.setAuditorId(UserUtils.getUser().getId()); entity.setAuditTime(new Date()); entity.setFunctionId(functionId); try { if(StringUtils.isBlank(entity.getCommonGroupIds())){ tip.append(String.format(props.getProperty("no_common_group","The configuration ID of %s does not have an group;"),id)); tip.append("
"); }else{ objectGroupService.auditPolicy(entity,isAudit,Constants.INSERT_ACTION); } if(tip.toString().length()>0){ addMessage(redirectAttributes,"error", tip.toString()); }else{ addMessage(redirectAttributes,"success", "audit_success"); } } catch ( Exception e) { logger.error("策略对象组下发失败:"+e); if(e instanceof MaatConvertException) { addMessage(redirectAttributes,"error","request_service_failed"); LogUtils.saveLog(request, null, e, null); }else { addMessage(redirectAttributes,"error","audit_failed"); LogUtils.saveLog(request, null, e, null); } } } }else { Page searchPage=new Page(request,response,"r"); Page auditPage=new Page(request,response,"r"); String tip=null; try { BeanUtils.copyProperties(searchPage, auditPage); tip= auditAll(auditPage,isValid , cfg,props); if(tip.toString().length()>0){ addMessage(redirectAttributes,"error", tip.toString()); }else{ addMessage(redirectAttributes,"success", "audit_success"); } } catch (Exception e) { logger.error("策略对象组下发失败:",e); if(e instanceof MaatConvertException) { addMessage(redirectAttributes,"error", "request_service_failed"); LogUtils.saveLog(request, null, e, null); }else { addMessage(redirectAttributes,"error", "audit_failed"); LogUtils.saveLog(request, null, e, null); } } //无法保存状态 return list(model, cfg, request, response,tip); } return "redirect:" + adminPath +"/objgroup/list?functionId="+functionId; } private String formatMultSelect(Object requestParameter){ if(StringUtil.isEmpty(requestParameter)){ return null; }else if(requestParameter.getClass().isArray()){ String[] array=(String[])requestParameter; StringBuffer buf=new StringBuffer(","); for(String param:array){ buf.append(param).append(","); } return buf.toString().length()==1?null:buf.toString(); }else{ return ","+requestParameter.toString()+","; } } @RequestMapping(value = { "/ajaxGetNames" }) @ResponseBody public Map> ajaxGetNames(Model model, @RequestParam(required=true,value="groupIds")String group) { String _group=group.replaceAll("\\|",","); Map> datas=new HashMap<>(); datas.put("ipGroup",new HashMap()); datas.put("urlGroup",new HashMap()); datas.put("subscribeIdGroup",new HashMap()); datas.put("domainGroup",new HashMap()); if(StringUtils.isNotBlank(group)){ List infos=policyGroupInfoService.findPolicyByServiceGroupInfoList(_group); for(PolicyGroupInfo info:infos){ for(String g:group.split("\\|")){ if(objectGroupService.indexOfContains(g,",",info.getServiceGroupId().toString())){ Map map=null; if(info.getGroupType().equals(Constants.IP_OBJ_GROUP_TYPE)){ map=datas.get("ipGroup"); }else if(info.getGroupType().equals(Constants.URL_OBJ_GROUP_TYPE)){ map=datas.get("urlGroup"); }else if(info.getGroupType().equals(Constants.SUBID_OBJ_GROUP_TYPE)){ map=datas.get("subscribeIdGroup"); }else if(info.getGroupType().equals(Constants.DOMAIN_OBJ_GROUP_TYPE)){ map=datas.get("domainGroup"); } map.put(g,map.containsKey(g)?map.get(g)+info.getGroupName()+",":info.getGroupName()+","); } } } } //删除最后的逗号 for(Map m:datas.values()){ for(Map.Entry e:m.entrySet()){ if(e.getValue().endsWith(",")){ m.put(e.getKey(),e.getValue().substring(0,e.getValue().length()-1)); } } } return datas; } //http配置导出 @RequestMapping(value = "exportObjGroup") public void exportdomain(Model model, HttpServletRequest request, HttpServletResponse response, @ModelAttribute("cfg") ObjGroupCfg entity, String ids, RedirectAttributes redirectAttributes){ try { //export data info List titleList=new ArrayList(); Map> classMap=new HashMap>(); Map dataMap=new HashMap(); Map noExportMap = new HashMap(); List lists = new ArrayList(); Properties msgProp = getMsgProp(); // 导出选中记录 if (!StringUtil.isEmpty(ids)) { lists = objectGroupService.getObjGroupList(ids,msgProp,entity.getFunctionId()); } else { Page pageInfo=new Page(request, response,"a"); pageInfo.setPageNo(1); pageInfo.setPageSize(Constants.MAX_EXPORT_SIZE); Page page = objectGroupService.getObjGroup(pageInfo, entity,msgProp); lists = page.getList(); } for(ObjGroupCfg c:lists){ if(StringUtils.isNotBlank(c.getIpGroup())&&c.getIpGroup().startsWith(",")){ c.setIpGroup(c.getIpGroup().substring(1)); } if(StringUtils.isNotBlank(c.getUrlGroup())&&c.getUrlGroup().startsWith(",")){ c.setUrlGroup(c.getUrlGroup().substring(1)); } if(StringUtils.isNotBlank(c.getSubscribeIdGroup())&&c.getSubscribeIdGroup().startsWith(",")){ c.setSubscribeIdGroup(c.getSubscribeIdGroup().substring(1)); } if(StringUtils.isNotBlank(c.getDomainGroup())&&c.getDomainGroup().startsWith(",")){ c.setDomainGroup(c.getDomainGroup().substring(1)); } } titleList.add(entity.getMenuNameCode()); classMap.put(entity.getMenuNameCode(), ObjGroupCfg.class); String cfgIndexInfoNoExport=",policy_name,group_name,userregion1,userregion2,userregion3,userregion4,userregion5,"; // 时间过滤 if (entity.getSearch_create_time_start() == null) { cfgIndexInfoNoExport = ",config_time" + cfgIndexInfoNoExport; } if (entity.getSearch_edit_time_start() == null) { cfgIndexInfoNoExport = ",edit_time" + cfgIndexInfoNoExport; } if (entity.getSearch_audit_time_start() == null) { cfgIndexInfoNoExport = ",audit_time" + cfgIndexInfoNoExport; } if (!StringUtil.isEmpty(entity.gethColumns())) { cfgIndexInfoNoExport = "," + entity.gethColumns() + "," + cfgIndexInfoNoExport; } noExportMap.put(entity.getMenuNameCode(),cfgIndexInfoNoExport); dataMap.put(entity.getMenuNameCode(), lists); String timeRange = initTimeMap(entity); noExportMap.put("timeRange", timeRange); if ("csv".equals(entity.getExType())) { this._exportCsv(model, request, response, redirectAttributes, entity.getMenuNameCode(), titleList, classMap, dataMap, noExportMap); } else { this._export(model, request, response, redirectAttributes, entity.getMenuNameCode(), titleList, classMap, dataMap, noExportMap); } } catch (Exception e) { logger.error("Obj group export failed",e); addMessage(redirectAttributes,"error", "export_failed"); LogUtils.saveLog(request, null, e, null); } } /** * 批量审核 * @param page * @param auditType * @param entity * @return */ public String auditAll(Page page,Integer auditType,CfgIndexInfo entity,Properties props)throws Exception { StringBuffer tip=new StringBuffer(); long start=System.currentTimeMillis(); page.setOrderBy(""); page.setPageSize(Constants.MAAT_JSON_SEND_SIZE); page.setPageNo(1); page.setLastPage(false); //携带审核状态信息的BaseCfg BaseCfg auditBatchCfg=new BaseCfg(); //携带审核条件的BaseCfg CfgIndexInfo searchCfg=new CfgIndexInfo(); if(entity != null && (entity instanceof CfgIndexInfo)) { BeanUtils.copyProperties(entity, auditBatchCfg); BeanUtils.copyProperties(entity, searchCfg); } auditType = (Integer)Reflections.invokeGetter(entity, "isAudit"); //全部审核通过,只查询当前条件下的所有未审核的配置 -批量审核通过/不通过 if(auditType.equals(1) || auditType.equals(2)) { if(auditType.equals(1)) { auditBatchCfg.setIsAudit(1); auditBatchCfg.setIsValid(1); }else { auditBatchCfg.setIsAudit(2); auditBatchCfg.setIsValid(0); } auditBatchCfg.setAuditTime(new Date()); auditBatchCfg.setAuditorId(UserUtils.getUser().getId()); }else { auditBatchCfg.setIsAudit(3); auditBatchCfg.setIsValid(0); auditBatchCfg.setAuditTime(new Date()); auditBatchCfg.setAuditorId(UserUtils.getUser().getId()); } ServiceConfigTemplateUtil serviceTemplate = new ServiceConfigTemplateUtil(); Integer functionId=0; if(auditBatchCfg != null && !StringUtil.isEmpty(auditBatchCfg.getFunctionId())) { functionId=auditBatchCfg.getFunctionId(); } List> serviceList = serviceTemplate.getServiceListByFunctionId(functionId); for(Map service:serviceList){ String tableNameXml = service.get("tableName").toString(); // 获取业务主配置表 String serviceTypeXml = service.get("serviceType").toString(); // 业务类型 1maat 2callback String classNameXml = service.get("className").toString(); // 主配置Java类 String serviceIdXml = service.get("id").toString(); // service字典表 service_id字段 String serviceIds=service.get("serviceIds").toString(); auditBatchCfg.setServiceId(Integer.valueOf(serviceIdXml)); auditBatchCfg.setTableName(tableNameXml); //searchCfg.setServiceId(Integer.valueOf(serviceIdXml)); searchCfg.setTableName(tableNameXml); if("1".equals(serviceTypeXml)){//maat类配置 if(StringUtils.isNotBlank(serviceIds)) {//公共分组 // 存放域配置类型 及 对应表名 Map>> childrenCfgMap=new HashMap<>(); Map>> childrenUserRegionMap=new HashMap<>(); for(String _serviceId:serviceIds.split(",")){ if(StringUtils.isNotBlank(_serviceId)){ Map subService=serviceTemplate.getServiceListByServiceId(Integer.parseInt(_serviceId)).get(0); childrenCfgMap.put(Integer.parseInt(_serviceId),(List>)subService.get("cfgList")); } } if(childrenCfgMap.size()>0){ for(Map.Entry e:childrenCfgMap.entrySet()){ boolean hasData = true; while(hasData){ page.setPageNo(1); page.setLastPage(false); searchCfg.setServiceId(Integer.parseInt(e.getKey().toString())); auditBatchCfg.setServiceId(Integer.parseInt(e.getKey().toString())); List list = getDataList(page,searchCfg,null,null,null); // 通过ServiceId获取cfg_index_info主配置表数据 for(CfgIndexInfo info:list){ if(StringUtils.isBlank(info.getCommonGroupIds())){ tip.append(String.format(props.getProperty("no_common_group","The configuration ID of %s does not have an group;"),info.getCompileId())); tip.append("
"); } } if(!StringUtil.isEmpty(list)){ //配置生效处理 复用全量下发 if(auditBatchCfg.getIsAudit().equals(1)) { hasData = configSynchronizationService.auditObjGroupListMaatData(childrenCfgMap,childrenUserRegionMap,page,auditBatchCfg,list,hasData,true); }else { List BaseCfgList=new ArrayList<>(); if(!StringUtil.isEmpty(list)) { for (CfgIndexInfo cfg : list) { BaseCfg baseCfg=new BaseCfg(); BeanUtils.copyProperties(cfg, baseCfg); BaseCfgList.add(baseCfg); } } if(auditBatchCfg.getIsAudit().equals(2)) {// 配置批量审核不通过 hasData = commonPolicyService.batchUnApproveObjGroupListatData(page, auditBatchCfg, BaseCfgList, hasData); }else {// 配置失效处理 批量处理 hasData = commonPolicyService.auditObjGroupListMaatData(tableNameXml, page, auditBatchCfg, BaseCfgList, hasData); } } }else{ hasData = false; } } } } } } } //批量审核通过时,如果没有携带isValid检索条件,返回界面需要将isValid置为null if(!StringUtil.isEmpty(entity)) { BaseCfg base=(BaseCfg)entity ; base.setBatchAuditValue(""); base.setBatchValidValue(""); //配置目标状态:1 1 生效,isAudit条件置为1,有selType条件,且不是isValid不改,没有sel改为isValid并且为1 if(base.getIsAudit()==1 && base.getIsValid()==1){ base.setIsAudit(1); if(!StringUtil.isEmpty(base.getSeltype()) && !base.getSeltype().equals("isValid")) { base.setIsValid(null); }else{ base.setIsValid(1); base.setSeltype("isValid"); } } //配置目标状态:2 0 不通过,isAudit条件置为2,有selType条件,且不是isValid不改,没有sel改为isValid并且为0 if(base.getIsAudit()==2 && base.getIsValid()==0){ base.setIsAudit(2); if(!StringUtil.isEmpty(base.getSeltype()) && !base.getSeltype().equals("isValid")) { base.setIsValid(null); }else{ base.setIsValid(0); base.setSeltype("isValid"); } } //配置目标状态:3 0 取消 if(base.getIsAudit()==3 && base.getIsValid()==0){ base.setIsAudit(3); if(!StringUtil.isEmpty(base.getSeltype()) && !base.getSeltype().equals("isValid")) { base.setIsValid(null); }else{ base.setIsValid(0); base.setSeltype("isValid"); } } BeanUtils.copyProperties(base, entity); } long end=System.currentTimeMillis(); logger.warn("配置批量生效/失效耗时:"+(end-start)); return tip.toString(); } @RequestMapping(value = { "ajaxSubList"}) public String ajaxSubList(Model model, Long cfgId, Integer index, Integer compileId) { CfgIndexInfo cfg = objectGroupService.getObjectGroupCfg(cfgId, null); List tabList = new ArrayList(); model.addAttribute("_cfg", cfg); model.addAttribute("index", index); model.addAttribute("tabList", tabList); return "/cfg/objgroup/subList"; } }