项目代码块
1.16,登录过滤器
1.16,登录过滤器代码
public class LoginFilter implements Filter {
@Override public void destroy() {
扫描二维码关注公众号,回复:
3315520 查看本文章
}
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest)servletRequest; HttpServletResponse response = (HttpServletResponse)servletResponse; String uri = request.getRequestURI(); //判断当前请求地址是否是登录的请求地址 if(!uri.contains("sys/login_")){ //非登录请求 if(request.getSession().getAttribute(Constant.USER) != null){ //说明已经登录过 chain.doFilter(request, response); } else { //没有登录,跳转到登录页面 response.sendRedirect(request.getContextPath() + "/sys/login_toLoginUI.action"); } } else { //登录请求;直接放行 chain.doFilter(request, response); } } @Override public void init(FilterConfig arg0) throws ServletException { }
} |
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <filter> <filter-name>loginFilter</filter-name> <filter-class>cn.itcast.core.filter.LoginFilter</filter-class> </filter> <filter-mapping> <filter-name>loginFilter</filter-name> <url-pattern>*.action</url-pattern> </filter-mapping> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>*.action</url-pattern> </filter-mapping> |
1.17,五大子系统权限鉴定
1.17.1,图解
1.17.2,代码
public class LoginFilter implements Filter {
@Override public void destroy() { }
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; String uri = request.getRequestURI(); // 判断当前请求地址是否是登录的请求地址 if (!uri.contains("sys/login_")) { // 非登录请求 if (request.getSession().getAttribute(Constant.USER) != null) { // 判断是否访问纳税服务系统 if (uri.contains("/nsfw/")) { // 访问纳税服务子系统 User user = (User) request.getSession().getAttribute( Constant.USER); // 获取spring容器 WebApplicationContext applicationContext = WebApplicationContextUtils .getWebApplicationContext(request.getSession() .getServletContext());
PermissionCheck pc = (PermissionCheck) applicationContext .getBean("permissionCheck"); if (pc.isAccessible(user, "nsfw")) { // 说明有权限,放行 chain.doFilter(request, response); } else { // 没有权限,跳转到没有权限提示页面 response.sendRedirect(request.getContextPath() + "/sys/login_toNoPermissionUI.action"); } } else { // 非访问纳税服务子系统,则直接放行 chain.doFilter(request, response); } } else { // 没有登录,跳转到登录页面 response.sendRedirect(request.getContextPath() + "/sys/login_toLoginUI.action"); } } else { // 登录请求;直接放行 chain.doFilter(request, response); } }
@Override public void init(FilterConfig arg0) throws ServletException { }
} |
public boolean isAccessible(User user, String code); |
public class PermissionCheckImpl implements PermissionCheck {
@Resource private UserService userService;
@Override public boolean isAccessible(User user, String code) { //1、获取用户的所有角色 List<UserRole> list = user.getUserRoles(); if(list == null){ list = userService.getUserRolesByUserId(user.getId()); }
//2、根据每个角色对于的所有权限进行对比 if(list != null && list.size()>0){ for(UserRole ur: list){ Role role = ur.getId().getRole(); for(RolePrivilege rp: role.getRolePrivileges()){ //对比是否有code对应的权限 if(code.equals(rp.getId().getCode())){ //说明有权限,返回true return true; } } } } return false; } } |
// 2.1、登录成功 User user = list.get(0); // 2.1.1、根据用户id查询该用户的所有角色 user.setUserRoles(userService.getUserRolesByUserId(user .getId())); // 2.1.2、将用户信息保存到session中 ServletActionContext.getRequest().getSession() .setAttribute(Constant.USER, user);
|
private List<UserRole> userRoles; |
<!-- 权限鉴定类 --> <bean id="permissionCheck" class="cn.itcast.core.permission.impl.PermissionCheckImpl"></bean> |
// 跳转到没有权限提示页面 public String toNoPermissionUI() { return "noPermissionUI"; } |
<result name="noPermissionUI">/WEB-INF/jsp/noPermissionUI.jsp</result> |
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <html> <head> <title>没有权限</title> </head>
<body> 对不起!您没有访问此功能的权限;请联系系统管理员。 <a href="javascript:history.go(-1)">《《返回</a> </body> </html> |
1.18,解决登录嵌套问题(session过期)
1.18.1,产生的现象
场景一:过30分钟,会出现 |
场景二:第一步打开两个窗口 |
窗口一: |
窗口二: |
步骤二:第二个窗口点击退出返回到登录页面
|
步骤三:再在第一个窗口点击用户管理: |
问题出现了,出现了页面嵌套的问题。 |
1.18.2,原因分析
1,当点击用户管理的时候我们登录过滤器规定,只要没登录就跳转到登录页面,因为这个时候seesion已经退出了,所以这个没问题。(现在把这个问题拆开来看) |
2,<a class="yh" href="${ctx }nsfw/role_listUI.action" target="mainFrame">这个页面规定点击超链接的时候就跳转到规定的页面。 |
3,登录过滤器规定,没有登录就跳转到登录页面,我现在就跳转到登录页面了,我也没问题。 |
两方面都没问题,但是现在问题来了,怎么解决呢。 |
1.18.3,解决方案
//解决子框架嵌套的问题 if (window != window.parent) { window.parent.location.reload(true); } |
1.19,信息发布基础的增删改查
1.19.1,基础的增删改查代码
<dl> <dt><a class="xxfb" href="${ctx }nsfw/info_listUI.action" target="mainFrame"><b></b>信息发布管理<s class="down"></s> </a></dt> </dl> |
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <%@include file="/common/header.jsp"%> <title>信息发布管理</title> <script type="text/javascript"> //全选、全反选 function doSelectAll(){ // jquery 1.6 前 //$("input[name=selectedRow]").attr("checked", $("#selAll").is(":checked")); //prop jquery 1.6+建议使用 $("input[name=selectedRow]").prop("checked", $("#selAll").is(":checked")); } //新增 function doAdd(){ document.forms[0].action = "${basePath}nsfw/info_addUI.action"; document.forms[0].submit(); } //编辑 function doEdit(id){ document.forms[0].action = "${basePath}nsfw/info_editUI.action?info.infoId=" + id; document.forms[0].submit(); } //删除 function doDelete(id){ document.forms[0].action = "${basePath}nsfw/info_delete.action?info.infoId=" + id; document.forms[0].submit(); } //批量删除 function doDeleteAll(){ document.forms[0].action = "${basePath}nsfw/info_deleteSelected.action"; document.forms[0].submit(); } //异步发布信息,信息的id及将要改成的信息状态 function doPublic(infoId, state){ //1、更新信息状态 $.ajax({ url:"${basePath}nsfw/info_publicInfo.action", data:{"info.infoId":infoId, "info.state":state}, type:"post", success: function(msg){ //2、更新状态栏、操作栏的显示值 if("更新状态成功" == msg){ if(state == 1){//说明信息状态已经被改成 发布,状态栏显示 发布,操作栏显示 停用 $("#show_"+infoId).html("发布"); $("#oper_"+infoId).html('<a href="javascript:doPublic(\''+infoId+'\',0)">停用</a>'); } else { $("#show_"+infoId).html("停用"); $("#oper_"+infoId).html('<a href="javascript:doPublic(\''+infoId+'\',1)">发布</a>'); } } else {alert("更新信息状态失败!");} }, error: function(){ alert("更新信息状态失败!"); } }); } </script> </head> <body class="rightBody"> <form name="form1" action="" method="post"> <div class="p_d_1"> <div class="p_d_1_1"> <div class="content_info"> <div class="c_crumbs"><div><b></b><strong>信息发布管理</strong></div> </div> <div class="search_art"> <li> 信息标题:<s:textfield name="info.title" cssClass="s_text" id="infoTitle" cssStyle="width:160px;"/> </li> <li><input type="button" class="s_button" value="搜 索" onclick="doSearch()"/></li> <li style="float:right;"> <input type="button" value="新增" class="s_button" onclick="doAdd()"/> <input type="button" value="删除" class="s_button" onclick="doDeleteAll()"/> </li> </div>
<div class="t_list" style="margin:0px; border:0px none;"> <table width="100%" border="0"> <tr class="t_tit"> <td width="30" align="center"><input type="checkbox" id="selAll" onclick="doSelectAll()" /></td> <td align="center">信息标题</td> <td width="120" align="center">信息分类</td> <td width="120" align="center">创建人</td> <td width="140" align="center">创建时间</td> <td width="80" align="center">状态</td> <td width="120" align="center">操作</td> </tr> <s:iterator value="infoList" status="st"> <tr <s:if test="#st.odd"> bgcolor="f8f8f8" </s:if> > <td align="center"><input type="checkbox" name="selectedRow" value="<s:property value='infoId'/>"/></td> <td align="center"><s:property value="title"/></td> <td align="center"> <s:property value="#infoTypeMap[type]"/> </td> <td align="center"><s:property value="creator"/></td> <td align="center"><s:date name="createTime" format="yyyy-MM-dd HH:mm"/></td> <td id="show_<s:property value='infoId'/>" align="center"><s:property value="state==1?'发布':'停用'"/></td> <td align="center"> <span id="oper_<s:property value='infoId'/>"> <s:if test="state==1"> <a href="javascript:doPublic('<s:property value='infoId'/>',0)">停用</a> </s:if><s:else> <a href="javascript:doPublic('<s:property value='infoId'/>',1)">发布</a> </s:else> </span> <a href="javascript:doEdit('<s:property value='infoId'/>')">编辑</a> <a href="javascript:doDelete('<s:property value='infoId'/>')">删除</a> </td> </tr> </s:iterator> </table> </div> </div> <div class="c_pate" style="margin-top: 5px;"> <table width="100%" class="pageDown" border="0" cellspacing="0" cellpadding="0"> <tr> <td align="right"> 总共1条记录,当前第 1 页,共 1 页 <a href="#">上一页</a> <a href="#">下一页</a> 到 <input type="text" style="width: 30px;" onkeypress="if(event.keyCode == 13){doGoPage(this.value);}" min="1" max="" value="1" /> </td> </tr> </table> </div>
</div> </div> </form>
</body> </html> |
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <%@include file="/common/header.jsp"%> <title>信息发布管理</title> <script type="text/javascript" charset="utf-8" src="${basePath }js/ueditor/ueditor.config.js"></script> <script type="text/javascript" charset="utf-8" src="${basePath }js/ueditor/ueditor.all.min.js"> </script> <script type="text/javascript" charset="utf-8" src="${basePath }js/ueditor/lang/zh-cn/zh-cn.js"></script>
<script> window.UEDITOR_HOME_URL = "${basePath }js/ueditor/"; var ue = UE.getEditor('editor'); </script> </head> <body class="rightBody"> <form id="form" name="form" action="${basePath }nsfw/info_add.action" method="post" enctype="multipart/form-data"> <div class="p_d_1"> <div class="p_d_1_1"> <div class="content_info"> <div class="c_crumbs"><div><b></b><strong>信息发布管理</strong> - 新增信息</div></div> <div class="tableH2">新增信息</div> <table id="baseInfo" width="100%" align="center" class="list" border="0" cellpadding="0" cellspacing="0" > <tr> <td class="tdBg" width="200px">信息分类:</td> <td><s:select name="info.type" list="#infoTypeMap"/></td> <td class="tdBg" width="200px">来源:</td> <td><s:textfield name="info.source"/></td> </tr> <tr> <td class="tdBg" width="200px">信息标题:</td> <td colspan="3"><s:textfield name="info.title" cssStyle="width:90%"/></td> </tr> <tr> <td class="tdBg" width="200px">信息内容:</td> <td colspan="3"><s:textarea id="editor" name="info.content" cssStyle="width:90%;height:160px;" /></td> </tr> <tr> <td class="tdBg" width="200px">备注:</td> <td colspan="3"><s:textarea name="info.memo" cols="90" rows="3"/></td> </tr> <tr> <td class="tdBg" width="200px">创建人:</td> <td> <s:property value="#session.SYS_USER.name"/> <s:hidden name="info.creator" value="%{#session.SYS_USER.name}"/> </td> <td class="tdBg" width="200px">创建时间:</td> <td> <s:date name="info.createTime" format="yyyy-MM-dd HH:mm"/> <s:hidden name="info.createTime"/> </td> </tr> </table> <!-- 默认信息状态为 发布 --> <s:hidden name="info.state" value="1"/> <div class="tc mt20"> <input type="submit" class="btnB2" value="保存" /> <input type="button" onclick="javascript:history.go(-1)" class="btnB2" value="返回" /> </div> </div></div></div> </form> </body> </html> |
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <%@include file="/common/header.jsp"%> <title>信息发布管理</title> <script type="text/javascript" charset="utf-8" src="${basePath }js/ueditor/ueditor.config.js"></script> <script type="text/javascript" charset="utf-8" src="${basePath }js/ueditor/ueditor.all.min.js"> </script> <script type="text/javascript" charset="utf-8" src="${basePath }js/ueditor/lang/zh-cn/zh-cn.js"></script>
<script> window.UEDITOR_HOME_URL = "${basePath }js/ueditor/"; var ue = UE.getEditor('editor'); </script>
</head> <body class="rightBody"> <form id="form" name="form" action="${basePath}nsfw/info_edit.action" method="post" enctype="multipart/form-data"> <div class="p_d_1"> <div class="p_d_1_1"> <div class="content_info"> <div class="c_crumbs"><div><b></b><strong>信息发布管理</strong> - 修改信息</div></div> <div class="tableH2">修改信息</div> <table id="baseInfo" width="100%" align="center" class="list" border="0" cellpadding="0" cellspacing="0" > <tr> <td class="tdBg" width="200px">信息分类:</td> <td><s:select name="info.type" list="#infoTypeMap"/></td> <td class="tdBg" width="200px">来源:</td> <td><s:textfield name="info.source"/></td> </tr> <tr> <td class="tdBg" width="200px">信息标题:</td> <td colspan="3"><s:textfield name="info.title" cssStyle="width:90%"/></td> </tr> <tr> <td class="tdBg" width="200px">信息内容:</td> <td colspan="3"><s:textarea id="editor" name="info.content" cssStyle="width:90%;height:160px;" /></td> </tr> <tr> <td class="tdBg" width="200px">备注:</td> <td colspan="3"><s:textarea name="info.memo" cols="90" rows="3"/></td> </tr> <tr> <td class="tdBg" width="200px">创建人:</td> <td> <s:property value="info.creator"/> <s:hidden name="info.creator"/> </td> <td class="tdBg" width="200px">创建时间:</td> <td> <s:date name="info.createTime" format="yyyy-MM-dd HH:mm"/> <s:hidden name="info.createTime"/> </td> </tr> </table> <s:hidden name="info.infoId"/> <s:hidden name="info.state"/> <div class="tc mt20"> <input type="submit" class="btnB2" value="保存" /> <input type="button" onclick="javascript:history.go(-1)" class="btnB2" value="返回" /> </div> </div></div></div> </form> </body> </html> |
<!-- 包含信息发布管理的struts配置文件 --> <include file="cn/itcast/nsfw/info/conf/info-struts.xml"></include> |
<package name="info-action" namespace="/nsfw" extends="struts-default"> <action name="info_*" class="cn.itcast.nsfw.info.action.InfoAction" method="{1}"> <result name="{1}">/WEB-INF/jsp/nsfw/info/{1}.jsp</result> <result name="list" type="redirectAction"> <param name="actionName">info_listUI</param> </result> </action> </package> |
<bean id="infoDao" class="cn.itcast.nsfw.info.dao.impl.InfoDaoImpl" parent="baseDao"></bean>
<!-- 扫描service --> <context:component-scan base-package="cn.itcast.nsfw.info.service.impl"></context:component-scan> </beans> |
public class Info implements Serializable {
private String infoId; private String type; private String source; private String title; private String content; private String memo; private String creator; private Timestamp createTime; private String state;
//状态 public static String INFO_STATE_PUBLIC = "1";//发布 public static String INFO_STATE_STOP = "0";//停用
//信息分类 public static String INFO_TYPE_TZGG = "tzgg"; public static String INFO_TYPE_ZCSD = "zcsd"; public static String INFO_TYPE_NSZD = "nszd"; public static Map<String, String> INFO_TYPE_MAP; static { INFO_TYPE_MAP = new HashMap<String, String>(); INFO_TYPE_MAP.put(INFO_TYPE_TZGG, "通知公告"); INFO_TYPE_MAP.put(INFO_TYPE_ZCSD, "政策速递"); INFO_TYPE_MAP.put(INFO_TYPE_NSZD, "纳税指导"); }
|
<class name="cn.itcast.nsfw.info.entity.Info" table="info"> <id name="infoId" type="java.lang.String"> <column name="info_id" length="32"/> <generator class="uuid.hex" /> </id> <property name="type" type="java.lang.String"> <column name="type" length="10" /> </property> <property name="source" type="java.lang.String"> <column name="source" length="50" /> </property> <property name="title" type="java.lang.String"> <column name="title" length="100" not-null="true" /> </property> <property name="content" type="text"> <column name="content" /> </property> <property name="memo" type="java.lang.String"> <column name="memo" length="200" /> </property> <property name="creator" type="java.lang.String"> <column name="creator" length="10" /> </property> <property name="createTime" type="java.sql.Timestamp"> <column name="create_time" length="19" /> </property> <property name="state" type="java.lang.String"> <column name="state" length="1" /> </property> </class> |
public class InfoAction extends BaseAction {
@Resource private InfoService infoService; private List<Info> infoList; private Info info; private String[] privilegeIds;
//列表页面 public String listUI() throws Exception{ //加载分类集合 ActionContext.getContext().getContextMap().put("infoTypeMap", Info.INFO_TYPE_MAP); try { infoList = infoService.findObjects(); } catch (Exception e) { throw new Exception(e.getMessage()); }
return "listUI"; } //跳转到新增页面 public String addUI(){ //加载分类集合 ActionContext.getContext().getContextMap().put("infoTypeMap", Info.INFO_TYPE_MAP); info = new Info(); info.setCreateTime(new Timestamp(new Date().getTime()));
return "addUI"; } //保存新增 public String add(){ try { if(info != null){ infoService.save(info); } } catch (Exception e) { e.printStackTrace(); } return "list"; } //跳转到编辑页面 public String editUI(){ //加载分类集合 ActionContext.getContext().getContextMap().put("infoTypeMap", Info.INFO_TYPE_MAP); if (info != null && info.getInfoId() != null) { info = infoService.findObjectById(info.getInfoId()); } return "editUI"; } //保存编辑 public String edit(){ try { if(info != null){ infoService.update(info); } } catch (Exception e) { e.printStackTrace(); } return "list"; } //删除 public String delete(){ if(info != null && info.getInfoId() != null){ infoService.delete(info.getInfoId()); } return "list"; } //批量删除 public String deleteSelected(){ if(selectedRow != null){ for(String id: selectedRow){ infoService.delete(id); } } return "list"; } //异步发布信息 public void publicInfo(){ try { if(info != null){ //1、更新信息状态 Info tem = infoService.findObjectById(info.getInfoId()); tem.setState(info.getState()); infoService.update(tem);
//2、输出更新结果 HttpServletResponse response = ServletActionContext.getResponse(); response.setContentType("text/html"); ServletOutputStream outputStream = response.getOutputStream(); outputStream.write("更新状态成功".getBytes("utf-8")); outputStream.close(); } } catch (Exception e) { e.printStackTrace(); } } public List<Info> getInfoList() { return infoList; } public void setInfoList(List<Info> infoList) { this.infoList = infoList; } public Info getInfo() { return info; } public void setInfo(Info info) { this.info = info; } public String[] getPrivilegeIds() { return privilegeIds; } public void setPrivilegeIds(String[] privilegeIds) { this.privilegeIds = privilegeIds; } |
public interface InfoService {
//新增 public void save(Info info); //更新 public void update(Info info); //根据id删除 public void delete(Serializable id); //根据id查找 public Info findObjectById(Serializable id); //查找列表 public List<Info> findObjects();
} |
@Service("infoService") public class InfoServiceImpl implements InfoService {
@Resource private InfoDao infoDao;
@Override public void save(Info info) { infoDao.save(info); }
@Override public void update(Info info) { infoDao.update(info); }
@Override public void delete(Serializable id) { infoDao.delete(id); } @Override public Info findObjectById(Serializable id) { return infoDao.findObjectById(id); } @Override public List<Info> findObjects() { return infoDao.findObjects(); } |
public interface InfoDao extends BaseDao<Info> {
} |
public class InfoDaoImpl extends BaseDaoImpl<Info> implements InfoDao {
} |
1.19.2,ueditor富文本编辑器的使用
<%@include file="/common/header.jsp"%> <title>信息发布管理</title> <script type="text/javascript" charset="utf-8" src="${basePath }js/ueditor/ueditor.config.js"></script> <script type="text/javascript" charset="utf-8" src="${basePath }js/ueditor/ueditor.all.min.js"> </script> <script type="text/javascript" charset="utf-8" src="${basePath }js/ueditor/lang/zh-cn/zh-cn.js"></script> <script> window.UEDITOR_HOME_URL = "${basePath }js/ueditor/"; var ue = UE.getEditor('editor'); </script> |
<tr> <td class="tdBg" width="200px">信息内容:</td> <td colspan="3"><s:textarea id="editor" name="info.content" cssStyle="width:90%;height:160px;" /></td> </tr> |
* 鉴于很多同学在使用编辑器的时候出现的种种路径问题,此处强烈建议大家使用"相对于网站根目录的相对路径"进行配置。 * "相对于网站根目录的相对路径"也就是以斜杠开头的形如"/myProject/ueditor/"这样的路径。 * 如果站点中有多个不在同一层级的页面需要实例化编辑器,且引用了同一UEditor的时候,此处的URL可能不适用于每个页面的编辑器。 * 因此,UEditor提供了针对不同页面的编辑器可单独配置的根路径,具体来说,在需要实例化编辑器的页面最顶部写上如下代码即可。当然,需要令此处的URL等于对应的配置。 * window.UEDITOR_HOME_URL = "/xxxx/xxxx/"; */ var URL = window.UEDITOR_HOME_URL || getUEBasePath(); |
, toolbars: [[ 'fullscreen', 'source', '|', 'undo', 'redo', '|', 'bold', 'italic', 'underline', 'fontborder', 'strikethrough', 'superscript', 'subscript', 'removeformat', 'formatmatch', 'autotypeset', 'blockquote', 'pasteplain', '|', 'forecolor', 'backcolor', 'insertorderedlist', 'insertunorderedlist', 'selectall', 'cleardoc', '|', 'rowspacingtop', 'rowspacingbottom', 'lineheight', '|', 'customstyle', 'paragraph', 'fontfamily', 'fontsize', '|', 'directionalityltr', 'directionalityrtl', 'indent', '|', 'justifyleft', 'justifycenter', 'justifyright', 'justifyjustify', '|', 'touppercase', 'tolowercase', '|', 'link', 'unlink', 'anchor', '|', 'imagenone', 'imageleft', 'imageright', 'imagecenter', '|', 'simpleupload', 'insertimage', 'emotion', 'scrawl', 'map', 'gmap', 'insertframe', 'insertcode', 'webapp', 'pagebreak', 'template', 'background', '|', 'horizontal', 'date', 'time', 'spechars', 'snapscreen', 'wordimage', '|', 'inserttable', 'deletetable', 'insertparagraphbeforetable', 'insertrow', 'deleterow', 'insertcol', 'deletecol', 'mergecells', 'mergeright', 'mergedown', 'splittocells', 'splittorows', 'splittocols', 'charts', '|', 'print', 'preview', 'searchreplace', 'help', 'drafts' ]] |
上传图片需要注意的地方 |
上传图片首先要加载jar包,,在js的bin包下。 |
"imageUrlPrefix": "http://localhost:8080/itcastTax", /* 图片访问路径前缀 */ "imagePathFormat": "/upload/ueditor/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ |
1.19.3,异步信息发布(发布与停用切换)
//异步发布信息,信息的id及将要改成的信息状态 function doPublic(infoId, state){ //1、更新信息状态 $.ajax({ url:"${basePath}nsfw/info_publicInfo.action", data:{"info.infoId":infoId, "info.state":state}, type:"post", success: function(msg){ //2、更新状态栏、操作栏的显示值 if("更新状态成功" == msg){ if(state == 1){//说明信息状态已经被改成 发布,状态栏显示 发布,操作栏显示 停用 $("#show_"+infoId).html("发布"); $("#oper_"+infoId).html('<a href="javascript:doPublic(\''+infoId+'\',0)">停用</a>'); } else { $("#show_"+infoId).html("停用"); $("#oper_"+infoId).html('<a href="javascript:doPublic(\''+infoId+'\',1)">发布</a>'); } } else {alert("更新信息状态失败!");} }, error: function(){ alert("更新信息状态失败!"); } }); |
<td id="show_<s:property value='infoId'/>" align="center"><s:property value="state==1?'发布':'停用'"/></td> <td align="center"> <span id="oper_<s:property value='infoId'/>"> <s:if test="state==1"> <a href="javascript:doPublic('<s:property value='infoId'/>',0)">停用</a> </s:if><s:else> <a href="javascript:doPublic('<s:property value='infoId'/>',1)">发布</a> </s:else> </span> <a href="javascript:doEdit('<s:property value='infoId'/>')">编辑</a> <a href="javascript:doDelete('<s:property value='infoId'/>')">删除</a> </td> |
//异步发布信息 public void publicInfo(){ try { if(info != null){ //1、更新信息状态 Info tem = infoService.findObjectById(info.getInfoId()); tem.setState(info.getState()); infoService.update(tem);
//2、输出更新结果 HttpServletResponse response = ServletActionContext.getResponse(); response.setContentType("text/html"); ServletOutputStream outputStream = response.getOutputStream(); outputStream.write("更新状态成功".getBytes("utf-8")); outputStream.close(); } } catch (Exception e) { e.printStackTrace(); } } |
1.20,抽取basesevice
1.20.1,代码
public interface InfoService extends BaseService<Info>{ } |
public class BaseServiceImpl<T> implements BaseService<T> {
private BaseDao<T> baseDao;
public void setBaseDao(BaseDao<T> baseDao) { this.baseDao = baseDao; }
@Override public void save(T entity) { baseDao.save(entity); }
@Override public void update(T entity) { baseDao.update(entity); }
@Override public void delete(Serializable id) { baseDao.delete(id); }
@Override public T findObjectById(Serializable id) { return baseDao.findObjectById(id); }
@Override public List<T> findObjects() { return baseDao.findObjects(); }
} |
public interface InfoService extends BaseService<Info>{ } |
@Service("infoService") public class InfoServiceImpl extends BaseServiceImpl<Info> implements InfoService { private InfoDao infoDao; @Resource public void setInfoDao(InfoDao infoDao) { super.setBaseDao(infoDao); this.infoDao = infoDao; } } |
1.21,逆向工程(略)
1.21.1,步骤
1、利用power designer 设计概念、物理 2、根据pdm的数据库表创建语句创建数据库表 3、添加hibernate能力,更加生成的数据库表逆向生成实体及其映射文件 |
1.21.2myeclipse和数据库的链接
1.21.3,在myeclipse中添加hibernate支持
1.21.4,在myeclipse中去除hibernate的逆向工程支持
|
1.22,按条件查询
1.22.1,没有工具类的按条件查询
<li><input type="button" class="s_button" value="搜 索" onclick="doSearch()"/></li> |
//按条件查询 function doSearch(){ document.forms[0].action = "${basePath}nsfw/info_listUI.action"; document.forms[0].submit(); } |
// 条件查询实体列表 public List<T> findObjects(String hql, List<Object> parameters); |
@Override public List<T> findObjects(String hql, List<Object> parameters) { return baseDao.findObjects(hql, parameters); } |
// 条件查询实体列表 public List<T> findObjects(String hql, List<Object> parameters); |
@Override public List<T> findObjects(String hql, List<Object> parameters) { Query query = getSession().createQuery(hql); if (parameters != null) { for (int i = 0; i < parameters.size(); i++) { query.setParameter(i, parameters.get(i)); } } return query.list(); } |
1.22.2,为什么在listui的方法中可以通用查询全部和根据条件查询(以新增页面跳转为例)
// 列表页面 public String listUI() throws Exception { // 加载分类集合 ActionContext.getContext().getContextMap() .put("infoTypeMap", Info.INFO_TYPE_MAP); System.out.println("1"+info); QueryHelper queryHelper = new QueryHelper(Info.class, "i"); System.out.println("2"+info); try { if (info != null) { if (StringUtils.isNotBlank(info.getTitle())) { queryHelper.addCondition("i.title like ?", "%" + info.getTitle() + "%"); } } // 根据创建时间降序排序 queryHelper.addOrderByProperty("i.createTime", QueryHelper.ORDER_BY_DESC); infoList = infoService.findObjects(queryHelper); } catch (Exception e) { throw new Exception(e.getMessage()); }
return "listUI"; } // 保存新增 public String add() { try { if (info != null) { System.out.println("3"+info.getTitle()); infoService.save(info); } } catch (Exception e) { e.printStackTrace(); } System.out.println("4"+info.getTitle()); return "list"; } |
1.22.3,有工具类的按条件查询
|
<li><input type="button" class="s_button" value="搜 索" onclick="doSearch()"/></li> |
//按条件查询 function doSearch(){ document.forms[0].action = "${basePath}nsfw/info_listUI.action"; document.forms[0].submit(); } |
// 列表页面 public String listUI() throws Exception { // 加载分类集合 ActionContext.getContext().getContextMap() .put("infoTypeMap", Info.INFO_TYPE_MAP); QueryHelper queryHelper = new QueryHelper(Info.class, "i"); try { if (info != null) { if (StringUtils.isNotBlank(info.getTitle())) { queryHelper.addCondition("i.title like ?", "%" + info.getTitle() + "%"); } } // 根据创建时间降序排序 queryHelper.addOrderByProperty("i.createTime", QueryHelper.ORDER_BY_DESC); infoList = infoService.findObjects(queryHelper); } catch (Exception e) { throw new Exception(e.getMessage()); }
return "listUI"; } |
FROM Info WHERE title like ? and state = ? order by createTime,state
条件查询(QueryHelper):
1、查询条件语句hql: from 子句:必定出现;而且只出现一次 where 子句:可选;但关键字where 出现一次;可添加多个查询条件 order by子句:可选;但关键字order by 出现一次;可添加多个排序属性
2、查询条件值集合: 出现时机:在添加查询条件的时候,?对应的查询条件值 |
public class QueryHelper { //from子句 private String fromClause = ""; //where子句 private String whereClause = ""; //order by子句 private String orderByClause = ""; private List<Object> parameters; //排序顺序 public static String ORDER_BY_DESC = "DESC";//降序 public static String ORDER_BY_ASC = "ASC";//升序
/** * 构造from 子句 * @param clazz 实体类 * @param alias 实体类对应的别名 */ public QueryHelper(Class clazz, String alias){ fromClause = "FROM " + clazz.getSimpleName() + " " + alias; }
/** * 构造where子句 * @param condition 查询条件语句;例如:i.title like ? * @param params 查询条件语句中?对应的查询条件值;例如: %标题% */ public void addCondition(String condition, Object... params){ if (whereClause.length() > 1) {//非第一个查询条件 whereClause += " AND " + condition; } else {//第一个查询条件 whereClause += " WHERE " + condition; }
//设置查询条件值到查询条件值集合中 if(parameters == null){ parameters = new ArrayList<Object>(); } if(params != null){ for(Object param: params){ parameters.add(param); } } }
/** * 构造order by子句 * @param property 排序属性,如:i.createTime * @param order 排序顺序,如:DESC 或者 ASC */ public void addOrderByProperty(String property, String order){ if (orderByClause.length() > 1) {//非第一个排序属性 orderByClause += "," + property + " " + order; } else {//第一个排序属性 orderByClause = " ORDER BY " + property + " " + order; } }
//查询hql语句 public String getQueryListHql(){ return fromClause + whereClause + orderByClause; }
//查询统计数的hql语句 public String getQueryCountHql(){ return "SELECT COUNT(*) " + fromClause + whereClause; }
//查询hql语句中?对应的查询条件值集合 public List<Object> getParameters(){ return parameters; } } |
// 条件查询实体列表--查询助手queryHelper public List<T> findObjects(QueryHelper queryHelper); |
@Override public List<T> findObjects(QueryHelper queryHelper) { return baseDao.findObjects(queryHelper); } |
// 条件查询实体列表--查询助手queryHelper public List<T> findObjects(QueryHelper queryHelper); |
@Override public List<T> findObjects(QueryHelper queryHelper) { Query query = getSession().createQuery(queryHelper.getQueryListHql()); // //FROM info i where i.title like ? order by i.createTime DESC; List<Object> parameters = queryHelper.getParameters(); if (parameters != null) { for (int i = 0; i < parameters.size(); i++) { query.setParameter(i, parameters.get(i)); } } //query.setParameter(0, "%" + info.getTitle() + "%"); return query.list(); } |
1.22.4,解决细节问题一,删除时查询条件丢失问题
原因分析: |
// 删除 public String delete() { if (info != null && info.getInfoId() != null) { infoService.delete(info.getInfoId()); } return "list"; } |
<struts> <package name="info-action" namespace="/nsfw" extends="struts-default"> <action name="info_*" class="cn.itcast.nsfw.info.action.InfoAction" method="{1}"> <result name="{1}">/WEB-INF/jsp/nsfw/info/{1}.jsp</result> <result name="list" type="redirectAction"> <param name="actionName">info_listUI</param> </result>
</action> |
// 列表页面 public String listUI() throws Exception { // 加载分类集合 ActionContext.getContext().getContextMap() .put("infoTypeMap", Info.INFO_TYPE_MAP); QueryHelper queryHelper = new QueryHelper(Info.class, "i"); try { if (info != null) { if (StringUtils.isNotBlank(info.getTitle())) { queryHelper.addCondition("i.title like ?", "%" + info.getTitle() + "%"); } } // 根据创建时间降序排序 queryHelper.addOrderByProperty("i.createTime", QueryHelper.ORDER_BY_DESC); infoList = infoService.findObjects(queryHelper); } catch (Exception e) { throw new Exception(e.getMessage()); }
return "listUI"; } |
解决方法:struts> <package name="info-action" namespace="/nsfw" extends="struts-default"> <action name="info_*" class="cn.itcast.nsfw.info.action.InfoAction" method="{1}"> <result name="{1}">/WEB-INF/jsp/nsfw/info/{1}.jsp</result> <result name="list" type="redirectAction"> <param name="actionName">info_listUI</param> <param name="info.title">${info.title}</param> </result> |
新的问题出现了(注意在自己的电脑上没有出现,可能是由于浏览器的问题) |
解决方法: <action name="info_*" class="cn.itcast.nsfw.info.action.InfoAction" method="{1}"> <result name="{1}">/WEB-INF/jsp/nsfw/info/{1}.jsp</result> <result name="list" type="redirectAction"> <param name="actionName">info_listUI</param> <param name="info.title">${info.title}</param> <param name="encode">true</param> </result> |
新的问题 |
解决方案: public String listUI() throws Exception { // 加载分类集合 ActionContext.getContext().getContextMap() .put("infoTypeMap", Info.INFO_TYPE_MAP); QueryHelper queryHelper = new QueryHelper(Info.class, "i"); try { if (info != null) { if (StringUtils.isNotBlank(info.getTitle())) { info.setTitle(URLDecoder.decode(info.getTitle(), "utf-8")); queryHelper.addCondition("i.title like ?", "%" + info.getTitle() + "%"); } } // 根据创建时间降序排序 queryHelper.addOrderByProperty("i.createTime", QueryHelper.ORDER_BY_DESC); infoList = infoService.findObjects(queryHelper); } catch (Exception e) { throw new Exception(e.getMessage()); }
return "listUI"; } |
1.22.5,解决细节问题二:新增或者编辑的时候查询条件变成了新增的条件
原因分析: // 保存新增 // 跳转到新增页面 public String addUI() { // 加载分类集合
ActionContext.getContext().getContextMap() .put("infoTypeMap", Info.INFO_TYPE_MAP); strTitle = info.getTitle(); info = new Info(); info.setCreateTime(new Timestamp(new Date().getTime()));
return "addUI"; } |
<package name="info-action" namespace="/nsfw" extends="struts-default"> <action name="info_*" class="cn.itcast.nsfw.info.action.InfoAction" method="{1}"> <result name="{1}">/WEB-INF/jsp/nsfw/info/{1}.jsp</result> <result name="list" type="redirectAction"> <param name="actionName">info_listUI</param> <param name="info.title">${info.title}</param> <param name="encode">true</param> </result>
</action> |
// 列表页面 public String listUI() throws Exception { // 加载分类集合 ActionContext.getContext().getContextMap() .put("infoTypeMap", Info.INFO_TYPE_MAP); QueryHelper queryHelper = new QueryHelper(Info.class, "i"); try { if (info != null) { if (StringUtils.isNotBlank(info.getTitle())) { info.setTitle(URLDecoder.decode(info.getTitle(), "utf-8")); queryHelper.addCondition("i.title like ?", "%" + info.getTitle() + "%"); } } // 根据创建时间降序排序 queryHelper.addOrderByProperty("i.createTime", QueryHelper.ORDER_BY_DESC); infoList = infoService.findObjects(queryHelper); } catch (Exception e) { throw new Exception(e.getMessage()); }
return "listUI"; } |
解决方法: private String strTitle; // 跳转到新增页面 public String addUI() { // 加载分类集合
ActionContext.getContext().getContextMap() .put("infoTypeMap", Info.INFO_TYPE_MAP); strTitle = info.getTitle(); info = new Info(); info.setCreateTime(new Timestamp(new Date().getTime()));
return "addUI"; } |
<s:hidden name="strTitle"/> |
<struts> <package name="info-action" namespace="/nsfw" extends="struts-default"> <action name="info_*" class="cn.itcast.nsfw.info.action.InfoAction" method="{1}"> <result name="{1}">/WEB-INF/jsp/nsfw/info/{1}.jsp</result> <result name="list" type="redirectAction"> <param name="actionName">info_listUI</param> <param name="info.title">${strTitle}</param> <param name="encode">true</param> </result>
</action> |
编辑页面也是同样的思路 |
1.23,分页
1.23.1,分页分析
总共1条记录,当前第 1 页,共 1 页 上一页 下一页 到 总记录数 当前页号 总页数 页大小 列表记录
共6条记录,每页3条,共2页
总页数 = 总记录数/页大小
共7条记录,每页3条,共3页
tem = 总记录数/页大小;
总页数 = (总记录数%页大小==0)?tem:(tem+1)
页号;当总记录数为0时,页号为0? |
public class PageResult {
//总记录数 private long totalCount; //当前页号 private int pageNo; //总页数 private int totalPageCount; //页大小 private int pageSize; //列表记录 private List items;
//计算总页数 public PageResult(long totalCount, int pageNo, int pageSize, List items) { this.items = items==null?new ArrayList():items; this.totalCount = totalCount; this.pageSize = pageSize; if(totalCount != 0){ //计算总页数 int tem = (int)totalCount/pageSize; this.totalPageCount = (totalCount%pageSize==0)?tem:(tem+1); this.pageNo = pageNo; } else { this.pageNo = 0; } } |
1.23.1,分页实现代码
<%@ page contentType="text/html;charset=UTF-8" language="java"%> <html> <head> <%@include file="/common/header.jsp"%> <title>信息发布管理</title> <script type="text/javascript"> //全选、全反选 function doSelectAll() { // jquery 1.6 前 //$("input[name=selectedRow]").attr("checked", $("#selAll").is(":checked")); //prop jquery 1.6+建议使用 $("input[name=selectedRow]").prop("checked", $("#selAll").is(":checked")); } //新增 function doAdd() { document.forms[0].action = "${basePath}nsfw/info_addUI.action"; document.forms[0].submit(); } //编辑 function doEdit(id) { document.forms[0].action = "${basePath}nsfw/info_editUI.action?info.infoId=" + id; document.forms[0].submit(); } //删除 function doDelete(id) { document.forms[0].action = "${basePath}nsfw/info_delete.action?info.infoId=" + id; document.forms[0].submit(); } //批量删除 function doDeleteAll() { document.forms[0].action = "${basePath}nsfw/info_deleteSelected.action"; document.forms[0].submit(); } //按条件查询 function doSearch() { document.forms[0].action = "${basePath}nsfw/info_listUI.action"; document.forms[0].submit(); } //异步发布信息,信息的id及将要改成的信息状态 function doPublic(infoId, state) { //1、更新信息状态 $.ajax({ url : "${basePath}nsfw/info_publicInfo.action", data : { "info.infoId" : infoId, "info.state" : state }, type : "post", success : function(msg) { //2、更新状态栏、操作栏的显示值 if ("更新状态成功" == msg) { if (state == 1) {//说明信息状态已经被改成 发布,状态栏显示 发布,操作栏显示 停用 $("#show_" + infoId).html("发布"); $("#oper_" + infoId).html( '<a href="javascript:doPublic(\'' + infoId + '\',0)">停用</a>'); } else { $("#show_" + infoId).html("停用"); $("#oper_" + infoId).html( '<a href="javascript:doPublic(\'' + infoId + '\',1)">发布</a>'); } } else { alert("更新信息状态失败!"); } }, error : function() { alert("更新信息状态失败!"); } }); } </script> </head> <body class="rightBody"> <form name="form1" action="" method="post"> <div class="p_d_1"> <div class="p_d_1_1"> <div class="content_info"> <div class="c_crumbs"> <div> <b></b><strong>信息发布管理</strong> </div> </div> <div class="search_art"> <li>信息标题:<s:textfield name="info.title" cssClass="s_text" id="infoTitle" cssStyle="width:160px;" /></li> <li><input type="button" class="s_button" value="搜 索" onclick="doSearch()" /> </li> <li style="float:right;"><input type="button" value="新增" class="s_button" onclick="doAdd()" /> <input type="button" value="删除" class="s_button" onclick="doDeleteAll()" /> </li> </div>
<div class="t_list" style="margin:0px; border:0px none;"> <table width="100%" border="0"> <tr class="t_tit"> <td width="30" align="center"><input type="checkbox" id="selAll" onclick="doSelectAll()" /> </td> <td align="center">信息标题</td> <td width="120" align="center">信息分类</td> <td width="120" align="center">创建人</td> <td width="140" align="center">创建时间</td> <td width="80" align="center">状态</td> <td width="120" align="center">操作</td> </tr> <s:iterator value="pageResult.items" status="st"> <tr <s:if test="#st.odd"> bgcolor="f8f8f8" </s:if>> <td align="center"><input type="checkbox" name="selectedRow" value="<s:property value='infoId'/>" /> </td> <td align="center"><s:property value="title" /> </td> <td align="center"><s:property value="#infoTypeMap[type]" /> </td> <td align="center"><s:property value="creator" /> </td> <td align="center"><s:date name="createTime" format="yyyy-MM-dd HH:mm" /> </td> <td id="show_<s:property value='infoId'/>" align="center"><s:property value="state==1?'发布':'停用'" /> </td> <td align="center"><span id="oper_<s:property value='infoId'/>"> <s:if test="state==1"> <a href="javascript:doPublic('<s:property value='infoId'/>',0)">停用</a> </s:if> <s:else> <a href="javascript:doPublic('<s:property value='infoId'/>',1)">发布</a> </s:else> </span> <a href="javascript:doEdit('<s:property value='infoId'/>')">编辑</a> <a href="javascript:doDelete('<s:property value='infoId'/>')">删除</a> </td> </tr> </s:iterator> </table> </div> </div> <div class="c_pate" style="margin-top: 5px;"> <s:if test="pageResult.totalCount > 0"> <table width="100%" class="pageDown" border="0" cellspacing="0" cellpadding="0"> <tr> <td align="right">总共 <s:property value="pageResult.totalCount" /> 条记录,当前第 <s:property value="pageResult.pageNo" /> 页, 共 <s:property value="pageResult.totalPageCount" /> 页 <s:if test="pageResult.pageNo > 1"> <a href="javascript:doGoPage(<s:property value='pageResult.pageNo-1'/>)">上一页</a> </s:if> <s:if test="pageResult.pageNo < pageResult.totalPageCount"> <a href="javascript:doGoPage(<s:property value='pageResult.pageNo+1'/>)">下一页</a> </s:if> 到 <input id="pageNo" name="pageNo" type="text" style="width: 30px;" onkeypress="if(event.keyCode == 13){doGoPage(this.value);}" min="1" max="" value="<s:property value='pageResult.pageNo'/>" /> </td> </tr> </table> </s:if> <s:else>暂无数据!</s:else> </div> <script type="text/javascript"> //翻页 function doGoPage(pageNo) { document.getElementById("pageNo").value = pageNo; document.forms[0].action = "${basePath}nsfw/info_listUI.action"; document.forms[0].submit(); } </script> </div> </div> </form>
</body> </html> |
protected PageResult pageResult; private int pageNo; private int pageSize;
// 列表页面 public String listUI() throws Exception { // 加载分类集合 ActionContext.getContext().getContextMap() .put("infoTypeMap", Info.INFO_TYPE_MAP); QueryHelper queryHelper = new QueryHelper(Info.class, "i");
try { if (info != null) { if (StringUtils.isNotBlank(info.getTitle())) { info.setTitle(URLDecoder.decode(info.getTitle(), "utf-8")); queryHelper.addCondition("i.title like ?", "%" + info.getTitle() + "%"); } } // 根据创建时间降序排序 queryHelper.addOrderByProperty("i.createTime", QueryHelper.ORDER_BY_DESC); pageResult = infoService.getPageResult(queryHelper, getPageNo(), getPageSize()); } catch (Exception e) { throw new Exception(e.getMessage()); }
return "listUI"; } public int getPageSize() { if(pageSize < 1) pageSize =2; return pageSize; } |
// 分页条件查询实体列表--查询助手queryHelper public PageResult getPageResult(QueryHelper queryHelper, int pageNo, int pageSize); |
@Override public PageResult getPageResult(QueryHelper queryHelper, int pageNo, int pageSize) { return baseDao.getPageResult(queryHelper, pageNo, pageSize); } |
// 分页条件查询实体列表--查询助手queryHelper public PageResult getPageResult(QueryHelper queryHelper, int pageNo, int pageSize); |
@Override public PageResult getPageResult(QueryHelper queryHelper, int pageNo, int pageSize) { Query query = getSession().createQuery(queryHelper.getQueryListHql()); List<Object> parameters = queryHelper.getParameters(); if (parameters != null) { for (int i = 0; i < parameters.size(); i++) { query.setParameter(i, parameters.get(i)); } } if (pageNo < 1) pageNo = 1;
query.setFirstResult((pageNo - 1) * pageSize);// 设置数据起始索引号 query.setMaxResults(pageSize); List items = query.list(); // 获取总记录数 Query queryCount = getSession().createQuery( queryHelper.getQueryCountHql()); if (parameters != null) { for (int i = 0; i < parameters.size(); i++) { queryCount.setParameter(i, parameters.get(i)); } } long totalCount = (Long) queryCount.uniqueResult();
return new PageResult(totalCount, pageNo, pageSize, items); } |
//查询统计数的hql语句 public String getQueryCountHql(){ return "SELECT COUNT(*) " + fromClause + whereClause; } //查询hql语句中?对应的查询条件值集合 public List<Object> getParameters(){ return parameters; } |
1.23.3,解决编辑的时候页面跳转的问题
解决方法:
<!-- 暂存查询条件值 --> <s:hidden name="strTitle"/> <s:hidden name="pageNo"/> <s:hidden name="info.infoId"/> <s:hidden name="info.state"/> |
<struts> <package name="info-action" namespace="/nsfw" extends="struts-default"> <action name="info_*" class="cn.itcast.nsfw.info.action.InfoAction" method="{1}"> <result name="{1}">/WEB-INF/jsp/nsfw/info/{1}.jsp</result> <result name="list" type="redirectAction"> <param name="actionName">info_listUI</param> <param name="pageNo">${pageNo}</param> <param name="info.title">${strTitle}</param> <param name="encode">true</param> </result>
</action> |
1.23.4,点击搜索后重置页号
function doSearch() { //重置页号 $("#pageNo").val(1); document.forms[0].action = "${basePath}nsfw/info_listUI.action"; document.forms[0].submit(); } |
1.23.5分页的抽取
protected PageResult pageResult; private int pageNo; private int pageSize; //默认页大小 public static int DEFAULT_PAGE_SIZE = 3; public PageResult getPageResult() { return pageResult; } public void setPageResult(PageResult pageResult) { this.pageResult = pageResult; } public int getPageNo() { return pageNo; } public void setPageNo(int pageNo) { this.pageNo = pageNo; } public int getPageSize() { if(pageSize < 1) pageSize = DEFAULT_PAGE_SIZE; return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } |
这个页面就可以把以前的删掉了。 protected PageResult pageResult; private int pageNo; private int pageSize; 这些就可以删掉了。 |
前台的抽取
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <div class="c_pate" style="margin-top: 5px;"> <s:if test="pageResult.totalCount > 0"> <table width="100%" class="pageDown" border="0" cellspacing="0" cellpadding="0"> <tr> <td align="right"> 总共 <s:property value="pageResult.totalCount"/> 条记录,当前第 <s:property value="pageResult.pageNo"/> 页, 共 <s:property value="pageResult.totalPageCount"/> 页 <s:if test="pageResult.pageNo > 1"> <a href="javascript:doGoPage(<s:property value='pageResult.pageNo-1'/>)">上一页</a> </s:if> <s:if test="pageResult.pageNo < pageResult.totalPageCount"> <a href="javascript:doGoPage(<s:property value='pageResult.pageNo+1'/>)">下一页</a> </s:if> 到 <input id="pageNo" name="pageNo" type="text" style="width: 30px;" onkeypress="if(event.keyCode == 13){doGoPage(this.value);}" min="1" max="" value="<s:property value='pageResult.pageNo'/>" /> </td> </tr> </table> </s:if><s:else>暂无数据!</s:else> </div> <script type="text/javascript"> //翻页 function doGoPage(pageNo){ document.getElementById("pageNo").value = pageNo; document.forms[0].action=list_url; document.forms[0].submit(); } </script> |
var list_url = "${basePath}nsfw/info_listUI.action"; //搜索 function doSearch() { //搜索重置页面 $("#pageNo").val(1); document.forms[0].action = list_url; document.forms[0].submit(); } |
</div> </div> <jsp:include page="/common/pageNavigator.jsp" /> </div> </div> </form> |
1.24,我要投诉(受理投诉)
1.24.1,基础页面显示
public class Complain implements java.io.Serializable {
// Fields
private String compId; private String compCompany; private String compName; private String compMobile; private Boolean isNm; private Timestamp compTime; private String compTitle; private String toCompName; private String toCompDept; private String compContent; private String state; private Set complainReplies = new HashSet(0);
//状态 public static String COMPLAIN_STATE_UNDONE = "0"; public static String COMPLAIN_STATE_DONE = "1"; public static String COMPLAIN_STATE_INVALID = "2"; public static Map<String, String> COMPLAIN_STATE_MAP; static { COMPLAIN_STATE_MAP = new HashMap<String, String>(); COMPLAIN_STATE_MAP.put(COMPLAIN_STATE_UNDONE, "待受理"); COMPLAIN_STATE_MAP.put(COMPLAIN_STATE_DONE, "已受理"); COMPLAIN_STATE_MAP.put(COMPLAIN_STATE_INVALID, "已失效"); } |
public class ComplainReply implements java.io.Serializable { // Fields private String replyId; private Complain complain; private String replyer; private String replyDept; private Timestamp replyTime; private String replyContent; |
<script type="text/javascript"> var list_url = "${basePath}nsfw/complain_listUI.action"; //搜索 function doSearch(){ //重置页号 $("#pageNo").val(1); document.forms[0].action = list_url; document.forms[0].submit(); } </script> </head> <body class="rightBody"> <form name="form1" action="" method="post"> <div class="p_d_1"> <div class="p_d_1_1"> <div class="content_info"> <div class="c_crumbs"><div><b></b><strong>投诉受理管理</strong></div> </div> <div class="search_art"> <li> 投诉标题:<s:textfield name="complain.compTitle" cssClass="s_text" cssStyle="width:160px;"/> </li> <li> 投诉时间:<s:textfield id="startTime" name="startTime" cssClass="s_text" cssStyle="width:160px;" readonly="true" onfocus="WdatePicker({'skin':'whyGreen','dateFmt':'yyyy-MM-dd HH:mm'});"/> - <s:textfield id="endTime" name="endTime" cssClass="s_text" cssStyle="width:160px;" readonly="true" onfocus="WdatePicker({'skin':'whyGreen','dateFmt':'yyyy-MM-dd HH:mm'});"/> </li> <li> 状态:<s:select name="complain.state" list="#complainStateMap" headerKey="" headerValue="全部"/> </li> <li><input type="button" class="s_button" value="搜 索" onclick="doSearch()"/></li> <li style="float:right;"> <input type="button" value="统计" class="s_button" onclick="doAnnualStatistic()"/> </li>
</div>
<div class="t_list" style="margin:0px; border:0px none;"> <table width="100%" border="0"> <tr class="t_tit"> <td align="center">投诉标题</td> <td width="120" align="center">被投诉部门</td> <td width="120" align="center">被投诉人</td> <td width="140" align="center">投诉时间</td> <td width="100" align="center">受理状态</td> <td width="100" align="center">操作</td> </tr> <s:iterator value="pageResult.items" status="st"> <tr <s:if test="#st.odd"> bgcolor="f8f8f8" </s:if> > <td align="center"><s:property value="compTitle"/></td> <td align="center"><s:property value="toCompDept"/></td> <td align="center"><s:property value="toCompName"/></td> <td align="center"><s:date name="compTime" format="yyyy-MM-dd HH:mm"/></td> <td align="center"><s:property value="#complainStateMap[state]"/></td> <td align="center"> <a href="javascript:doDeal('<s:property value='compId'/>')">受理</a> </td> </tr> </s:iterator> </table> </div> </div>
<jsp:include page="/common/pageNavigator.jsp"/>
</div> </div> </form> |
<struts> <package name="complain-action" namespace="/nsfw" extends="struts-default"> <action name="complain_*" class="cn.itcast.nsfw.complain.action.ComplainAction" method="{1}"> <result name="{1}">/WEB-INF/jsp/nsfw/complain/{1}.jsp</result> <result name="list" type="redirectAction"> <param name="actionName">complain_listUI</param> <param name="complain.name">${strName}</param> <param name="encode">true</param> </result>
</action> </package> |
public class ComplainAction extends BaseAction1 {
@Resource private ComplainService complainService; private Complain complain; //列表 public String listUI(){ //加载状态集合 ActionContext.getContext().getContextMap().put("complainStateMap", Complain.COMPLAIN_STATE_MAP); QueryHelper queryHelper = new QueryHelper(Complain.class, "c"); pageResult = complainService.getPageResult(queryHelper, getPageNo(), getPageSize());
return "listUI"; } public Complain getComplain() { return complain; } public void setComplain(Complain complain) { this.complain = complain; } |
<bean id="complainDao" class="cn.itcast.nsfw.complain.dao.impl.ComplainDaoImpl" parent="baseDao"></bean>
<!-- 扫描service --> <context:component-scan base-package="cn.itcast.nsfw.complain.service.impl"></context:component-scan> </beans> |
@Service("complainService") public class ComplainServiceImpl extends BaseServiceImpl<Complain> implements ComplainService {
private ComplainDao complainDao;
@Resource public void setComplainDao(ComplainDao complainDao) { super.setBaseDao(complainDao); this.complainDao = complainDao; } |
public class ComplainDaoImpl extends BaseDaoImpl<Complain> implements ComplainDao {
} |
1.24.2,解决多条件查询问题,时间是间断的。
<li> 投诉时间:<s:textfield id="startTime" name="startTime" cssClass="s_text" cssStyle="width:160px;" readonly="true" onfocus="WdatePicker({'skin':'whyGreen','dateFmt':'yyyy-MM-dd HH:mm'});"/> - <s:textfield id="endTime" name="endTime" cssClass="s_text" cssStyle="width:160px;" readonly="true" onfocus="WdatePicker({'skin':'whyGreen','dateFmt':'yyyy-MM-dd HH:mm'});"/> </li> 状态:<s:select name="complain.state" list="#complainStateMap" headerKey="" headerValue="全部"/> |
private Complain complain; private String startTime; private String endTime; //列表 public String listUI(){ //加载状态集合 ActionContext.getContext().getContextMap().put("complainStateMap", Complain.COMPLAIN_STATE_MAP); try { QueryHelper queryHelper = new QueryHelper(Complain.class, "c"); if(StringUtils.isNotBlank(startTime)){//查询开始时间之后的投诉数据 startTime = URLDecoder.decode(startTime, "utf-8"); queryHelper.addCondition("c.compTime >= ?", DateUtils.parseDate(startTime+":00", "yyyy-MM-dd HH:mm:ss")); } if(StringUtils.isNotBlank(endTime)){//查询结束时间之前的投诉数据 endTime = URLDecoder.decode(endTime, "utf-8"); queryHelper.addCondition("c.compTime <= ?", DateUtils.parseDate(endTime+":59", "yyyy-MM-dd HH:mm:ss")); } if(complain != null){ if(StringUtils.isNotBlank(complain.getState())){ queryHelper.addCondition("c.state=?", complain.getState()); } if(StringUtils.isNotBlank(complain.getCompTitle())){ complain.setCompTitle(URLDecoder.decode(complain.getCompTitle(), "utf-8")); queryHelper.addCondition("c.compTitle like ?", "%" + complain.getCompTitle() + "%"); } } //安装状态升序排序 queryHelper.addOrderByProperty("c.state", QueryHelper.ORDER_BY_ASC); //按照投诉时间升序排序 queryHelper.addOrderByProperty("c.compTime", QueryHelper.ORDER_BY_ASC);
pageResult = complainService.getPageResult(queryHelper, getPageNo(), getPageSize()); } catch (Exception e) { e.printStackTrace(); } return "listUI"; } |
1.24.3,投诉受理
//受理 function doDeal(compId){ document.forms[0].action = "${basePath}nsfw/complain_dealUI.action?complain.compId=" + compId; document.forms[0].submit(); } </script> |
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <%@include file="/common/header.jsp"%> <title>投诉受理管理</title> </head> <body class="rightBody"> <form id="form" name="form" action="${basePath }nsfw/complain_deal.action" method="post" enctype="multipart/form-data"> <div class="p_d_1"> <div class="p_d_1_1"> <div class="content_info"> <div class="c_crumbs"><div><b></b><strong>投诉受理管理</strong> - 投诉受理</div></div> <div class="tableH2">投诉详细信息<span style="color:red;">(<s:property value="#complainStateMap[complain.state]"/>)</span></div> <table id="baseInfo" width="100%" align="center" class="list" border="0" cellpadding="0" cellspacing="0" > <tr><td colspan="2" align="center">投诉人信息</td></tr> <tr> <td class="tdBg" width="250px">是否匿名投诉:</td> <td><s:property value="complain.isNm?'匿名投诉':'非匿名投诉'"/></td> </tr> <tr> <td class="tdBg">投诉人单位:</td> <td>
<s:property value="complain.compCompany"/>
</td> </tr> <tr> <td class="tdBg">投诉人姓名:</td> <td><s:property value="complain.compName"/></td> </tr> <tr> <td class="tdBg">投诉人手机:</td> <td>
<s:property value="complain.compMobile"/>
</td> </tr> <tr><td colspan="2" align="center">投诉信息</td></tr> <tr> <td class="tdBg">投诉时间:</td> <td> <s:date name="complain.compTime" format="yyyy-MM-dd HH:mm"/> </td> </tr> <tr> <td class="tdBg">被投诉部门:</td> <td><s:property value="complain.toCompDept"/></td> </tr> <tr> <td class="tdBg">被投诉人:</td> <td><s:property value="complain.toCompName"/></td> </tr> <tr> <td class="tdBg">投诉标题:</td> <td><s:property value="complain.compTitle"/></td> </tr> <tr> <td class="tdBg">投诉内容:</td> <td><s:property value="complain.compContent" escape="false"/></td> </tr> <tr><td colspan="2" align="center">受理信息</td></tr> <tr> <td colspan="2"> <s:iterator value="complain.complainReplies" status="st"> <fieldset style="border: solid 1px #c0c0c0;margin-top:5px;"><legend style="color:green;font-weight:bold;">回复<s:property value="#st.count"/> </legend> <div style="width:100%; text-align:center;color:#ccc;maring-top:5px;"> 回复部门:<s:property value="replyDept"/> 回复人:<s:property value="replyer"/> 回复时间:<s:date name="replyTime" format="yyyy-MM-dd HH:mm"/> </div> <div style="width:100%;maring-top:10px;font-size:13px;padding-left:5px;"> <s:property value="replyContent"/> </div> </fieldset> </s:iterator> </td> </tr> <tr><td colspan="2" align="center">受理操作</td></tr> <tr> <td class="tdBg">回复部门:</td> <td> <s:property value="#session.SYS_USER.dept"/> <s:hidden name="reply.replyDept" value="%{#session.SYS_USER.dept}"/> </td> </tr> <tr> <td class="tdBg">回复人:</td> <td> <s:property value="#session.SYS_USER.name"/> <s:hidden name="reply.replyer" value="%{#session.SYS_USER.name}"/> </td> </tr>
<tr> <td class="tdBg" width="200px">回复内容:</td> <td><s:textarea name="reply.replyContent" cols="90" rows="8" /></td> </tr> </table> <s:hidden name="complain.compId"/> <div class="tc mt20"> <input type="submit" class="btnB2" value="保存" /> <input type="button" onclick="javascript:history.go(-1)" class="btnB2" value="返回" /> </div> </div></div></div> </form> </body> </html> |
private ComplainReply reply; // 跳转到受理页面 public String dealUI() { // 加载状态集合 ActionContext.getContext().getContextMap() .put("complainStateMap", Complain.COMPLAIN_STATE_MAP); if (complain != null) { complain = complainService.findObjectById(complain.getCompId()); } return "dealUI"; }
public String deal() { if (complain != null) { Complain tem = complainService.findObjectById(complain.getCompId()); // 1、更新投诉的状态为 已受理 if (!Complain.COMPLAIN_STATE_DONE.equals(tem.getState())) {// 更新状态为 // 已受理 tem.setState(Complain.COMPLAIN_STATE_DONE); } // 2、保存回复信息 if (reply != null) { reply.setComplain(tem); reply.setReplyTime(new Timestamp(new Date().getTime())); tem.getComplainReplies().add(reply); } complainService.update(tem); } return "list"; } |
<set name="complainReplies" inverse="true" cascade="save-update,delete" lazy="false" order-by="reply_time"> |
1.24.4,匿名投诉
<tr> <td class="tdBg" width="250px">是否匿名投诉:</td> <td><s:property value="complain.isNm?'匿名投诉':'非匿名投诉'"/></td> </tr> <tr> <td class="tdBg">投诉人单位:</td> <td> <s:if test="!complain.isNm"> <s:property value="complain.compCompany"/> </s:if> </td> </tr> <tr> <td class="tdBg">投诉人姓名:</td> <td><s:if test="!complain.isNm"><s:property value="complain.compName"/></s:if></td> </tr> <tr> <td class="tdBg">投诉人手机:</td> <td> <s:if test="!complain.isNm"> <s:property value="complain.compMobile"/> </s:if><s:elseif test="%{complain.compMobile.length() > 10}"> <s:property value="%{complain.compMobile.substring(0,3) + '****' + complain.compMobile.substring(7,11)}"/> </s:elseif> </td> </tr> |
1.24.5,回复信息的回显
<tr> <td colspan="2"> <s:iterator value="complain.complainReplies" status="st"> <fieldset style="border: solid 1px #c0c0c0;margin-top:5px;"><legend style="color:green;font-weight:bold;">回复<s:property value="#st.count"/> </legend> <div style="width:100%; text-align:center;color:#ccc;maring-top:5px;"> 回复部门:<s:property value="replyDept"/> 回复人:<s:property value="replyer"/> 回复时间:<s:date name="replyTime" format="yyyy-MM-dd HH:mm"/> </div> <div style="width:100%;maring-top:10px;font-size:13px;padding-left:5px;"> <s:property value="replyContent"/> </div> </fieldset> </s:iterator> </td> </tr> |
<set name="complainReplies" inverse="true" cascade="save-update,delete" lazy="false" order-by="reply_time"> |
1.24.6,细节自动处理保存到数据库的标签(适合用工具保存东西的时候带有格式化的)
<td class="tdBg">投诉内容:</td> <td><s:property value="complain.compContent" escape="false"/></td> |
1.25,在home页面的用户投诉
1.25.1,页面出来
<div class="lc_grzxbt"> <h1>我的投诉</h1> <div style="float:right;padding-top:3px;"> <s:a action="home_complainAddUI" namespace="/sys">我要投诉</s:a> </div> </div> |
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <% pageContext.setAttribute("basePath", request.getContextPath()+"/") ; %> <html> <head> <%@include file="/common/header.jsp"%> <title>我要投诉</title> <script type="text/javascript" charset="utf-8" src="${basePath }js/ueditor/ueditor.config.js"></script> <script type="text/javascript" charset="utf-8" src="${basePath }js/ueditor/ueditor.all.min.js"> </script> <script type="text/javascript" charset="utf-8" src="${basePath }js/ueditor/lang/zh-cn/zh-cn.js"></script>
<script> window.UEDITOR_HOME_URL = "${basePath }js/ueditor/"; var ue = UE.getEditor('editor');
//根据部门查询该部门下的用户列表 function doSelectDept(){ //1、获取部门 var dept = $("#toCompDept option:selected").val(); if(dept != ""){ //2、根据部门查询列表 $.ajax({ url:"${basePath}sys/home_getUserJson2.action", data:{"dept":dept}, type:"post", dataType:"json",//返回数据类型 success: function(data){ //2.1、将用户列表设置到被投诉人下拉框中 if(data != null && data != "" && data != undefined){ if("success" == data.msg){ var toCompName = $("#toCompName"); toCompName.empty(); $.each(data.userList, function(index, user){ toCompName.append("<option value='" + user.name + "'>" + user.name + "</option>"); }); } else {alert("获取被投诉人列表失败!");} } else { alert("获取被投诉人列表失败!"); } }, error:function(){alert("获取被投诉人列表失败!");} }); } else { //清空被投诉人列表下拉框 $("#toCompName").empty(); } } </script>
</head> <body> <form id="form" name="form" action="" method="post" enctype="multipart/form-data"> <div class="vp_d_1"> <div style="width:1%;float:left;"> </div> <div class="vp_d_1_1"> <div class="content_info"> <div class="c_crumbs"><div><b></b><strong>工作主页</strong> - 我要投诉</div></div> <div class="tableH2">我要投诉</div> <table id="baseInfo" width="100%" align="center" class="list" border="0" cellpadding="0" cellspacing="0" > <tr> <td class="tdBg" width="250px">投诉标题:</td> <td><s:textfield name="comp.compTitle"/></td> </tr> <tr> <td class="tdBg">被投诉人部门:</td> <td><s:select id="toCompDept" name="user.dept" list="#{'':'请选择','部门A':'部门A','部门B':'部门B' }" onchange="doSelectDept()"/></td> </tr> <tr> <td class="tdBg">被投诉人姓名:</td> <td> <select id="toCompName" name="comp.toCompName"> </select> </td> </tr> <tr> <td class="tdBg">投诉内容:</td> <td><s:textarea id="editor" name="comp.compContent" cssStyle="width:90%;height:160px;" /></td> </tr> <tr> <td class="tdBg">是否匿名投诉:</td> <td><s:radio name="comp.isNm" list="#{'0':'非匿名投诉','1':'匿名投诉' }" value="0"/></td> </tr>
</table>
<div class="tc mt20"> <input type="button" class="btnB2" value="保存" /> <input type="button" onclick="javascript:window.close()" class="btnB2" value="关闭" /> </div> </div></div> <div style="width:1%;float:left;"> </div> </div> </form> </body> </html> |
//跳转到首页 public String execute(){ return "home"; }
//跳转到我要投诉 public String complainAddUI(){ return "complainAddUI"; }
|
1.25.2,根据下拉列表的部门显示出来被投诉人的信息(方法一:无框架实现)
<tr> <td class="tdBg">被投诉人部门:</td> <td><s:select id="toCompDept" name="user.dept" list="#{'':'请选择','部门A':'部门A','部门B':'部门B' }" onchange="doSelectDept()"/></td> </tr> |
<script> window.UEDITOR_HOME_URL = "${basePath }js/ueditor/"; var ue = UE.getEditor('editor');
//根据部门查询该部门下的用户列表 function doSelectDept(){ //1、获取部门 var dept = $("#toCompDept option:selected").val(); if(dept != ""){ //2、根据部门查询列表 $.ajax({ url:"${basePath}sys/home_getUserJson.action", data:{"dept":dept}, type:"post", dataType:"json",//返回数据类型 success: function(data){ //2.1、将用户列表设置到被投诉人下拉框中 if(data != null && data != "" && data != undefined){ if("success" == data.msg){ var toCompName = $("#toCompName"); toCompName.empty(); $.each(data.userList, function(index, user){ toCompName.append("<option value='" + user.name + "'>" + user.name + "</option>"); }); } else {alert("获取被投诉人列表失败!");} } else { alert("获取被投诉人列表失败!"); } }, error:function(){alert("获取被投诉人列表失败!");} }); } else { //清空被投诉人列表下拉框 $("#toCompName").empty(); } } </script> |
public void getUserJson() { try { // 1、获取部门 String dept = ServletActionContext.getRequest() .getParameter("dept"); if (StringUtils.isNotBlank(dept)) { QueryHelper queryHelper = new QueryHelper(User.class, "u"); queryHelper.addCondition("u.dept like ?", "%" + dept); // 2、根据部门查询用户列表 List<User> userList = userService.findObjects(queryHelper); // 创建Json对象 JSONObject jso = new JSONObject(); jso.put("msg", "success"); jso.accumulate("userList", userList);
// 3、输出用户列表以json格式字符串形式输出 HttpServletResponse response = ServletActionContext .getResponse(); response.setContentType("text/html"); ServletOutputStream outputStream = response.getOutputStream(); outputStream.write(jso.toString().getBytes("utf-8")); outputStream.close(); } } catch (Exception e) { e.printStackTrace(); } } } |
用json的时候注意这3个jar包向本项目lib包加入"json-lib-2.3-jdk15.jar,ezmorph-1.0.6.jar,commons-beanutils-1.8.0.jar" |
1.25.3,根据下拉列表的部门显示出来被投诉人的信息(方法二:struts2框架实现)过度出现的问题
使用struts2-json-plugin-2.x.jar 包,由struts将action中的变量组装成Json对象。 加入 struts2-json-plugin-2.x.jar 到项目中,在*-struts.xml中配置对应请求方法的返回类型为json。 |
首先我们看一下,第一种方法,返回什么格式的json 在浏览器中输入:http://localhost:8080/itcastTax/sys/home_getUserJson.action?dept=A { "msg": "success", "userList": [ { "account": "admin1", "dept": "部门A", "email": "", "gender": false, "id": "402880e45ae14e67015ae1509a4d0000", "memo": "", "mobile": "", "name": "管理员", "password": "123", "state": "1" }, { "account": "admin", "dept": "部门A", "email": "", "gender": true, "headImg": "user/4cf51c7afa9f4f1e92c297d2fb60ea12.jpg", "id": "402880e85acd262f015acd26dba20000", "memo": "", "mobile": "", "name": "管理员", "password": "123", "state": "1" }, { "account": "user", "birthday": "1999-10-10 00:00:00.0", "dept": "部门A", "email": "[email protected]", "gender": true, "id": "402880e85acd3d5a015acd7a15b10001", "memo": "", "mobile": "13888888888", "name": "用户一", "password": "123", "state": "1" } ] } |
格式化之后, |
用struts框架之后会出现什么情况 首先我们来配置一下 <package name="sysHomeJson-action" namespace="/sys" extends="json-default"> <action name="home_getUserJson2" class="cn.itcast.home.action.HomeAction" method="getUserJson2"> <result type="json">
</result> </action> </package> |
private List<User> userList; public String getUserJson2() { try { // 1、获取部门 String dept = ServletActionContext.getRequest() .getParameter("dept"); if (StringUtils.isNotBlank(dept)) { QueryHelper queryHelper = new QueryHelper(User.class, "u"); queryHelper.addCondition("u.dept like ?", "%" + dept); // 2、根据部门查询用户列表 userList = userService.findObjects(queryHelper); } } catch (Exception e) { e.printStackTrace(); } return SUCCESS; } |
{ "userJson2": "success", "userList": [ { "account": "admin1", "dept": "部门A", "email": "", "gender": false, "id": "402880e45ae14e67015ae1509a4d0000", "memo": "", "mobile": "", "name": "管理员", "password": "123", "state": "1" }, { "account": "admin", "dept": "部门A", "email": "", "gender": true, "headImg": "user/4cf51c7afa9f4f1e92c297d2fb60ea12.jpg", "id": "402880e85acd262f015acd26dba20000", "memo": "", "mobile": "", "name": "管理员", "password": "123", "state": "1" }, { "account": "user", "birthday": "1999-10-10T00:00:00", "dept": "部门A", "email": "[email protected]", "gender": true, "id": "402880e85acd3d5a015acd7a15b10001", "memo": "", "mobile": "13888888888", "name": "用户一", "password": "123", "state": "1" } ] } |
格式化之后看: |
根据上面出现的问题看下面的解决方法 |
1.25.4,根据下拉列表的部门显示出来被投诉人的信息(方法二:struts2框架实现)
既然上面的产生的原因主要是return会success捣的鬼,那么看下面的解决方法: |
private Map<String, Object> return_map; public String getUserJson2(){ try { //1、获取部门 String dept = ServletActionContext.getRequest().getParameter("dept"); if(StringUtils.isNotBlank(dept)){ QueryHelper queryHelper = new QueryHelper(User.class, "u"); queryHelper.addCondition("u.dept like ?", "%" +dept); //2、根据部门查询用户列表 return_map = new HashMap<String, Object>(); return_map.put("msg", "success"); return_map.put("userList", userService.findObjects(queryHelper)); } } catch (Exception e) { e.printStackTrace(); } return SUCCESS; }
public Map<String, Object> getReturn_map() { return return_map; }
public void setReturn_map(Map<String, Object> return_map) { this.return_map = return_map; }
|
<package name="sysHomeJson-action" namespace="/sys" extends="json-default"> <action name="home_getUserJson2" class="cn.itcast.home.action.HomeAction" method="getUserJson2"> <result type="json"> <param name="root">return_map</param> </result> </action> </package> |
1.26,保存我要投诉
1.26.1,代码实现
1、保存投诉信息
2、提示用户投诉成功
3、刷新父窗口
4、关闭当前窗口
$("form").serialize() |
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <% pageContext.setAttribute("basePath", request.getContextPath()+"/") ; %> <html> <head> <%@include file="/common/header.jsp"%> <title>我要投诉</title> <script type="text/javascript" charset="utf-8" src="${basePath }js/ueditor/ueditor.config.js"></script> <script type="text/javascript" charset="utf-8" src="${basePath }js/ueditor/ueditor.all.min.js"> </script> <script type="text/javascript" charset="utf-8" src="${basePath }js/ueditor/lang/zh-cn/zh-cn.js"></script>
<script> window.UEDITOR_HOME_URL = "${basePath }js/ueditor/"; var ue = UE.getEditor('editor');
//根据部门查询该部门下的用户列表 function doSelectDept(){ //1、获取部门 var dept = $("#toCompDept option:selected").val(); if(dept != ""){ //2、根据部门查询列表 $.ajax({ url:"${basePath}sys/home_getUserJson2.action", data:{"dept":dept}, type:"post", dataType:"json",//返回数据类型 success: function(data){ //2.1、将用户列表设置到被投诉人下拉框中 if(data != null && data != "" && data != undefined){ if("success" == data.msg){ var toCompName = $("#toCompName"); toCompName.empty(); $.each(data.userList, function(index, user){ toCompName.append("<option value='" + user.name + "'>" + user.name + "</option>"); }); } else {alert("获取被投诉人列表失败!");} } else { alert("获取被投诉人列表失败!"); } }, error:function(){alert("获取被投诉人列表失败!");} }); } else { //清空被投诉人列表下拉框 $("#toCompName").empty(); } } //提交表单 function doSubmit(){ //1、提交表单并保存 $.ajax({ url:"${basePath}sys/home_complainAdd.action", data:$("#form").serialize(), type:"post", async: false, success: function(msg){ if("success" == msg){ //2、提示用户投诉成功 alert("投诉成功!"); //3、刷新父窗口 window.opener.parent.location.reload(true); //4、关闭当前窗口 window.close(); } else {alert("投诉失败!");} }, error: function(){alert("投诉失败!");} }); } </script>
</head> <body> <form id="form" name="form" action="" method="post" enctype="multipart/form-data"> <div class="vp_d_1"> <div style="width:1%;float:left;"> </div> <div class="vp_d_1_1"> <div class="content_info"> <div class="c_crumbs"><div><b></b><strong>工作主页</strong> - 我要投诉</div></div> <div class="tableH2">我要投诉</div> <table id="baseInfo" width="100%" align="center" class="list" border="0" cellpadding="0" cellspacing="0" > <tr> <td class="tdBg" width="250px">投诉标题:</td> <td><s:textfield name="comp.compTitle"/></td> </tr> <tr> <td class="tdBg">被投诉人部门:</td> <td><s:select id="toCompDept" name="comp.toCompDept" list="#{'':'请选择','部门A':'部门A','部门B':'部门B' }" onchange="doSelectDept()"/></td> </tr> <tr> <td class="tdBg">被投诉人姓名:</td> <td> <select id="toCompName" name="comp.toCompName"> </select> </td> </tr> <tr> <td class="tdBg">投诉内容:</td> <td><s:textarea id="editor" name="comp.compContent" cssStyle="width:90%;height:160px;" /></td> </tr> <tr> <td class="tdBg">是否匿名投诉:</td> <td><s:radio name="comp.isNm" list="#{'false':'非匿名投诉','true':'匿名投诉' }" value="true"/></td> </tr>
</table> <s:hidden name="comp.compCompany" value="%{#session.SYS_USER.dept}"/> <s:hidden name="comp.compName" value="%{#session.SYS_USER.name}"/> <s:hidden name="comp.compMobile" value="%{#session.SYS_USER.mobile}"/> <div class="tc mt20"> <input type="button" class="btnB2" value="保存" onclick="doSubmit()" /> <input type="button" onclick="javascript:window.close()" class="btnB2" value="关闭" /> </div> </div></div> <div style="width:1%;float:left;"> </div> </div> </form> </body> </html> |
@Resource private ComplainService complainService; private Complain comp; //保存投诉 public void complainAdd(){ try { if(comp != null){ //设置默写投诉状态为 待受理 comp.setState(Complain.COMPLAIN_STATE_UNDONE); comp.setCompTime(new Timestamp(new Date().getTime())); complainService.save(comp);
//输出投诉结果 HttpServletResponse response = ServletActionContext.getResponse(); response.setContentType("text/html"); ServletOutputStream outputStream = response.getOutputStream(); outputStream.write("success".getBytes("utf-8")); outputStream.close();
} } catch (Exception e) { e.printStackTrace(); } } |
1.27,解决搜索条件被覆盖丢失的问题(略和之前的逻辑一样)
1.27.1,注意配置文件的代码
<struts> <package name="complain-action" namespace="/nsfw" extends="base-default"> <action name="complain_*" class="cn.itcast.nsfw.complain.action.ComplainAction" method="{1}"> <result name="{1}">/WEB-INF/jsp/nsfw/complain/{1}.jsp</result> <result name="list" type="redirectAction"> <param name="actionName">complain_listUI</param> <param name="complain.compTitle">${strTitle}</param> <param name="complain.state">${strState}</param> <param name="startTime">${startTime}</param> <param name="endTime">${endTime}</param> <param name="pageNo">${pageNo}</param> <param name="encode">true</param> </result>
</action> </package> |
1.28,quartz的讲解
1.28.1,讲解
Jar包org.springframework.context.support-3.0.2.RELEASE quartz-1.8.6 |
1、制定任务信息 bean ① 设置执行对象 ② 设置执行对象中对应的执行方法 ③ 是否可以同步执行
2、制定任务执行时机(执行触发器) bean 2.1、简单触发器(SimpleTrigger) ① 设置任务详细 ② 设置任务延迟执行时间 ③ 设置任务执行频率
2.2、任务触发器(CronTrigger) ① 设置任务详细 ② 设置执行时机(cronExpression) cronExpression:秒 分 时 日 月 周 年(可选)
3、设置任务调度工厂 bean 设置触发器们 |
public class QuartzTask {
public void doSimpleTriggerTask() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("doing simpleTrigger task..." + sdf.format(new Date())); } |
简单的触发器:org.springframework.scheduling.quartz.SimpleTriggerBean <!-- 注册一个普通bean --> <bean id="quartzTask" class="cn.itcast.nsfw.complain.QuartzTask"></bean>
<!-- 1、制定任务信息信息 --> <bean id="jobDetail1" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <!-- 设置执行对象 --> <property name="targetObject" ref="quartzTask"></property> <!-- 设置执行对象中对应的执行方法 --> <property name="targetMethod" value="doSimpleTriggerTask"></property> <!-- 是否可以同步执行;不可同步执行 --> <property name="concurrent" value="false"></property> </bean> <!-- 2、制定任务执行时机(任务执行触发器) --> <bean id="simplerTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> <!-- 设置任务详细 --> <property name="jobDetail" ref="jobDetail1"></property> <!-- 设置任务延迟执行时间 ;延迟2秒执行--> <property name="startDelay" value="2000"></property> <!-- 设置任务执行频率;执行频率为每4秒执行一下 --> <property name="repeatInterval" value="1000"></property> </bean> <!-- 3、设置调度工厂 --> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="simplerTrigger"/> <!-- <ref bean="cronTrigger"/> --> </list> </property> </bean> |
<!-- 引入外部配置文件 --> <import resource="classpath:cn/itcast/*/conf/*-spring.xml" /> <import resource="classpath:cn/itcast/nsfw/*/conf/*-spring.xml"/> |
任务触发器:org.springframework.scheduling.quartz.CronTriggerBean |
public class QuartzTask {
public void doCronTriggerTask() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println("doing cronTrigger task..." + sdf.format(new Date())); }
|
<!-- 注册一个普通bean --> <bean id="quartzTask" class="cn.itcast.nsfw.complain.QuartzTask"></bean>
<!-- 1、制定任务信息信息 --> <bean id="jobDetail2" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <!-- 设置执行对象 --> <property name="targetObject" ref="quartzTask"></property> <!-- 设置执行对象中对应的执行方法 --> <property name="targetMethod" value="doCronTriggerTask"></property> <!-- 是否可以同步执行;不可同步执行 --> <property name="concurrent" value="false"></property> </bean>
<!-- 2、制定任务执行时机(任务执行触发器) --> <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <!-- 设置任务详细 --> <property name="jobDetail" ref="jobDetail2"></property> <!-- 设置任务执行时机,cron表达式 --> <!--<property name="cronExpression" value="* * * 18c * ?"></property>--> <property name="cronExpression" value="0/3 * * * * ?"></property> </bean>
<!-- 3、设置调度工厂 --> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="cronTrigger"/> </list> </property> </bean> </beans> |
'*' 字符可以用于所有字段,在"分"字段中设为"*"表示"每一分钟"的含义。
'?' 字符可以用在"日"和"周几"字段. 它用来指定 '不明确的值'. 这在你需要指定这两个字段中的某一个值而不是另外一个的时候会被用到。在后面的例子中可以看到其含义。
'-' 字符被用来指定一个值的范围,比如在"小时"字段中设为"10-12"表示"10点到12点".
',' 字符指定数个值。比如在"周几"字段中设为"MON,WED,FRI"表示"the days Monday, Wednesday, and Friday".
'/' 字符用来指定一个值的的增加幅度. 比如在"秒"字段中设置为"0/15"表示"第0, 15, 30, 和 45秒"。而 "5/15"则表示"第5, 20, 35, 和 50". 在'/'前加"*"字符相当于指定从0秒开始. 每个字段都有一系列可以开始或结束的数值。对于"秒"和"分"字段来说,其数值范围为0到59,对于"小时"字段来说其为0到23, 对于"日"字段来说为0到31, 而对于"月"字段来说为1到12。"/"字段仅仅只是帮助你在允许的数值范围内从开始"第n"的值。 因此对于"月"字段来说"7/6"只是表示7月被开启而不是"每六个月", 请注意其中微妙的差别。
'L'字符可用在"日"和"周几"这两个字段。它是"last"的缩写, 但是在这两个字段中有不同的含义。例如,"日"字段中的"L"表示"一个月中的最后一天" —— 对于一月就是31号对于二月来说就是28号(非闰年)。而在"周几"字段中, 它简单的表示"7" or "SAT",但是如果在"周几"字段中使用时跟在某个数字之后, 它表示"该月最后一个星期×" —— 比如"6L"表示"该月最后一个周五"。当使用'L'选项时,指定确定的列表或者范围非常重要,否则你会被结果搞糊涂的。
'W' 可用于"日"字段。用来指定历给定日期最近的工作日(周一到周五) 。比如你将"日"字段设为"15W",意为: "离该月15号最近的工作日"。因此如果15号为周六,触发器会在14号即周五调用。如果15号为周日, 触发器会在16号也就是周一触发。如果15号为周二,那么当天就会触发。然而如果你将"日"字段设为"1W", 而一号又是周六, 触发器会于下周一也就是当月的3号触发,因为它不会越过当月的值的范围边界。'W'字符只能用于"日"字段的值为单独的一天而不是一系列值的时候。
'L'和'W'可以组合用于"日"字段表示为'LW',意为"该月最后一个工作日"。
'#' 字符可用于"周几"字段。该字符表示"该月第几个周×",比如"6#3"表示该月第三个周五( 6表示周五而"#3"该月第三个)。再比如: "2#1" = 表示该月第一个周一而 "4#5" = 该月第五个周三。注意如果你指定"#5"该月没有第五个"周×",该月是不会触发的。
'C' 字符可用于"日"和"周几"字段,它是"calendar"的缩写。它表示为基于相关的日历所计算出的值(如果有的话)。如果没有关联的日历, 那它等同于包含全部日历。"日"字段值为"5C"表示"日历中的第一天或者5号及其以后","周几"字段值为"1C"则表示"日历中的第一天或者周日及其以后"。
对于"月份"字段和"周几"字段来说合法的字符都不是大小写敏感的。
|
1.29,自动受理
1.29,每月的月底的晚上将上一个月的没有受理的投诉自动改成失效
<bean id="complainDao" class="cn.itcast.nsfw.complain.dao.impl.ComplainDaoImpl" parent="baseDao"></bean>
<!-- 扫描service --> <context:component-scan base-package="cn.itcast.nsfw.complain.service.impl"></context:component-scan>
<!-- 1、制定任务信息信息 --> <bean id="complainJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <!-- 设置执行对象 --> <property name="targetObject" ref="complainService"></property> <!-- 设置执行对象中对应的执行方法 --> <property name="targetMethod" value="autoDeal"></property> <!-- 是否可以同步执行;不可同步执行 --> <property name="concurrent" value="false"></property> </bean> <!-- 2、制定任务执行时机(任务执行触发器) --> <bean id="complainCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <!-- 设置任务详细信息 --> <property name="jobDetail" ref="complainJobDetail"></property> <!-- 设置任务执行时间点,cronExpression: 在每月的月底下午的3点每分钟的第10秒执行任务 --> <property name="cronExpression" value="10 * 15 L * ?"></property> </bean> <!-- 3、设置调度工厂 --> <bean id="complainScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="complainCronTrigger"/> </list> </property> </bean> </beans> |
public interface ComplainService extends BaseService<Complain> {
//自动受理投诉 public void autoDeal(); } |
@Service("complainService") public class ComplainServiceImpl extends BaseServiceImpl<Complain> implements ComplainService {
private ComplainDao complainDao;
@Resource public void setComplainDao(ComplainDao complainDao) { super.setBaseDao(complainDao); this.complainDao = complainDao; }
@Override public void autoDeal() { Calendar cal = Calendar.getInstance(); cal.set(Calendar.DAY_OF_MONTH, 1);//设置当前时间的日期为1号 cal.set(Calendar.HOUR_OF_DAY, 0);//设置当前时间的日期为1号,0时 cal.set(Calendar.MINUTE, 0);//设置当前时间的日期为1号,0分 cal.set(Calendar.SECOND, 0);//设置当前时间的日期为1号,0秒
//1、查询本月之前的待受理的投诉列表 QueryHelper queryHelper = new QueryHelper(Complain.class, "c"); queryHelper.addCondition("c.state=?", Complain.COMPLAIN_STATE_UNDONE); queryHelper.addCondition("c.compTime < ?", cal.getTime());//本月1号0时0分0秒
List<Complain> list = findObjects(queryHelper); if(list != null && list.size() > 0){ //2、更新投诉信息的状态为 已失效 for(Complain comp: list){ comp.setState(Complain.COMPLAIN_STATE_INVALID); update(comp); } } } |
<td align="center"><s:property value="#complainStateMap[state]"/></td> <td align="center"> <s:if test="state!=2"> <a href="javascript:doDeal('<s:property value='compId'/>')">受理</a> </s:if> </td> |
1.30,fusioncharts实现图形展示效果
1.30.1,代码展示
于此;要使用fusioncharts先将"fusioncharts.js"和"fusioncharts.charts.js"和相关主题文件复制到项目的js/fusioncharts文件夹。 |
//投诉统计 function doAnnualStatistic(){ document.forms[0].action = "${basePath}nsfw/complain_annualStatisticChartUI.action"; document.forms[0].submit(); } <li style="float:right;"> <input type="button" value="统计" class="s_button" onclick="doAnnualStatistic()"/> </li> |
<% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
//获取当前年份 Calendar cal = Calendar.getInstance(); int curYear = cal.get(Calendar.YEAR);//当前年份 request.setAttribute("curYear", curYear);
List yearList = new ArrayList(); for(int i = curYear; i > curYear-5 ; i--){ yearList.add(i); } request.setAttribute("yearList", yearList);
%>
<!DOCTYPE HTML> <html> <head> <%@include file="/common/header.jsp"%> <title>年度投诉统计图</title> </head> <script type="text/javascript" src="${basePath }js/fusioncharts/fusioncharts.js"></script> <script type="text/javascript" src="${basePath }js/fusioncharts/fusioncharts.charts.js"></script> <script type="text/javascript" src="${basePath }js/fusioncharts/themes/fusioncharts.theme.fint.js"></script> <script type="text/javascript">
//加载完dom元素后,执行 $(document).ready(doAnnualStatistic());
//根据年份统计投诉数 function doAnnualStatistic(){ //1、获取年份 var year = $("#year option:selected").val(); if(year == "" || year == undefined){ year = "${curYear}";//默认当前年份 } //2、根据年份统计 $.ajax({ url:"${basePath }/nsfw/complain_getAnnualStatisticData.action", data:{"year":year}, type: "post", dataType:"json", success: function(data){ if(data != null && data != "" && data != undefined){ var revenueChart = new FusionCharts({ "type": "line", "renderAt": "chartContainer", "width": "600", "height": "400", "dataFormat": "json", "dataSource": { "chart": { "caption": year + " 年度投诉数统计图", "xAxisName": "月 份", "yAxisName": "投 诉 数", "theme": "fint" }, "data": data.chartData }
}); revenueChart.render(); } else { alert("统计投诉数失败!"); } }, error: function(){alert("统计投诉数失败!");} });
}
</script> <body> <br> <div style="text-align:center;width:100%;"><s:select id="year" list="#request.yearList" onchange="doAnnualStatistic()"></s:select></div> <br> <div id="chartContainer" style="text-align:center;width:100%;"></div> </body> </html> |
[ { "label": "1 月", "value": "42" }, { "label": "2 月", "value": "81" } ]注意上面的json要的值的格式。 |
<struts> <package name="complain-action" namespace="/nsfw" extends="struts-default,json-default"> <action name="complain_*" class="cn.itcast.nsfw.complain.action.ComplainAction" method="{1}"> <result name="{1}">/WEB-INF/jsp/nsfw/complain/{1}.jsp</result> <result name="list" type="redirectAction"> <param name="actionName">complain_listUI</param> <param name="complain.compTitle">${strTitle}</param> <param name="complain.state">${strState}</param> <param name="startTime">${startTime}</param> <param name="endTime">${endTime}</param> <param name="pageNo">${pageNo}</param> <param name="encode">true</param> </result> <result type="json" name="annualStatisticData"> <param name="root">statisticMap</param> </result> </action> </package> |
private Map<String, Object> statisticMap; //跳转到统计页面 public String annualStatisticChartUI(){ return "annualStatisticChartUI"; }
//根据年度获取该年度下的统计数 public String getAnnualStatisticData(){ //1、获取年份 HttpServletRequest request = ServletActionContext.getRequest(); int year = 0; if(request.getParameter("year") != null){ year = Integer.valueOf(request.getParameter("year")); } else { //默认 当前年份 year = Calendar.getInstance().get(Calendar.YEAR); } //2、获取统计年度的每个月的投诉数 statisticMap = new HashMap<String, Object>(); statisticMap.put("msg", "success"); statisticMap.put("chartData", complainService.getAnnualStatisticDataByYear(year)); return "annualStatisticData"; } |
/** * 根据年份获取统计年度的每个月的投诉数 * * @param year * 要统计的年份 * @return 统计数据 */ public List<Map> getAnnualStatisticDataByYear(int year); |
@Override public List<Map> getAnnualStatisticDataByYear(int year) { List<Map> resList = new ArrayList<Map>(); // 1、获取统计数据 List<Object[]> list = complainDao.getAnnualStatisticDataByYear(year);
if (list != null && list.size() > 0) { Calendar cal = Calendar.getInstance(); // 是否当前年份 boolean isCurYear = (cal.get(Calendar.YEAR) == year); int curMonth = cal.get(Calendar.MONTH) + 1;// 当前月份 // 2、格式化统计结果 int temMonth = 0; Map<String, Object> map = null; for (Object[] obj : list) { temMonth = Integer.valueOf((obj[0]) + ""); map = new HashMap<String, Object>(); map.put("label", temMonth + " 月"); if (isCurYear) {// 当前年份 // 当前年份:如果月份已过的则直接取投诉数并且值为空或null时则设为0;如果月份未过的则全部投诉数置空 if (temMonth > curMonth) {// 未到月份,则投诉数为空 map.put("value", ""); } else {// 已过月份 map.put("value", obj[1] == null ? "0" : obj[1]); } } else {// 非当前年份则直接取投诉数并且值为空或null时则设为0 map.put("value", obj[1] == null ? "0" : obj[1]); } resList.add(map); } }
return resList; } |
@Override public List<Map> getAnnualStatisticDataByYear(int year) { List<Map> resList = new ArrayList<Map>(); // 1、获取统计数据 List<Object[]> list = complainDao.getAnnualStatisticDataByYear(year); if (list != null && list.size() > 0) { // 2、格式化统计结果 int temMonth = 0; Map<String, Object> map = null; for (Object[] obj : list) { temMonth = Integer.valueOf((obj[0]) + ""); map = new HashMap<String, Object>(); map.put("label", temMonth + " 月"); map.put("value", obj[1] == null ? "0" : obj[1]); resList.add(map); } } return resList; } |
/** * 根据年份获取统计年度的每个月的投诉数 * @param year 要统计的年份 * @return 统计数据 */ public List<Object[]> getAnnualStatisticDataByYear(int year) |
需求:根据年度将相应年度的每个月的投诉数进行统计,并以图表的形式展示在页面中;在页面中可以选择查看当前年度及其前4年的投诉数。在页面中可以选择不同的年度,然后页面展示该年度的曲线统计图
内容:① 统计年度的每个月的投诉数;(未到月份不应该显示投诉数,已过的月份如果没有投诉数应该显示为0) ② 页面中可选择近5年的年份;并且根据选择的年份显示投诉统计图表
-----------------------------------------------------------------前端 1、年份选择(最近5年)
2、一进入页面中需要加载当前年度的投诉统计数
[ { "label": "1 月", "value": "42" }, { "label": "2 月", "value": "81" } ]
-----------------------------------------------------------------后端
目标: 统计年度的每个月的投诉数 Action: 1、获取年份 2、统计年度的每个月的投诉数并输出json格式字符串
2.1、根据年份统计该年份各个月的投诉数
统计语句:
统计相应年度各个月的投诉数sql:
select 月份,投诉数 from 投诉 where 年度=传入值 group by 月份
------------------实际月份的投诉数统计结果 select month(comp_time) as '月份',count(*) '总数' from complain where year(comp_time)=? group by month(comp_time)
select imonth, count(comp_id) from tmonth left join complain on imonth=month(comp_time) and year(comp_time)=? group by imonth order by imonth; 假如现在有12个月,后面的数据有100条的话,总共去数据库里面查找1200次。 然后在把这100条数据进行一一的分组在加12次总共1212次 假如现在有12个月,后面的数据有10000条的话,总共去数据库里面查找120000次。 然后在把这100条数据进行一一的分组在加12次总共120012次 ---------------------------------------------- select imonth,c2 from tmonth left join (select month(comp_time) c1, count(comp_id) c2 from complain where year(comp_time)=? group by month(comp_time)) t on imonth = c1 order by imonth; 现在还是假设有12个月,总共有100条数据,现在先把100条数据进行分组, 总共查了100次,分组有加了12次,总共112次, 并且已经分好12个组了,现在只需要把imonth12个月与分好组的12个月进行对比,这时候总共查了144次, 这时候两者相加总共查了156次。 现在还是假设有12个月,总共有10000条数据,现在先把10000条数据进行分组, 总共查了10000次,分组有加了12次,总共10012次, 并且已经分好12个组了,现在只需要把imonth12个月与分好组的12个月进行对比,这时候总共查了144次, 这时候两者相加总共查了10156次。 其实两者的根本的却别就是一个没有分组的去一个个的去给12个月数据对比,一个是分好了组的拿着一个组去给12个月做对比。 返回json格式字符串:① 当年份是非当前年份的话:则每月对应的投诉数如果出现空值则应设置为0;②当前年份的话:则每月中如果是月份大于当前月份投诉数出现空值则为空值或0时也设为空
|
ComplainDao { @Override public List<Object[]> getAnnualStatisticDataByYear(int year) { StringBuffer sb = new StringBuffer(); sb.append("SELECT imonth, COUNT(comp_id)") .append(" FROM tmonth LEFT JOIN complain ON imonth=MONTH(comp_time)") .append(" AND YEAR(comp_time)=?").append(" GROUP BY imonth ") .append(" ORDER BY imonth"); SQLQuery sqlQuery = getSession().createSQLQuery(sb.toString()); sqlQuery.setParameter(0, year); return sqlQuery.list(); } |
public List<Object[]> getAnnualStatisticDataByYear(int year) { StringBuffer sb = new StringBuffer(); sb.append("SELECT imonth, COUNT(comp_id) FROM tmonth LEFT JOIN complain ON imonth=MONTH(comp_time) AND YEAR(comp_time)=? GROUP BY imonth ORDER BY imonth"); SQLQuery sqlQuery = getSession().createSQLQuery(sb.toString()); sqlQuery.setParameter(0, year); return sqlQuery.list(); } |
优化, select imonth, count(comp_id) from tmonth left join complain on imonth=month(comp_time) and year(comp_time)=? group by imonth order by imonth; 假如现在有12个月,后面的数据有100条的话,总共去数据库里面查找1200次。 然后在把这100条数据进行一一的分组在加12次总共1212次 假如现在有12个月,后面的数据有10000条的话,总共去数据库里面查找120000次。 然后在把这100条数据进行一一的分组在加12次总共120012次 ---------------------------------------------- select imonth,c2 from tmonth left join (select month(comp_time) c1, count(comp_id) c2 from complain where year(comp_time)=? group by month(comp_time)) t on imonth = c1 order by imonth; 现在还是假设有12个月,总共有100条数据,现在先把100条数据进行分组, 总共查了100次,分组有加了12次,总共112次, 并且已经分好12个组了,现在只需要把imonth12个月与分好组的12个月进行对比,这时候总共查了144次, 这时候两者相加总共查了156次。 现在还是假设有12个月,总共有10000条数据,现在先把10000条数据进行分组, 总共查了10000次,分组有加了12次,总共10012次, 并且已经分好12个组了,现在只需要把imonth12个月与分好组的12个月进行对比,这时候总共查了144次, 这时候两者相加总共查了10156次。 其实两者的根本的却别就是一个没有分组的去一个个的去给12个月数据对比,一个是分好了组的拿着一个组去给12个月做对比。 |
1.31,前台页面展示
1.31.1,代码展示
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>国税协同办公平台</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <link href="${ctx}/css/home.css" rel="stylesheet" type="text/css" />
</head>
<body> <!-- 头部{ --> <table width="1222" border="0" align="center" cellpadding="0" cellspacing="0" background="${ctx}/images/home/top_bg.png" class="top"> <tr> <td width="32" height="106"> </td> <td width="418" height="106" align="left" valign="middle"> <img class="zxx_test_png" src="${ctx}/images/home/ind01.png" width="470" height="90" alt="" /> </td> <td width="211"> </td> <td width="328"> <object id="FlashID" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="450" height="86"> <param name="movie" value="${ctx}/images/home/flash.swf" /> <param name="quality" value="high" /> <param name="wmode" value="transparent" /> <param name="swfversion" value="6.0.65.0" /> <!-- 此 param 标签提示使用 Flash Player 6.0 r65 和更高版本的用户下载最新版本的 Flash Player。如果您不想让用户看到该提示,请将其删除。 --> <param name="expressinstall" value="Scripts/expressInstall.swf" /> <!-- 下一个对象标签用于非 IE 浏览器。所以使用 IECC 将其从 IE 隐藏。 --> <!--[if !IE]>--> <object type="application/x-shockwave-flash" data="${ctx}/images/home/flash.swf" width="380" height="86"> <!--<![endif]--> <param name="quality" value="high" /> <param name="wmode" value="transparent" /> <param name="swfversion" value="6.0.65.0" /> <param name="expressinstall" value="Scripts/expressInstall.swf" /> <!-- 浏览器将以下替代内容显示给使用 Flash Player 6.0 和更低版本的用户。 --> <div> <h4>此页面上的内容需要较新版本的 Adobe Flash Player。</h4> <p> <a href="http://www.adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="获取 Adobe Flash Player" width="112" height="33" /> </a> </p> </div> <!--[if !IE]>--> </object> <!--<![endif]--> </object> </td> <td width="331" align="right" valign="top"> <table width="350" border="0" cellpadding="0" cellspacing="0"> <tr> <td width="64" height="4"></td> <td width="25" height="5"></td> <td width="120" height="4"></td> <td width="25" height="4"></td> <td width="40" height="4"></td> <td width="25" height="4"></td> <td width="50" height="4"></td> </tr> <tr> <td align="center"></td> <td align="left"></td> <td align="right"> <a><b></b><font color="red">欢迎您,<s:property value="#session.SYS_USER.name"/> </font></a> </td> <td align="center"><img src="${ctx}/images/home/help.png" width="12" height="17" /></td> <td align="left"><a href="javascript:void(0);">帮助</a></td> <td align="center"><img src="${ctx}/images/home/exit.png" width="14" height="14" /></td> <td align="left" valign="middle" ><a href="${ctx }/sys/login_logout.action">退出</a></td> </tr> </table> </td> </tr> </table> <!-- }头部 --> <!-- 导航{ --> <div class="menu"> <ul class="clearfix"> <li class="hover"><a href="javascript:void(0);">工作主页</a></li> <li><a href="javascript:void(0);">行政管理</a></li> <li><a href="javascript:void(0);">后勤服务</a></li> <li><a href="javascript:void(0);">在线学习</a></li> <li><a href="${ctx }/nsfw/home_frame.action">纳税服务</a> </li> <li><a href="javascript:void(0);">我的空间</a></li> </ul> </div> <!-- }导航 --> <!-- 左{ --> <div class="content"> <div class="left"> <!-- 个人资料{ --> <div class="left_grzx1"> <div class="left_grzxbt"> <h1>个人资料</h1> </div> <table width="98%" border="0" align="center"> <tr> <td width="76" height="100" align="center" valign="middle"> <div class="left-tx"> <s:if test="%{#session.SYS_USER.headImg != null && #session.SYS_USER.headImg !=''}"> <img src="${ctx}/upload/<s:property value='#session.SYS_USER.headImg'/>" width="70" height="70" /> </s:if><s:else> <img src="${ctx}/images/home/gs09.png" width="70" height="70" /> </s:else> </div> </td> <td width="5%"><img src="${ctx}/images/home/gs10.png" width="4" height="59" alt="" /></td> <td width="60%"><table width="95%" border="0" cellpadding="0" cellspacing="0"> <tr> <td colspan="2" style=" font-weight:bold; color:#3a7daa;"><s:property value="#session.SYS_USER.name"/></td> </tr> <tr> <td colspan="2">所属部门:<s:property value="#session.SYS_USER.dept"/></td> </tr> </table> </td> </tr> </table> </div> <!-- }个人资料 --> </div> <!-- }左 -->
<!-- 右{ --> <div class="right"> <div class="left_grzx1"> <div class="left_grzxbt"> <h1>信息列表</h1> </div> <table width="98%" border="0" align="center"> <s:iterator value="#infoList"> <tr> <td height="23"> <s:url var="infoViewUrl" action="home_infoViewUI" namespace="/sys" > <s:param name="info.infoId"><s:property value="infoId"/></s:param> </s:url> <s:a href="%{#infoViewUrl}" target="_blank"> <s:property value="title"/> </s:a> </td> <td width="150px"><s:property value="#infoTypeMap[type]"/></td> <td width="150px"><s:property value="creator"/></td> <td width="150px"><s:date name="createTime" format="yyyy-MM-dd HH:mm"/></td> </tr> </s:iterator> </table> </div> </div> <!-- }右--> <div class="clear"></div>
<div class="layout_center"> <div class="lc_grzx1"> <div class="lc_grzxbt"> <h1>我的投诉</h1> <div style="float:right;padding-top:3px;"> <s:a action="home_complainAddUI" namespace="/sys" target="_blank">我要投诉</s:a> </div> </div> <table width="98%" border="0" align="center"> <s:iterator value="#complainList"> <tr> <td height="23"> <s:url var="complainViewUrl" action="home_complainViewUI" namespace="/sys" > <s:param name="comp.compId"><s:property value="compId"/></s:param> </s:url> <s:a href="%{#complainViewUrl}" target="_blank"> <s:property value="compTitle"/> </s:a> </td> <td width="180px"><s:property value="#complainStateMap[state]"/></td> <td width="180px"><s:property value="isNm?'匿名投诉':'非匿名投诉'"/></td> <td width="180px"><s:date name="compTime" format="yyyy-MM-dd HH:mm"/></td> </tr> </s:iterator> </table> </div>
<div class="lc_grzx1"> <div class="lc_grzxbt"> <h1>我的咨询</h1> </div> <table width="98%" border="0" align="center"> <tr> <td></td> <td width="150px"></td> <td width="150px"></td> </tr> </table> </div> </div> </div> <!-- 尾部{ --> <div class="foot">版权所有©国税局 2014</div> <!-- }尾部 --> </body> |
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ taglib prefix="s" uri="/struts-tags" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %>
<html> <head> <base href="<%=basePath%>">
<title>查看信息</title>
<meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0">
</head>
<body> <div align="center " style="text-align: center; width: 100%;height: 100%;overflow: hidden"> <!-- 标题 --> <div style="text-align: center; width: 100%;"> <h1><s:property value="info.title"/></h1> </div> <hr/> <!-- 时间、作者 --> <div style="text-align: center; width: 100%;color:#ccc;font-size:12px;"> 信息分类:<s:property value="#infoTypeMap[info.type]"/> 创建人:<s:property value="info.creator"/> 创建时间:<s:date name="info.createTime" format="yyyy-MM-dd HH:mm"/> </div> <div style="text-align: center; width: 100%;padding:8px;"> <s:property value="info.content" escape="false"/> </div> </div>
</body> </html> |
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <% pageContext.setAttribute("basePath", request.getContextPath()+"/") ; %> <html> <head> <%@include file="/common/header.jsp"%> <title>投诉信息</title> </head> <body class="rightBody"> <div class="vp_d_1"> <div style="width:1%;float:left;"> </div> <div class="vp_d_1_1"> <div class="content_info"> <div class="c_crumbs"><div><b></b><strong>工作主页</strong> - 投诉信息</div></div> <div class="tableH2">投诉详细信息<span style="color:red;">(<s:property value="#complainStateMap[comp.state]"/>)</span></div> <table id="baseInfo" width="100%" align="center" class="list" border="0" cellpadding="0" cellspacing="0" > <tr><td colspan="2" align="center">投诉人信息</td></tr> <tr> <td class="tdBg" width="250px">是否匿名投诉:</td> <td><s:property value="comp.isNm?'匿名投诉':'非匿名投诉'"/></td> </tr> <tr> <td class="tdBg">投诉人单位:</td> <td> <s:if test="!comp.isNm"> <s:property value="comp.compCompany"/> </s:if> </td> </tr> <tr> <td class="tdBg">投诉人姓名:</td> <td><s:if test="!comp.isNm"><s:property value="comp.compName"/></s:if></td> </tr> <tr> <td class="tdBg">投诉人手机:</td> <td> <s:if test="!comp.isNm"> <s:property value="comp.compMobile"/> </s:if><s:elseif test="%{comp.compMobile.length() > 10}"> <s:property value="%{comp.compMobile.substring(0,3) + '****' + comp.compMobile.substring(7,11)}"/> </s:elseif> </td> </tr> <tr><td colspan="2" align="center">投诉信息</td></tr> <tr> <td class="tdBg">投诉时间:</td> <td> <s:date name="comp.compTime" format="yyyy-MM-dd HH:mm"/> </td> </tr> <tr> <td class="tdBg">被投诉部门:</td> <td><s:property value="comp.toCompDept"/></td> </tr> <tr> <td class="tdBg">被投诉人:</td> <td><s:property value="comp.toCompName"/></td> </tr> <tr> <td class="tdBg">投诉标题:</td> <td><s:property value="comp.compTitle"/></td> </tr> <tr> <td class="tdBg">投诉内容:</td> <td><s:property value="comp.compContent" escape="false"/></td> </tr> <tr><td colspan="2" align="center">受理信息</td></tr> <tr> <td colspan="2"> <s:iterator value="comp.complainReplies" status="st"> <fieldset style="border: solid 1px #c0c0c0;margin-top:5px;"><legend style="color:green;font-weight:bold;">回复<s:property value="#st.count"/> </legend> <div style="width:100%; text-align:center;color:#ccc;maring-top:5px;"> 回复部门:<s:property value="replyDept"/> 回复人:<s:property value="replyer"/> 回复时间:<s:date name="replyTime" format="yyyy-MM-dd HH:mm"/> </div> <div style="width:100%;maring-top:10px;font-size:13px;padding-left:5px;"> <s:property value="replyContent"/> </div> </fieldset> </s:iterator> </td> </tr> </table> </div></div> <div style="width:1%;float:left;"> </div> </div> </body> </html> |
public class HomeAction extends ActionSupport {
@Resource private UserService userService; @Resource private InfoService infoService;
@Resource private ComplainService complainService;
private Map<String, Object> return_map; private Complain comp; private Info info; //跳转到首页 public String execute(){ //加载信息列表 //加载分类集合 ActionContext.getContext().getContextMap().put("infoTypeMap", Info.INFO_TYPE_MAP); QueryHelper queryHelper1 = new QueryHelper(Info.class, "i"); queryHelper1.addOrderByProperty("i.createTime", QueryHelper.ORDER_BY_DESC); List<Info> infoList = infoService.getPageResult(queryHelper1, 1, 5).getItems(); ActionContext.getContext().getContextMap().put("infoList", infoList);
User user = (User) ServletActionContext.getRequest().getSession().getAttribute(Constant.USER); //加载我的投诉信息列表 //加载状态集合 ActionContext.getContext().getContextMap().put("complainStateMap", Complain.COMPLAIN_STATE_MAP); QueryHelper queryHelper2 = new QueryHelper(Complain.class, "c"); queryHelper2.addCondition("c.compName = ?", user.getName()); //根据投诉时间升序排序 queryHelper2.addOrderByProperty("c.compTime", QueryHelper.ORDER_BY_ASC); //根据投诉状态降序排序 queryHelper2.addOrderByProperty("c.state", QueryHelper.ORDER_BY_DESC); List<Complain> complainList = complainService.getPageResult(queryHelper2, 1, 6).getItems(); ActionContext.getContext().getContextMap().put("complainList", complainList); return "home"; }
//跳转到我要投诉 public String complainAddUI(){ return "complainAddUI"; }
public void getUserJson(){ try { //1、获取部门 String dept = ServletActionContext.getRequest().getParameter("dept"); if(StringUtils.isNotBlank(dept)){ QueryHelper queryHelper = new QueryHelper(User.class, "u"); queryHelper.addCondition("u.dept like ?", "%" + dept); //2、根据部门查询用户列表 List<User> userList = userService.findObjects(queryHelper); //创建Json对象 JSONObject jso = new JSONObject(); jso.put("msg", "success"); jso.accumulate("userList", userList);
//3、输出用户列表以json格式字符串形式输出 HttpServletResponse response = ServletActionContext.getResponse(); response.setContentType("text/html"); ServletOutputStream outputStream = response.getOutputStream(); outputStream.write(jso.toString().getBytes("utf-8")); outputStream.close(); } } catch (Exception e) { e.printStackTrace(); } }
public String getUserJson2(){ try { //1、获取部门 String dept = ServletActionContext.getRequest().getParameter("dept"); if(StringUtils.isNotBlank(dept)){ QueryHelper queryHelper = new QueryHelper(User.class, "u"); queryHelper.addCondition("u.dept like ?", "%" +dept); //2、根据部门查询用户列表 return_map = new HashMap<String, Object>(); return_map.put("msg", "success"); return_map.put("userList", userService.findObjects(queryHelper)); } } catch (Exception e) { e.printStackTrace(); } return SUCCESS; }
//保存投诉 public void complainAdd(){ try { if(comp != null){ //设置默写投诉状态为 待受理 comp.setState(Complain.COMPLAIN_STATE_UNDONE); comp.setCompTime(new Timestamp(new Date().getTime())); complainService.save(comp);
//输出投诉结果 HttpServletResponse response = ServletActionContext.getResponse(); response.setContentType("text/html"); ServletOutputStream outputStream = response.getOutputStream(); outputStream.write("success".getBytes("utf-8")); outputStream.close();
} } catch (Exception e) { e.printStackTrace(); } }
//查看信息 public String infoViewUI(){ //加载分类集合 ActionContext.getContext().getContextMap().put("infoTypeMap", Info.INFO_TYPE_MAP); if(info != null){ info = infoService.findObjectById(info.getInfoId()); } return "infoViewUI"; }
//查看投诉信息 public String complainViewUI(){ //加载状态集合 ActionContext.getContext().getContextMap().put("complainStateMap", Complain.COMPLAIN_STATE_MAP); if(comp != null){ comp = complainService.findObjectById(comp.getCompId()); } return "complainViewUI"; }
public Map<String, Object> getReturn_map() { return return_map; }
public void setReturn_map(Map<String, Object> return_map) { this.return_map = return_map; }
public Complain getComp() { return comp; }
public void setComp(Complain comp) { this.comp = comp; }
public Info getInfo() { return info; }
public void setInfo(Info info) { this.info = info; } |
1.32,关于懒加载的一些细节
1.32.1,举例
<set name="complainReplies" inverse="true" cascade="save-update,delete" lazy="true" order-by="reply_time">
|
具体解决方法两种,一种就是像上面的把lazy改成false |
另一种情况就是在web.xml中加上这行代码, <filter> <filter-name>openSessionInViewFilter</filter-name> <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class> </filter> <filter-mapping> <filter-name>openSessionInViewFilter</filter-name> <url-pattern>*.action</url-pattern> </filter-mapping> |