缓存第五篇:无框架的自定义页面缓存---从后台到页面

来源:互联网 发布:战地1枪械数据 编辑:程序博客网 时间:2024/06/06 02:12

前几篇讲的缓存都是后台缓存,并且思路都是与mybatis结合的sql持久化层的缓存,用的redis或者ehache缓存框架。今天我们讲一个前台页面缓存,没有任何框架,纯java代码,并且很实用和灵活。是从我们项目中抽离出来的分享给大家。

1.前台页面缓存主要用在什么地方?

我们这里主要是用在下拉框数据显示上,和前端工程师的静态页面缓存没任何关联。如果用户登录成功进入功能页面,一些预先加载的数据中,查询条件的下拉数据是绝对要先加载好的。

2.下拉数据缓存的数据结构

下拉数据的结构设计直接影响取值和级联效果的开发难以程度。非常重要。下拉的数据最合理的结构之一如下:

[{id:"真实值",name:"显示值"},{id:"真实值",name:"显示值"},...]比如[{id:"A",name:"北京分公司"},{id:"B",name:"湖北分公司"}]

那这些数据结构如何构造出来的呢?
我们在执行查询语句的Service层,对查询出来的数据进行结构调整。下面这个可以先简单看下,和后面的具体步骤结合更好理解。

sql:SELECT DISTINCT MANAGECOMCODE AS ID,NAME,MANAGECOM FROM.....//查询语句List<Map<String,String>> list=appDao.queryForMapList("SOA.DataDict.getBranchByUserId",param);//执行查询出来的数据结构为List<Map<String,String>>,比如[{"A":"北京分公司","ID":"10","NAME":"北京分支"},{"B":"湖北分公司","ID":"20","NAME":"十堰分支"},...];要让这数据拆成[{id:"A",name:"北京分公司"},{id:"B",name:"湖北分公司"}]Map<String,List<Map<String,String>>> data=new HashMap<String,List<Map<String,String>>>();//防止字典表数据重复,也为了拆分map值。用到HashSetSet<String> keySet =new HashSet<String>();for(Map<String,String> map:list){    //把所有公司码都作为key先放到set集合中,也有去重复作用。    keySet.add(map.get("MANAGECOM"));}//然后根据公司码遍历出公司名。重新构造数据结构for(String key:keySet){    List<Map<String,String>> cd=new ArrayList<Map<String,String>>();    for(Map<String,String> map:list){        if(map.get("MANAGECOM").equals(key)){            Map<String,String> org=new HashMap<String,String>();            org.put("id",map.get("ID"));            org.put("name",map.get("NAME"));            cd.add(org);        }    }data.put(key,cd);}return data;

3.用的什么来缓存数据?

shiro的Session来存储数据。因为用户登录用到shiro,验证通过就可以加载缓存。

4.数据缓存从后台到前台页面的流程

1.查询出数据,进行数据结构调整。—service层

2.将数据进一步区分,放到公共的缓存HashMap中—cache层,相当于service层

3.用户登录成功,创建session,并把公共的缓存setAttribute进session中。

4.到加载菜单页面的公共页面取出缓存数据,并转数据类型为json

5.在单独一个js中对json缓存数据进行按key区分,取出数据封装下拉框公共方法

6.在各个子页面引入公共方法和公共页面,展示出数据。

5.具体实现步骤(看思路,代码供参考,不具备复现价值)

项目框架:ssm
现在我们要实现一个省市区中省份的下拉数据展示,则依它来了解数据流如何从数据库到下拉菜单的。

5.1 数据库中省的单表数据结构如下图 ,表名称:soa_province,表字段有PROVINCE , NAME , ENABLED , ADDUSER , ADDTIME .

这里写图片描述

5.2 mapper文件的SQL查询语句,这就开始注意数据结构的id,name字段

<select id="getProvince" resultMap="BaseResultMap">    SELECT PROVINCE AS ID,NAME FROM SOA_PROVINCE WHERE ENABLED='Y'</select>

5.3 service层执行查询的语句,调整数据结构

@Service(DataDictSerice.service_ID)public class DataDictServiceImpl extends BaseServiceImpl implements DataDictSerice{    public List<Map<String,String>> getProvince(){        List<Map<String,String>> list=appDAO.queryForMapList("SOA.getProvince",new HashMap());        List<Map<String,String>> data=new ArrayList<Map<String,String>>();        Map<String,String> map;        final String ID="id";        final String NAME="name";        for(Map<String,String> map:list){            map=new HashMap<String,String>();            map.put(ID,map.get("ID"));            map.put(NAME,map.get("NAME"));            data.add(map);        }    return data;    }}

5.4 对数据进一步处理,并存放到HashMap中。

@Service("CommonCacheMap")public class CommonCacheMap{    @Resource(name=DataDictService.SERVICE_ID)    private DataDictService dataDictService;    public static final Map<String,Object> baseData=new HashMap<String,Object>();    //系统启动时就加载好各缓存    @PostConstruct    public void afterPropertiesSet() throws Exception{        SoaDataDictProvince();        SoaDataDictCity();        ...    }    private static Map<String,String> PROVINCE=new ConcurrentHashMap<String,String>();    private void SoaDataDictProvince(){        PROVINCE.clear();        List<Map<String,String>> data=dataDictService.getProvince()        for(Map<String,String> map:data){            PROVINCE.put(map.get("id"),map.get("name"))        }        baseData.put("province",data);    }}

5.5 在用户登录时把HashMap中的数据放到session中返回前台菜单公共页面

@Controller("mainController")@RequestMapping(value="")public class MainController extends BaseController{    @Resource(name=ISystemService.SERVICE_ID)    private ISystemService systemAction;    @RequestMapping("/importFunction")    public ModelAndView main(HttpServletRequest request){        LoginUser user=UserUtils.getUser();         UserBo userInfo=user.getUser();        Map<String,Object> baseData=CommonCacheMap.baseData;        Session session=SecurityUtils.getSubject().getSession();        session.setAttribute("baseData",baseData);        session.setAttribute("currentUser",user);        ModelAndVilw modelAndView=new ModelAndView();        //用modelandvilw实现转跳到main.jsp页面        modelAndView.setViewName("main");        return modelAndView;    }}

5.6 main.jsp公共页面处理缓存数据,转换为json数据。

在main.jsp中并没有直接处理数据js代码,但是main.jsp引入了别的jsp页面来处理后台传过来的数据
这里写图片描述
在include.jsp公共页面中。确实有处理的代码。

第一步:取到baseData

<%String baseData="";Object base=session.getAttribute("baseData");if(base !=null){    baseData=JSONUtils.toJOSNString(base);}%>第二步  赋值给jsp变量并转换数据类型。<script type="text/javascript">    var baseData;    var bb="<%=baseData%>";    if(bb){        baseData=eval("("+bb+")")    }</script>

下图为强转后的数据结构:
这里写图片描述
在这个include.jsp页面处理完缓存后才能引入data.js文件。注意按先后顺序加载!

5.7 封装缓存为公共方法,供子页面调用。在data.js这个js文件中实现。
//定义全局变量

var comObj,saleCom,center,city,dept,group,branch,province,....;if(baseData){    province=baseData.province;//省    city=baseData.city;//市}//为下拉显示加上全部这个字段。function getAllProvince(){    if([]!=province){        var temp=$.extend(true,[],province);        temp.unshift({'id':'','name':'全部'});        return temp;    }}function getAllCity(key){    if([] !=city[key]){        var temp=$.extend(true,[],city[key]);        temp.unshift({'id':'','name':"全部"});        return temp;    }}

5.8 在子页面引用封装的方法,easyui框架来实现下拉。

<input class="easyui-combobox" id="transProv" name="transProv"/>//省市区下拉列表$("#transProv").combobox({    editable:false;    data:getAllProvince(),    valueField:"id",    textFileld:"name",    onSelect:function(current){        $("#transCity").combobox({            editable:false;            data:getAllCity(current.id),            valueField:"id",            textField:"name",            onSelect:function(currentd){                $("#transDisr").combobox({                    editable:false,                    data:getAllDist(currentd.id),                    valueField:"id",                    textField:"name"                })            }        })$("#transDistr").combobox('setValue','');$("#transDistr").combobox('loadData',[]);    }})
原创粉丝点击