Solr高亮查询案例

本例程使用Solr高亮查询商品名称,使用FreeMarker生成静态页面,Solr与FreeMarker都是使用直接调用的方式,没有使用与SpringBoot集成方案。

这里写图片描述

这里写图片描述

数据库SQL

create table t_good (id int auto_increment primary key,
    name varchar(100),price float,dt date);

create table t_shop(id int auto_increment primary key,
    name varchar(100));

create table t_g2s(gid int,sid int);

insert into t_shop(name) values('海淀');
insert into t_shop(name) values('朝阳');
insert into t_shop(name) values('丰台');

insert into t_good(name,price) values('七匹狼短袖T恤',200);
insert into t_good(name,price) values('花花公子短袖T恤',100);
insert into t_good(name,price) values('森马短袖T恤',300);

insert into t_g2s(gid,sid) values(1,1);
insert into t_g2s(gid,sid) values(1,2);
insert into t_g2s(gid,sid) values(2,2);
insert into t_g2s(gid,sid) values(2,3);

select * from t_shop s,t_g2s g2s where s.id=g2s.sid;

select g2s.gid,group_concat(s.name) sname,group_concat(s.id) sid from t_shop s,t_g2s g2s 
    where s.id=g2s.sid group by g2s.gid;

select * from t_good a left join
(select g2s.gid,group_concat(s.name) sname,group_concat(s.id) sid from t_shop s,t_g2s g2s 
    where s.id=g2s.sid group by g2s.gid) b
on a.id=b.gid where a.id=8;

数据库实体类设计

package com.test.bean;

import java.io.Serializable;
import java.sql.Date;
import java.sql.Timestamp;

import org.apache.solr.client.solrj.beans.Field;

public class GoodInfo implements Serializable{
    private Integer id = null;
    private String name = null;
    private Float price = null;
    private Date dt = null;
    private Timestamp ts = null;

    private String shopId = null;//id,id,id
    private String shopName = null;//name,name,name
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Float getPrice() {
        return price;
    }
    public void setPrice(Float price) {
        this.price = price;
    }
    public Date getDt() {
        return dt;
    }
    public void setDt(Date dt) {
        this.dt = dt;
    }
    public String getShopId() {
        return shopId;
    }
    public void setShopId(String shopId) {
        this.shopId = shopId;
    }
    public String getShopName() {
        return shopName;
    }
    public void setShopName(String shopName) {
        this.shopName = shopName;
    }   
}
package com.test.bean;

import java.io.Serializable;

public class ShopInfo implements Serializable{
    private Integer id = null;
    private String name = null;
    private String checked = "";
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getChecked() {
        return checked;
    }
    public void setChecked(String checked) {
        this.checked = checked;
    }   
}
package com.test.bean;

import java.io.Serializable;

public class G2SInfo implements Serializable{
    private Integer gid = null;
    private Integer sid = null;
    public Integer getGid() {
        return gid;
    }
    public void setGid(Integer gid) {
        this.gid = gid;
    }
    public Integer getSid() {
        return sid;
    }
    public void setSid(Integer sid) {
        this.sid = sid;
    }   
}

Mybatis 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.test.mapper.GoodMapper">
    <select id="getGoodById" resultType="com.test.bean.GoodInfo">
        select a.*,b.shopName,b.shopId from t_good a left join
        (select g2s.gid,group_concat(s.name) shopName,group_concat(s.id) shopId from t_shop s,t_g2s g2s 
            where s.id=g2s.sid group by g2s.gid) b
        on a.id=b.gid where a.id=#{id}
    </select>
    <insert id="saveGood" parameterType="com.test.bean.GoodInfo"
        useGeneratedKeys="true" keyColumn="id" keyProperty="id">
        insert into t_good(name,price,dt) values (#{name},#{price},#{dt})
    </insert>
    <update id="updateGood" parameterType="com.test.bean.GoodInfo">
        update t_good set name=#{name},price=#{price},dt=#{dt} where id=#{id}
    </update>
    <delete id="deleteGood" parameterType="Integer">
        delete from t_good where id=#{id}
    </delete>
    <select id="getShop" resultType="com.test.bean.ShopInfo">
        select * from t_shop
    </select>
    <insert id="saveG2S" parameterType="com.test.bean.G2SInfo">
        insert into t_g2s(gid,sid) values (#{gid},#{sid})
    </insert>
    <delete id="deleteG2S" parameterType="Integer">
        delete from t_g2s where gid=#{gid}
    </delete>
</mapper>

Mybatis Mapper接口

package com.test.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import com.test.bean.G2SInfo;
import com.test.bean.GoodInfo;
import com.test.bean.ShopInfo;

@Mapper
public interface GoodMapper {
    public GoodInfo getGoodById(@Param("id") Integer id);
    public void saveGood(GoodInfo gi);
    public void updateGood(GoodInfo gi);
    public void deleteGood(@Param("id") Integer id);
    public List<ShopInfo> getShop();
    public void saveG2S(G2SInfo g2s);
    public void deleteG2S(@Param("gid") Integer gid);
}

Good服务接口与实现类

package com.test.service;

import java.util.List;

import org.apache.ibatis.annotations.Param;

import com.test.bean.G2SInfo;
import com.test.bean.GoodInfo;
import com.test.bean.ShopInfo;

public interface IGoodService {
    public GoodInfo getGoodById(Integer id);
    public void saveGood(GoodInfo gi);
    public void updateGood(GoodInfo gi);
    public void deleteGood(Integer id);
    public List<ShopInfo> getShop();
    public void saveG2S(G2SInfo g2s);
    public void deleteG2S(Integer gid);
}
package com.test.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.test.bean.G2SInfo;
import com.test.bean.GoodInfo;
import com.test.bean.ShopInfo;
import com.test.mapper.GoodMapper;
import com.test.service.IGoodService;

@Service
public class GoodServiceImpl implements IGoodService{
    @Autowired
    private GoodMapper mapper;

    @Override
    public GoodInfo getGoodById(Integer id) {
        try
        {
            return mapper.getGoodById(id);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public void saveGood(GoodInfo gi) {
        try
        {
            mapper.saveGood(gi);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

    @Override
    public void updateGood(GoodInfo gi) {
        try
        {
            mapper.updateGood(gi);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

    @Override
    public void deleteGood(Integer id) {
        try
        {
            mapper.deleteGood(id);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

    @Override
    public void saveG2S(G2SInfo g2s) {
        try
        {
            mapper.saveG2S(g2s);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

    @Override
    public void deleteG2S(Integer gid) {
        try
        {
            mapper.deleteG2S(gid);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

    @Override
    public List<ShopInfo> getShop() {
        try
        {
            return mapper.getShop();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        return null;
    }

}

GoodController设计

package com.test.ctrl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.test.bean.G2SInfo;
import com.test.bean.GoodInfo;
import com.test.bean.ShopInfo;
import com.test.service.IGoodService;
import com.test.util.FreeMarkerUtil;
import com.test.util.PageUtil;
import com.test.util.ResultInfo;
import com.test.util.SolrUtil;

@Controller
public class GoodCtrl {
    @Autowired
    private IGoodService serv;
    //使用直连Solr的方式,没有使用集成的SolrClient
    private String url = "http://localhost:8984/solr/new_core2";

    /**
     * 列表页面
     * @param req
     * @param page 当前页码
     * @param rows 每页显示记录数
     * @return
     */
    @RequestMapping("/list")
    public String list(HttpServletRequest req,Integer page,Integer rows)
    {
        if(page == null)
            page = 1;
        if(rows == null)
            rows = 4;
        String name = req.getParameter("name");
        //定义查询Solr的字符串
        String query = null;
        if(name == null || "".equals(name))
            query = "*:*";
        else
            query = "name:"+name;
        System.out.println("query="+query);
        List<String> flList = new ArrayList<String>();
        flList.add("name");
        Integer starts = (page-1)*rows;
        //使用SolrUtil工具类高亮查询
        SolrUtil solr = new SolrUtil(url);
        //高亮查询返回自定义对象ResultInfo
        ResultInfo<GoodInfo> rtn = solr.queryHL(GoodInfo.class,query,
                flList,starts,rows);

        String listUrl = "/list";
        Long total = rtn.getTotal();
        //实现分页导航
        PageUtil pu = new PageUtil(listUrl,page,rows,total);

        List<GoodInfo> list = rtn.getList();
        String pageHtml = pu.toHtml();
        //添加Request上下文数据,前台页面使用JSTL标签展示
        req.setAttribute("list", list);
        req.setAttribute("pageHtml", pageHtml);
        req.setAttribute("query", name);

        return "good";
    }

    /**
     * 前台点击跳转对应方法
     */
    @RequestMapping("/add")
    public String add(HttpServletRequest req)
    {
        //检索店铺列表,存放到Request对象中,以备前台页面展示
        List<ShopInfo> shopList = serv.getShop();
        req.setAttribute("shopList", shopList);
        return "add";
    }

    /**
     * 保存和更新对应的方法
     * @param req
     * @param gi 通过Request中的参数封装对象GoodInfo
     * @return
     */
    @RequestMapping("/save")
    public String save(HttpServletRequest req,GoodInfo gi)
    {
        Integer id = gi.getId();
        //必须在保存GoodInfo之前,获取店铺ID
        String shopId = gi.getShopId();
        System.out.println("shopId="+shopId);
        boolean isNew = false;
        if(id == null)
        {
            //新增
            serv.saveGood(gi);
            isNew = true;
        }
        else
        {
            //更新
            serv.updateGood(gi);
            //删除原来此商品关联的店铺信息
            serv.deleteG2S(id);
            isNew = false;
        }
        //根据页面传入店铺ID信息,添加到关联表
        if(shopId != null)
        {
            String[] dim = shopId.split(",");
            for(String sid:dim)
            {
                G2SInfo g2s = new G2SInfo();
                //对象gi保存后记录了生成的ID,需要在Mybatis后台XML文件配置useGenerateKeys=true
                g2s.setGid(gi.getId());
                g2s.setSid(Integer.parseInt(sid));
                serv.saveG2S(g2s);
            }
        }
        //重新关联查询GoodInfo对象,需要从中间表装载店铺相关信息
        gi = serv.getGoodById(gi.getId());
        //定义Map对象,将数据保存到Solr中
        Map m = new HashMap();
        m.put("id", gi.getId().toString());
        m.put("name", gi.getName());
        m.put("price", gi.getPrice());
        m.put("dt", gi.getDt());
        m.put("shopId", gi.getShopId());
        m.put("shopName", gi.getShopName());
        System.out.println("map="+m);
        SolrUtil solr = new SolrUtil(url);
        if(isNew)
            solr.addMap(m);//新增
        else
        {
            solr.update(m);//更新

            //根据Map对象和FreeMarker模板生成静态页面
            String ftlDir = "flt";
            String ftlName = "good.html";
            String htmlDir = "html";
            FreeMarkerUtil.genHtml(req.getServletContext(), m, ftlDir, ftlName, htmlDir);
        }



        return "redirect:list";
    }

    /**
     * 根据前台传入的ID删除数据库及Solr中的数据,也删除静态页面
     * @param req
     * @param chkid
     * @return
     */
    @RequestMapping("/delete")
    public String delete(HttpServletRequest req,Integer[] chkid)
    {
        if(chkid != null)
        {
            SolrUtil solr = new SolrUtil(url);
            for(Integer id:chkid)
            {
                System.out.println("id="+id);
                serv.deleteGood(id);
                serv.deleteG2S(id);
                solr.deleteById(id.toString());
                //删除静态页面
                String htmlDir = "html";
                FreeMarkerUtil.deleteHtml(req.getServletContext(), htmlDir, id);
            }
        }
        //跳转到列表页面
        return "redirect:list";
    }

    /**
     * 修改GoodInfo页面对应的方法
     * @param req
     * @param id
     * @return
     */
    @RequestMapping("/modify")
    public String modify(HttpServletRequest req,Integer id)
    {
        //根据前台传入的ID,检索GoodInfo对象
        GoodInfo gi = serv.getGoodById(id);
        String shopId = gi.getShopId();
        //根据对象包含的店铺ID信息,选中Checkbox状态
        List<ShopInfo> shopList = serv.getShop();
        for(ShopInfo si:shopList)
        {
            System.out.println(shopId+","+si.getId());
            if(shopId.indexOf(si.getId().toString())>=0)
            {
                si.setChecked("checked");
            }
        }

        req.setAttribute("shopList", shopList);
        req.setAttribute("good", gi);
        return "add";
    }

    /**
     * 查看静态页面,根据Map与Freemarker模板生成静态页面,并跳转到静态页面
     * @param req
     * @param id
     * @return
     */
    @RequestMapping("/view")
    public String view(HttpServletRequest req,Integer id)
    {
        GoodInfo gi = serv.getGoodById(id);
        Map m = new HashMap();
        m.put("id", gi.getId().toString());
        m.put("name", gi.getName());
        m.put("price", gi.getPrice());
        m.put("dt", gi.getDt());
        m.put("shopId", gi.getShopId());
        m.put("shopName", gi.getShopName());
        System.out.println("map="+m);

        //使用FreeMarkerUtil工具类生成静态页面
        String ftlDir = "flt";
        String ftlName = "good.html";
        String htmlDir = "html";
        FreeMarkerUtil.genHtml(req.getServletContext(), m, ftlDir, ftlName, htmlDir);
        String htmlFile = "/html/"+id+".html";
        return "redirect:"+htmlFile;
    }
}

SolrUtil工具类

package com.test.util;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.UpdateResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;

public class SolrUtil {
    private HttpSolrClient client = null;

    public SolrUtil(String url)
    {
        //SolrJ-7.3.1
        //client = new HttpSolrClient.Builder(url).build();
        //SolrJ-5.5.5
        client = new HttpSolrClient(url);
    }

    /**
     * 将Map对象添加到Solr中
     * @param m
     */
    public boolean addMap(Map m)
    {
        //Key-Value,
        //Key Set;Value Collection
        Set kset = m.keySet();
        SolrInputDocument doc = new SolrInputDocument();
        for(Object k:kset)
        {
            Object val = m.get(k);
            if(val != null)
                doc.addField(k.toString(), val);
        }
        try
        {
            client.add(doc);
            UpdateResponse resp = client.commit();
            if(resp.getStatus() == 0)
                return true;
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 更新Solr中的文档,Map对象中必须存在id键用于定位doc文档
     * Map中其他的键值对是修改的内容,Key<String>代表数据域名称,
     * Value<Object>代表修改值
     * @param map
     */
    public boolean update(Map<String,Object> map)
    {
        try
        {
            String id = (String)map.get("id");
            SolrInputDocument doc = new SolrInputDocument();
            doc.addField("id", id);
            for(String k:map.keySet())
            {
                if(!"id".equals(k))
                {
                    Map map2 = new HashMap();
                    map2.put("set", map.get(k));
                    doc.addField(k, map2);
                }
            }
            client.add(doc);
            UpdateResponse resp = client.commit();
            if(resp.getStatus() == 0)
                return true;
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 通过文档ID删除Solr中的文档
     * @param id
     */
    public boolean deleteById(String id)
    {
        try
        {
            client.deleteById(id);
            UpdateResponse resp = client.commit();
            if(resp.getStatus() == 0)
                return true;
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 通过查询删除Solr中对应的数据集合
     * @param query
     */
    public boolean deleteByQuery(String query)
    {
        try
        {
            client.deleteByQuery(query);
            UpdateResponse resp = client.commit();
            if(resp.getStatus() == 0)
                return true;
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 通过泛型获取Solr中的对象集合
     * @param clz 泛型类对应java.lang.Class
     * @param query 数据域名称:数据域的值;查询全部*:*;多条件查询 name:Java AND age:20
     * @param flList 高亮显示数据域名称,是List<String>集合
     * @param page 分页查询时,开始记录数
     * @param rows 本次查询检索记录数
     * @return
     */
    public <T> ResultInfo<T> queryHL(Class<T> clz,String query,List<String> flList,
            Integer page,Integer rows)
    {
        try
        {
            //定义返回自定义数据结构对象
            ResultInfo<T> rslt = new ResultInfo<T>();
            SolrQuery q = new SolrQuery();
            q.set("q", query);
            q.set("fl","*");
            q.setHighlight(true);
            //高亮显示字段
            String hlField = "";
            for(String s:flList)
                hlField = hlField + s + ",";
            if(hlField.endsWith(","))
                hlField = hlField.substring(0,hlField.length()-1);
            q.set("hl.fl",hlField);
            //
            q.setHighlightSimplePre("<font color=\"red\">");
            q.setHighlightSimplePost("</font>");
            q.setStart(page);
            q.setRows(rows);
            QueryResponse qr = client.query(q);
            Map<String,Map<String,List<String>>> hlMap = qr.getHighlighting();
            System.out.println(hlMap);
            //Map<ID,Map<FieldName,[MultiValue]>>
            SolrDocumentList lst = qr.getResults();
            List<T> rtn = new ArrayList<T>();
            Long total = qr.getResults().getNumFound();

            for(SolrDocument doc:lst)
            {
                String id = (String)doc.getFieldValue("id");
                T t = clz.newInstance();
                //获取自定义类所有属性名称
                Field[] flds = getField(clz);
                for(Field field:flds)
                {
                    String fname = field.getName();
                    String solrFldName = getSolrFieldName(clz,field);               
                    String fObj = getSingleValue(doc.getFieldValue(solrFldName));
                    if(fObj == null)
                        continue;
                    if(field.getType() == java.sql.Date.class)
                    {
                        java.util.Date dt = new java.util.Date(fObj);
                        fObj = new java.sql.Date(dt.getTime()).toString();
                    }
                    if(field.getType() == java.sql.Timestamp.class)
                    {
                        java.util.Date dt = new java.util.Date(fObj);
                        fObj = new java.sql.Timestamp(dt.getTime()).toString();
                    }
                    if(field.getType() == java.sql.Time.class)
                    {
                        java.util.Date dt = new java.util.Date(fObj);
                        fObj = new java.sql.Time(dt.getTime()).toString();
                    }
                    //高亮显示数据形式
                    ////Map<ID,Map<FieldName,[MultiValue]>>
                    if(flList.contains(fname))
                    {
                        //Map<FieldName,List<MultiValue>>
                        Map<String,List<String>> fldMap = hlMap.get(id);
                        Object hlObj = fldMap.get(fname);
                        String hlVal = getSingleValue(hlObj);
                        if(hlVal != null)
                            fObj = hlVal;

                    }
                    if(fObj != null)
                        BeanUtils.setProperty(t, fname, fObj);
                }
                rtn.add(t);
            }
            rslt.setList(rtn);
            rslt.setTotal(total);
            return rslt;

        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 转化多值域为单值
     * @param obj
     * @return
     */
    private String getSingleValue(Object obj)
    {
        if(obj == null)
            return null;
        String val = obj.toString();
        if(val.startsWith("[") && val.endsWith("]"))
        {
            return val.substring(1,val.length()-1);
        }
        return val;
    }

    /**
     * 根据Class对象获取此类型的定义属性数据
     * @param clz
     * @return
     */
    private Field[] getField(Class clz)
    {
        Field[] flds = clz.getDeclaredFields();
        return flds;
    }

    /**
     * 通过Field对象取得其上定义的注解名称
     * @param clz
     * @param fld
     * @return
     */
    private String getSolrFieldName(Class clz,Field fld)
    {
        org.apache.solr.client.solrj.beans.Field fld2 = 
                fld.getAnnotation(org.apache.solr.client.solrj.beans.Field.class);
        if(fld2 == null)
            return fld.getName();

        if(fld2.value().equals("#default"))
            return fld.getName();
        else
            return fld2.value();

    }

    public static void main(String[] args)
    {
        System.out.println(new java.util.Date());
        Map m = new HashMap();
        m.put("sid", "10");
        m.put("name","Java");
        String url = "http://localhost:8984/solr/new_core2/";
        SolrUtil solr = new SolrUtil(url);
        solr.addMap(m);

    }
}
package com.test.util;

import java.util.List;

/**
 * 查询Solr返回的对象,对象类型为T的集合,还包含Solr中符合条件记录总数
 * @param <T>
 */
public class ResultInfo<T> {
    private List<T> list = null;
    private Long total = null;

    public List<T> getList() {
        return list;
    }
    public void setList(List<T> list) {
        this.list = list;
    }
    public Long getTotal() {
        return total;
    }
    public void setTotal(Long total) {
        this.total = total;
    }   
}

分页工具类

package com.test.util;

public class PageUtil {
    private Integer page = 1;//默认显示第一页
    private Integer rows = 4;//每页显示记录数
    private Long total = null;//总行数
    private String url = null;//点击页码跳转url

    public PageUtil(String url,Integer page,Integer rows,Long total)
    {
        this.url = url;
        this.page = page;
        this.rows = rows;
        this.total = total;
    }

    public String toHtml()
    {
        StringBuffer sb = new StringBuffer();
        //计算总页数
        int pages = 0;
        if(total % rows == 0)
            pages = total.intValue() / rows;
        else
            pages = (total.intValue() / rows) + 1;
        sb.append("<div id='pagediv'>\r\n");
        String firstUrl = null;
        if(url.indexOf("?")>0)
            firstUrl = url + "&page=1&rows="+rows;
        else
            firstUrl = url + "?page=1&rows="+rows;
        sb.append("<a href='"+firstUrl+"'>首页</a>\r\n");
        String backUrl = null;
        if(url.indexOf("?")>0)
            backUrl = url + "&page="+(page==1?1:(page-1))+"&rows="+rows;
        else
            backUrl = url + "?page="+(page==1?1:(page-1))+"&rows="+rows;
        sb.append("<a href='"+backUrl+"'>上一页</a>\r\n");
        for(int i=1;i<=pages;i++)
        {
            String pageUrl = null;
            if(url.indexOf("?")>0)
                pageUrl = url + "&page="+i+"&rows="+rows;
            else
                pageUrl = url + "?page="+i+"&rows="+rows;
            if(i == page)
                sb.append("<a href='"+pageUrl+"'><b><font color='red'>"+i+"</font></b></a>\r\n");
            else
                sb.append("<a href='"+pageUrl+"'>"+i+"</a>\r\n");
        }
        String nextUrl = null;
        if(url.indexOf("?")>0)
            nextUrl = url + "&page="+(page==pages?pages:(page+1))+"&rows="+rows;
        else
            nextUrl = url + "?page="+(page==pages?pages:(page+1))+"&rows="+rows;
        sb.append("<a href='"+nextUrl+"'>下一页</a>\r\n");
        String lastUrl = null;
        if(url.indexOf("?")>0)
            lastUrl = url + "&page="+pages+"&rows="+rows;
        else
            lastUrl = url + "?page="+pages+"&rows="+rows;
        sb.append("<a href='"+lastUrl+"'>尾页</a>\r\n");
        sb.append("&nbsp;&nbsp;&nbsp;&nbsp;第"+page+"/"+pages+"页\r\n");
        sb.append("&nbsp;&nbsp;&nbsp;&nbsp;共"+total+"条记录\r\n");
        sb.append("</div>\r\n");
        return sb.toString();
    }
}

FreeMarkerUtil工具类

package com.test.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;

import freemarker.template.Configuration;
import freemarker.template.Template;

public class FreeMarkerUtil {

    /**
     * 
     * @param ctx
     * @param map Map中必须包含id的键,id将作为静态HTML的文件名
     * @param ftlDir
     * @param ftlName
     * @param htmlDir
     */
    public static void genHtml(ServletContext ctx,Map map,
            String ftlDir,String ftlName,String htmlDir)
    {
        try
        {
            if(!map.containsKey("id"))
            {
                throw new Exception("Map参数必须包含键值id");
            }

            //1.定义FreeMarker配置对象
            Configuration config = new Configuration(Configuration.VERSION_2_3_23);
            //2.设定模板加载路径
            config.setServletContextForTemplateLoading(ctx, ftlDir);
            //3.根据模板文件名获取模板对象
            Template templt = config.getTemplate(ftlName);
            //4.根据htmlDir获取HTML所在的绝对目录
            String path = ctx.getRealPath(htmlDir);
            String id = (String)map.get("id");
            String fileName = path + "/"+ id + ".html";
            //5.定义文件输出流,将FreeMarker的输出写入到文件
            FileOutputStream fos = new FileOutputStream(fileName);
            //将文件输出流[字节流]转化为字符输出流[有编码]
            OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF8");
            //FreeMarker根据模板和数据模型生成静态页面
            templt.process(map, osw);
            osw.close();
            fos.close();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

    /**
     * 
     * @param ctx
     * @param map Map中必须包含id的键,id将作为静态HTML的文件名
     * @param ftlDir
     * @param ftlName
     * @param htmlDir
     */
    public static void genExcel(ServletContext ctx,List lst,
            String ftlDir,String ftlName,String htmlDir)
    {
        try
        {
            //1.定义FreeMarker配置对象
            Configuration config = new Configuration(Configuration.VERSION_2_3_23);
            //2.设定模板加载路径
            config.setServletContextForTemplateLoading(ctx, ftlDir);
            //3.根据模板文件名获取模板对象
            Template templt = config.getTemplate(ftlName);
            //4.根据htmlDir获取HTML所在的绝对目录
            String path = ctx.getRealPath(htmlDir);
            String fileName = path + "/excelout.xml";
            //5.定义文件输出流,将FreeMarker的输出写入到文件
            FileOutputStream fos = new FileOutputStream(fileName);
            //将文件输出流[字节流]转化为字符输出流[有编码]
            OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF8");
            //FreeMarker根据模板和数据模型生成静态页面
            Map map = new HashMap();
            map.put("blogList", lst);
            templt.process(map, osw);

            fos.close();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

    public static void deleteHtml(ServletContext ctx,String htmlDir,Integer id)
    {
        try
        {
            String path = ctx.getRealPath(htmlDir);
            String file = path + "\\" + id +".html";
            File f = new File(file);
            boolean isOk = f.delete();
            System.out.println(f+",isOk="+isOk);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}

日期转化类

package com.test.util;

import java.sql.Date;
import java.text.SimpleDateFormat;

import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

@Component
public class CustomDateConverter implements Converter<String, Date>  {
        private static final String dateFormat      = "yyyy-MM-dd HH:mm:ss";
        private static final String shortDateFormat = "yyyy-MM-dd";

    /**
     * @param source
     * @return
     */
    @Override
    public Date convert(String source) {
        if (source == null || "".equals(source)) {
            return null;
        }
        source = source.trim();
        try {
            if (source.contains("-")) {
                SimpleDateFormat formatter;
                if (source.contains(":")) {
                    formatter = new SimpleDateFormat(dateFormat);
                } else {
                    formatter = new SimpleDateFormat(shortDateFormat);
                }
                java.util.Date dtDate = formatter.parse(source);
                return new Date(dtDate.getTime());
            } else if (source.matches("^\\d+$")) {
                Long lDate = new Long(source);
                return new Date(lDate);
            }
        } catch (Exception e) {
            throw new RuntimeException(String.format("parser %s to Date fail", source));
        }
        throw new RuntimeException(String.format("parser %s to Date fail", source));
    }
}

列表JSP

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>    
<!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>商品列表</title>
<link rel="stylesheet" type="text/css" href="/jscss/base.css">
<script type="text/javascript" src="/jscss/jquery.min.js"></script>
<script>
    function doquery()
    {
        var query = $('#name').val();
        location.href="/list?name="+query;
    }
    function doadd()
    {
        window.open('/add','_self');
    }
    function selectAll()
    {
        $("input[name='chkid']").each(function(){
            this.checked=!this.checked;
        });
    }
    function dodelete()
    {
        goodForm.submit();
    }
    function domodify(id)
    {
        window.open('/modify?id='+id,'_self');
    }
    function doview(id)
    {
        window.open('/view?id='+id,'_blank');
    }
</script>
</head>
<body>
<form id="goodForm" action="/delete">
<input type="text" id="name" name="name" value="${query}"/>
<input type="button" value="查询" onclick="doquery()"/>
<input type="button" value="添加" onclick="doadd()"/>
<table>
    <tr>
        <th>全选<input type="checkbox" id="chkall" name="chkall" onclick="selectAll();"></th>
        <th>编号</th>
        <th>名称</th>
        <th>店铺</th>
        <th>价格</th>
        <th>上架时间</th>
        <th>操作</th>
    </tr>

    <c:forEach items="${list }" var="g">
    <tr>
        <td><input type="checkbox" id="chkid" name="chkid" value="${g.id }"></td>
        <td>${g.id }</td>
        <td>${g.name }</td>
        <td>${g.shopName }</td>
        <td>${g.price }</td>
        <td>${g.dt }</td>
        <td>
        <input type="button" value="查看" onclick="doview('${g.id }')"/>
        <input type="button" value="修改" onclick="domodify('${g.id }')"/>
        </td>
    </tr>
    </c:forEach>
</table>
${pageHtml}
<input type="button" value="删除" onclick="dodelete()"/>
</form>
</body>
</html>

添加与修改JSP页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>    
<!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>商品添加</title>
<link rel="stylesheet" type="text/css" href="/jscss/base.css">
<script type="text/javascript" src="/jscss/jquery.min.js"></script>
<script>
    function dosave()
    {
        goodForm.submit();
    }
    function dolist()
    {
        location.href="/list";
    }
</script>
</head>
<body>
<form id="goodForm" action="/save">
    <table>
        <input type="hidden" id="id" name="id" value="${good.id }"/>
        <tr>
            <td>商品名称</td>
            <td><input type="text" id="name" name="name" value="${good.name }"/></td>
        </tr>
        <tr>
            <td>商品价格</td>
            <td><input type="text" id="price" name="price" value="${good.price }"/></td>
        </tr>
        <tr>
            <td>上架时间</td>
            <td><input type="text" id="dt" name="dt" value="${good.dt }"/></td>
        </tr>
        <tr>
            <td>店铺</td>
            <td>
                <c:forEach items="${shopList}" var="s">
                    <input type="checkbox" id="shopId" name="shopId" value="${s.id }" ${s.checked }>${s.name }
                </c:forEach>
            </td>
        </tr>
    </table>
    <input type="button" value="保存" onclick="dosave()"/>
    <input type="button" value="返回" onclick="dolist()"/>
</form>
</body>
</html>

Good Freemarker模板

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>商品详情</title>
</head>
<body>
    <h3>名称:${name}</h3>
    <h3>价格:${price}</h3>
    <h3>店铺名称:${shopName}</h3>
    <h3>上架时间:${dt!}</h3>
</body>
</html>

代码共享:
https://pan.baidu.com/s/1D24wCQenT5mT3tkSWVZwZQ

猜你喜欢

转载自blog.csdn.net/qixiang_chen/article/details/82716877