本例程使用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(" 第"+page+"/"+pages+"页\r\n");
sb.append(" 共"+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>