纳税服务系统六(信息发布管理模块)【Ueditor、异步信息交互、抽取BaseService、条件查询、分页】...

SpringBoot+Vue+Mysql社区医院信息平台(源码+文档) SpringBoot+Vue+Mysql学生宿舍信息管理系统 WEB端软件项目(源码+文档) 项目包含:①完整源码(后端+管理后台+用户前台);②数据库脚本文件;③万字论文文档;④开题报告;⑤答辩PPT;⑥项目运行视频教程。 项目架构: B/S 架构、MVC 分层设计 技术栈: Java、MySQL、SpringBoot、MyBatis-Plus、Token 权限校验、管理后台 Vue+ElementUI+ECharts、用户前台 Layui+jQuery、Maven 构建。 一、角色设计 学生用户: 注册登录、浏览宿舍信息、查询宿舍安排、在线报修、缴费查询、失物招领、桶装水预订、评论交流、收藏等。 商家用户: 注册登录、桶装水品牌与商品信息维护、预订订单查看与处理。 维修人员: 注册登录、查看待处理报修、接单维修、填写报修处理结果与进度反馈。 管理员: 学生管理、班级管理、宿舍信息管理、宿舍安排管理、报修处理管理、缴费信息管理、卫生检查与文明宿舍管理、失物招领管理、桶装水与商家管理、维修人员管理、公告资讯与轮播图管理等。 二、前台功能模块(学生端) 1. 首页展示:轮播图、宿舍公告、最新动态推荐、常用服务快速入口 2. 宿舍信息模块:宿舍列表、楼栋与房间条件筛选、宿舍详情查看、我的宿舍安排查询 3. 在线报修模块:在线提交宿舍设施报修申请、上传故障描述、查看报修进度与维修处理结果 4. 缴费模块:水电等缴费记录查询、缴费状态查看 5. 卫生检查与文明宿舍:宿舍卫生检查结果公示、文明宿舍展示 6. 失物招领模块:失物信息发布、招领信息发布、详情查看、评论互动 7. 桶装水预订:桶装水品牌与商品浏览、在线预订、我的预订记录查询 8. 假期留宿:假期留校申请提交、申请记录查询 9. 评论与收藏:信息评论、查看他人评论、评论回复互动、收藏感兴趣的内容 10. 个人中心... 立即下载

需求分析

我们现在来到了纳税服务系统的信息发布管理模块,首先我们跟着原型图来进行需求分析把:

一些普通的CRUD,值得一做的就是状态之间的切换了。停用和发布切换。


640?wx_fmt=png

值得注意的是:在信息内容中,它可以带格式地复制内容,然后上传到我们的服务器中。

640?wx_fmt=png

流程图:


640?wx_fmt=png

编写JavaBean与配置文件

javaBean

package zhongfucheng.info.entity;import java.sql.Timestamp;import java.util.HashMap;import java.util.Map;public class Info implements java.io.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 = new HashMap<String, String>();    static {        INFO_TYPE_MAP.put(INFO_TYPE_TZGG, "通知公告");        INFO_TYPE_MAP.put(INFO_TYPE_ZCSD, "政策速递");        INFO_TYPE_MAP.put(INFO_TYPE_NSZD, "纳税指导");    }    public Info() {    }    public Info(String title) {        this.title = title;    }    public Info(String type, String source, String title, String content, String memo, String creator, Timestamp createTime, String state) {        this.type = type;        this.source = source;        this.title = title;        this.content = content;        this.memo = memo;        this.creator = creator;        this.createTime = createTime;        this.state = state;    }    public String getInfoId() {        return this.infoId;    }    public void setInfoId(String infoId) {        this.infoId = infoId;    }    public String getType() {        return this.type;    }    public void setType(String type) {        this.type = type;    }    public String getSource() {        return this.source;    }    public void setSource(String source) {        this.source = source;    }    public String getTitle() {        return this.title;    }    public void setTitle(String title) {        this.title = title;    }    public String getContent() {        return this.content;    }    public void setContent(String content) {        this.content = content;    }    public String getMemo() {        return this.memo;    }    public void setMemo(String memo) {        this.memo = memo;    }    public String getCreator() {        return this.creator;    }    public void setCreator(String creator) {        this.creator = creator;    }    public Timestamp getCreateTime() {        return this.createTime;    }    public void setCreateTime(Timestamp createTime) {        this.createTime = createTime;    }    public String getState() {        return this.state;    }    public void setState(String state) {        this.state = state;    }}

import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Map;

public class Info implements java.io.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 = new HashMap<String, String>();
   static {
       INFO_TYPE_MAP.put(INFO_TYPE_TZGG, "通知公告");
       INFO_TYPE_MAP.put(INFO_TYPE_ZCSD, "政策速递");
       INFO_TYPE_MAP.put(INFO_TYPE_NSZD, "纳税指导");
   }

   public Info() {
   }

   public Info(String title) {
       this.title = title;
   }

   public Info(String type, String source, String title, String content, String memo, String creator, Timestamp createTime, String state) {
       this.type = type;
       this.source = source;
       this.title = title;
       this.content = content;
       this.memo = memo;
       this.creator = creator;
       this.createTime = createTime;
       this.state = state;
   }


   public String getInfoId() {
       return this.infoId;
   }

   public void setInfoId(String infoId) {
       this.infoId = infoId;
   }

   public String getType() {
       return this.type;
   }

   public void setType(String type) {
       this.type = type;
   }

   public String getSource() {
       return this.source;
   }

   public void setSource(String source) {
       this.source = source;
   }

   public String getTitle() {
       return this.title;
   }

   public void setTitle(String title) {
       this.title = title;
   }

   public String getContent() {
       return this.content;
   }

   public void setContent(String content) {
       this.content = content;
   }

   public String getMemo() {
       return this.memo;
   }

   public void setMemo(String memo) {
       this.memo = memo;
   }

   public String getCreator() {
       return this.creator;
   }

   public void setCreator(String creator) {
       this.creator = creator;
   }

   public Timestamp getCreateTime() {
       return this.createTime;
   }

   public void setCreateTime(Timestamp createTime) {
       this.createTime = createTime;
   }

   public String getState() {
       return this.state;
   }

   public void setState(String state) {
       this.state = state;
   }

}

配置文件

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping>    <class name="zhongfucheng.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></hibernate-mapping>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">


<hibernate-mapping>
   <class name="zhongfucheng.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>
</hibernate-mapping>

常规增删改查

这现在对我们来说没有什么难度了,改之前写过的User模块就行了。

编写dao、编写service、编写action、编写配置文件

将配置文件加载到总配置文件中。

导入前端的JSP页面

弄完之后,简单的增删改查我们已经实现了。。

640?wx_fmt=png
这里写图片描述

接下来就是处理一些不是常用增删改查的东西了。

创建人与创建时间

我们在添加的时候怎么写呢???在需求上,不是让我们填的,而是写死的。

<tr>    <td class="tdBg" width="200px">创建人:</td>    <td>    </td>    <td class="tdBg" width="200px">创建时间:</td>    <td>    </td></tr>
   <td class="tdBg" width="200px">创建人:</td>
   <td>

   </td>
   <td class="tdBg" width="200px">创建时间:</td>
   <td>

   </td>
</tr>

创建人我们在Session中找到对应的用户,给出对应的值。显示出来后,在提交的时候还要通过隐藏域把数据带过去

    <tr>        <td class="tdBg" width="200px">创建人:</td>        <td>            <s:property value="#session.SYS_USER.name"/>            <s:hidden value="#session.SYS_USER.name" 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>
       <td class="tdBg" width="200px">创建人:</td>
       <td>
           <s:property value="#session.SYS_USER.name"/>
           <s:hidden value="#session.SYS_USER.name" 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>

创建时间,我们可以直接在InfoAction中,new出Info对象,给出对应的值。在JSP页面就可以回显出来了。

当然了,我们也要通过隐藏域把数据带过去。

    public String addUI() {        ActionContext.getContext().getContextMap().put("infoTypeMap", Info.INFO_TYPE_MAP);        info = new Info();        info.setCreateTime(new Timestamp(new Date().getTime()));        return "addUI";    }

       ActionContext.getContext().getContextMap().put("infoTypeMap", Info.INFO_TYPE_MAP);
       info = new Info();
       info.setCreateTime(new Timestamp(new Date().getTime()));
       return "addUI";
   }

!

640?wx_fmt=png
这里写图片描述

富文本框编辑器

我们想要在那个大文本框中,把复制的内容是带有格式的,图片也可以复制过去。普通的textarea是搞不掂的,我们需要借助别的组件。。我们用的是Ueditor组件

使用步骤:

    "imageUrlPrefix": "http://localhost:8080", /* 图片访问路径前缀 */    "imagePathFormat": "/upload/ueditor/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */"http://localhost:8080", /* 图片访问路径前缀 */
   "imagePathFormat": "/upload/ueditor/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
    <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>        //配置ueditor的根路径        var UEDITOR_HOME_URL = "${basePath}js/ueditor/";        var ue = UE.getEditor('editor');    </script>"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>
       //配置ueditor的根路径
       var UEDITOR_HOME_URL = "${basePath}js/ueditor/";
       var ue = UE.getEditor('editor');
   </script>
    <td colspan="3"><s:textarea id="editor" name="info.content" cssStyle="width:90%;height:160px;" /></td><s:textarea id="editor" name="info.content" cssStyle="width:90%;height:160px;" /></td>

富文本框的配置我们大多数可以在这里修改:

640?wx_fmt=png
这里写图片描述

效果:

640?wx_fmt=png


很奇怪的是,如果单单访问info模块的话,使用是完全没有问题的。但是在总系统进入到info模块时,富文本框就点击不了:输入会显示输入个数,但是显示不了内容。编辑的时候同样看不到内容。

于是在网上搜了一下:把以下的代码加入到要用到富文本框的JSP页面下就解决掉问题了:

<script>    setTimeout(function(){uParse('div',            {                'highlightJsUrl':'/ueditor/third-party/SyntaxHighlighter/shCore.js',                'highlightCssUrl':'/ueditor/third-party/SyntaxHighlighter/shCoreDefault.css'})    },300);</script>function(){uParse('div',
           {
               'highlightJsUrl':'/ueditor/third-party/SyntaxHighlighter/shCore.js',
               'highlightCssUrl':'/ueditor/third-party/SyntaxHighlighter/shCoreDefault.css'})
   },300);
</script>

参考博文:http://blog.youkuaiyun.com/eightwhells/article/details/13314069

异步信息交互

最后地,我们剩下停用与发布这个功能还没完成…

640?wx_fmt=png
这里写图片描述

其实就是一个异步信息交互的实现,当用户点击超链接为停用的时候,就到后台把数据更新,把Info的state变成为0,然后将超链接改成发布。

绑定事件

使用opertor前缀+id定位到我们的span节点中。这肯定是独一无二的。

位于iterator内,直接写state判断就行了。

    <span id="operator_<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>
     <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>

ajax进行交互

注意在拼接字符串的时候,不要有空格………

error:如果出错了,可以提示用户。

function doPublic (infoId,state){            $.ajax(                    {                        url: "${basePath}info/info_doPublic.action",                        data: { "info.infoId": infoId,"info.state": state},                        type: "post",                        success: function (backData) {                            if ("更新成功" == backData) {                                if (state == 0) {//如果用户点击的是停用                                    //将超链接改成发布                                    $("#operator_"+infoId).html("<a href='javascript:doPublic(\""+infoId+"\",1)'>发布</a>");                                    //将显示状态改成是停用                                    $("#show_" + infoId).html("停用");                                }else{//用户点击的是发布                                    //将超链接改成停用                                    $("#operator_"+infoId).html("<a href='javascript:doPublic(\""+infoId +"\",0)'>停用</a>");                                    //将显示状态改成是发布                                    $("#show_" + infoId).html("发布");                                }                            }else {                                alert("更新失败,稍后重试");                            }                        },                        //如果失败了,就提示给用户,不要让用户继续操作了                        error:function () {                            alert("更新失败,稍后重试");                        }                    }            );        }    </script>
           $.ajax(
                   {
                       url: "${basePath}info/info_doPublic.action",
                       data: { "info.infoId": infoId,"info.state": state},
                       type: "post",
                       success: function (backData) {

                           if ("更新成功" == backData) {

                               if (state == 0) {//如果用户点击的是停用

                                   //将超链接改成发布
                                   $("#operator_"+infoId).html("<a href='javascript:doPublic(\""+infoId+"\",1)'>发布</a>");

                                   //将显示状态改成是停用
                                   $("#show_" + infoId).html("停用");

                               }else{//用户点击的是发布

                                   //将超链接改成停用
                                   $("#operator_"+infoId).html("<a href='javascript:doPublic(\""+infoId +"\",0)'>停用</a>");

                                   //将显示状态改成是发布
                                   $("#show_" + infoId).html("发布");
                               }

                           }else {
                               alert("更新失败,稍后重试");
                           }
                       },
                       //如果失败了,就提示给用户,不要让用户继续操作了
                       error:function () {
                           alert("更新失败,稍后重试");
                       }

                   }
           );
       }
   </script>

Action处理

得到用户的id,查询出Info对象的信息,再设置Info对象的属性。

    public void doPublic() {        try {            if (info != null) {                //得到用户带过来的id查询出该对象                Info objectById = infoServiceImpl.findObjectById(info.getInfoId());                //设置它的状态                objectById.setState(info.getState());                //调用service更新数据库                infoServiceImpl.update(objectById);                //返回数据给浏览器                HttpServletResponse response = ServletActionContext.getResponse();                response.setContentType("text/html charset=utf-8");                response.getOutputStream().write("更新成功".getBytes("UTF-8"));            }        } catch (IOException e) {            e.printStackTrace();        }    }
       try {

           if (info != null) {
               //得到用户带过来的id查询出该对象
               Info objectById = infoServiceImpl.findObjectById(info.getInfoId());
               //设置它的状态
               objectById.setState(info.getState());

               //调用service更新数据库
               infoServiceImpl.update(objectById);

               //返回数据给浏览器
               HttpServletResponse response = ServletActionContext.getResponse();
               response.setContentType("text/html charset=utf-8");
               response.getOutputStream().write("更新成功".getBytes("UTF-8"));

           }
       } catch (IOException e) {
           e.printStackTrace();
       }


   }

抽取BaseService

到目前为止,我们已经写了三个模块的开发了。我们已经抽取过了BaseAction、BaseDao,我们这次来看看我们的Service接口。

/** * created by ozc on 2017/5/23. */public interface UserService {    //新增    void save(User user);    //更新    void update(User user);    //根据id删除    void delete(Serializable id);    //根据id查找    User findObjectById(Serializable id);    //查找列表    List<User> findObjects() throws ServiceException;    //导出用户列表    void exportExcel(List<User> userList, ServletOutputStream outputStream);    //导入用户列表    void importExcel(File userExcel, String userExcelFileName);    /**     * 根据帐号和用户id查询用户     *     * @param id      用户ID     * @param account 用户帐号     * @return 用户列表     */    List<User> findAccount(String id, String account);    void saveUserAndRole(User user, String[] userRoleIds);    //通过用户id得到该用户的角色    List<UserRole> findRoleById(String id);    void deleteUserRoleById(String[] userRoleIds);    List<User> findUserByAccountAndPassword(String account, String password);}
public interface UserService {

   //新增
   void save(User user);

   //更新
   void update(User user);

   //根据id删除
   void delete(Serializable id);

   //根据id查找
   User findObjectById(Serializable id);

   //查找列表
   List<User> findObjects() throws ServiceException;

   //导出用户列表
   void exportExcel(List<User> userList, ServletOutputStream outputStream);

   //导入用户列表
   void importExcel(File userExcel, String userExcelFileName);

   /**
    * 根据帐号和用户id查询用户
    *
    * @param id      用户ID
    * @param account 用户帐号
    * @return 用户列表
    */

   List<User> findAccount(String id, String account);

   void saveUserAndRole(User user, String[] userRoleIds);

   //通过用户id得到该用户的角色
   List<UserRole> findRoleById(String id);

   void deleteUserRoleById(String[] userRoleIds);

   List<User> findUserByAccountAndPassword(String account, String password);
}
/** * created by ozc on 2017/5/23. */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() ;}
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() ;
}
/** * Created by ozc on 2017/5/26. */public interface RoleService {    //新增     void save(Role role);    //更新     void update(Role role);    //根据id删除O     void delete(Serializable id);    //根据id查找     Role findObjectById(Serializable id);    //查找列表     List<Role> findObjects()  ;}
public interface RoleService {

   //新增
    void save(Role role);
   //更新
    void update(Role role);
   //根据id删除O
    void delete(Serializable id);
   //根据id查找
    Role findObjectById(Serializable id);
   //查找列表
    List<Role> findObjects()  ;

}

我们可以发现,三个Service接口中都存在着增删改查的方法,这明显就是重复的代码。因此,我们需要将他们进行抽取成一个BaseService。

抽取BaseService

在core模块中添加service包,抽取BaseService

package zhongfucheng.core.service;import java.io.Serializable;import java.util.List;/** * Created by ozc on 2017/6/7. */interface BaseService<T> {    //新增    void save(T entity);    //更新    void update(T entity);    //根据id删除    void delete(Serializable id);    //根据id查找    T findObjectById(Serializable id);    //查找列表    List<T> findObjects();}

import java.io.Serializable;
import java.util.List;

/**
* Created by ozc on 2017/6/7.
*/

interface BaseService<T> {
   //新增
   void save(T entity);

   //更新
   void update(T entity);

   //根据id删除
   void delete(Serializable id);

   //根据id查找
   T findObjectById(Serializable id);

   //查找列表
   List<T> findObjects();
}

我们的Sercive是调用dao层的对象来实现方法的,因为这个Service是代表整个项目的Service,于是应该使用BaseDao

package zhongfucheng.core.service.impl;import zhongfucheng.core.dao.BaseDao;import zhongfucheng.core.service.BaseService;import java.io.Serializable;import java.util.List;/** * Created by ozc on 2017/6/7. */public abstract class BaseServiceImpl <T> implements BaseService <T>{    //通过BaseDao来操作数据库    private BaseDao<T> 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();    }}

import zhongfucheng.core.dao.BaseDao;
import zhongfucheng.core.service.BaseService;

import java.io.Serializable;
import java.util.List;

/**
* Created by ozc on 2017/6/7.
*/


public abstract class BaseServiceImpl <T> implements BaseService <T>{

   //通过BaseDao来操作数据库
   private BaseDao<T> 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();

   }
}

以Info模块举例子

InfoService继承了BaseService接口,于是就有了增删改查的方法。同时把泛型T的类型确定下来。

    /**     * created by ozc on 2017/5/23.     */    public interface InfoService extends BaseService<Info> {    }
   public interface InfoService extends BaseService<Info> {

   }

继承了InfoService,有了增删该查的方法,然而具体的操作是BaseServiceImpl中实现的。我们继承它,并给出泛型T对应的类型。

@Servicepublic class InfoServiceImpl extends BaseServiceImpl<Info> implements InfoService {}
public class InfoServiceImpl extends BaseServiceImpl<Info> implements InfoService {


}

现在的问题是什么呢???我们在BaseServiceImpl中使用了BaseDao这个变量来对数据库进行操作。可是在BaseServiceImpl中是没有BaseDao这个变量的。

首先,要明确的是,我们不能在BaseServiceImpl中注入BaseDao,因为BaseServiceImpl本身就是一个抽象类。那我们怎么对BaseDao进行实例化呢???

我们可以这样做:

@Servicepublic class InfoServiceImpl extends BaseServiceImpl<Info> implements InfoService {    private InfoDao infoDao;    @Resource    public void setInfoDao(InfoDao infoDao) {        super.setBaseDao(infoDao);        this.infoDao = infoDao;    }}
public class InfoServiceImpl extends BaseServiceImpl<Info> implements InfoService {

   private InfoDao infoDao;
   @Resource
   public void setInfoDao(InfoDao infoDao) {
       super.setBaseDao(infoDao);
       this.infoDao = infoDao;
   }
}
   //通过BaseDao来操作数据库    private BaseDao<T> baseDao;    public void setBaseDao(BaseDao<T> baseDao) {        this.baseDao = baseDao;    }
   private BaseDao<T> baseDao;
   public void setBaseDao(BaseDao<T> baseDao) {
       this.baseDao = baseDao;
   }

条件查询

我们来实现下面的功能:

640?wx_fmt=png
这里写图片描述

传统方式

其实也是一个查询,只不过查询多了一个条件罢了。按照传统的方式我们可以这样做:

    //根据条件查询列表    List<T> findObjects(String sql, List<Object> objectList);
   List<T> findObjects(String sql, List<Object> objectList);
    @Override    public List<T> findObjects(String sql, List<Object> objectList) {        Query query = getSession().createQuery(sql);        if (objectList != null) {            int i =0;            for (Object o : objectList) {                query.setParameter(i, o);                i++;            }            return query.list();        }        return query.list();    }
   public List<T> findObjects(String sql, List<Object> objectList) {

       Query query = getSession().createQuery(sql);
       if (objectList != null) {
           int i =0;
           for (Object o : objectList) {
               query.setParameter(i, o);
               i++;
           }
           return query.list();
       }
       return query.list();
   }
    //根据条件查询列表    List<T> findObjects(String sql, List<Object> objectList);
   List<T> findObjects(String sql, List<Object> objectList);
    @Override    public List<T> findObjects(String sql, List<Object> objectList) {        return baseDao.findObjects(sql, objectList);    }
   public List<T> findObjects(String sql, List<Object> objectList) {
       return baseDao.findObjects(sql, objectList);
   }

我们还是用着listUI这个方法,因为它仅仅是参数可能不同。

    public String listUI() {        //查询语句        String hql = "FROM Info i ";        List<Object> objectList  = new ArrayList<>();        //根据info是否为null来判断是否是条件查询。如果info为空,那么是查询所有。        if (info != null) {            if (StringUtils.isNotBlank(info.getTitle())) {                hql += "where i.title like ?";                objectList.add("%" + info.getTitle() + "%");            }        }        infoList = infoServiceImpl.findObjects(hql,objectList);        ActionContext.getContext().getContextMap().put("infoTypeMap", Info.INFO_TYPE_MAP);        return "listUI";    }

       //查询语句
       String hql = "FROM Info i ";
       List<Object> objectList  = new ArrayList<>();

       //根据info是否为null来判断是否是条件查询。如果info为空,那么是查询所有。
       if (info != null) {
           if (StringUtils.isNotBlank(info.getTitle())) {
               hql += "where i.title like ?";
               objectList.add("%" + info.getTitle() + "%");
           }
       }
       infoList = infoServiceImpl.findObjects(hql,objectList);
       ActionContext.getContext().getContextMap().put("infoTypeMap", Info.INFO_TYPE_MAP);
       return "listUI";
   }

优化

看回我们Action中的代码,我们可以看出一些不够优雅的地方:

640?wx_fmt=png
这里写图片描述

于是,我们想要用一个工具类来把上面的代码进行优化。

针对上面的问题,我们发现手写拼接SQL很容易出错。那我们可以在工具类里面拼接,使用的时候调用方法获取就行啦。查询的对象写死了,我们要可以处理任何的查询。。

我们能够找到如下的规律:

    FROM Info     WHERE title like ? and state = ?     order by createTime,state    条件查询(QueryHelper):    1、查询条件语句hql:    from 子句:必定出现;而且只出现一次    where 子句:可选;但关键字where 出现一次;可添加多个查询条件    order by子句:可选;但关键字order by 出现一次;可添加多个排序属性    2、查询条件值集合:    出现时机:在添加查询条件的时候,?对应的查询条件值
   order by createTime,state


   条件查询(QueryHelper):

   1、查询条件语句hql:
   from 子句:必定出现;而且只出现一次
   where 子句:可选;但关键字where 出现一次;可添加多个查询条件
   order by子句:可选;但关键字order by 出现一次;可添加多个排序属性

   2、查询条件值集合:
   出现时机:在添加查询条件的时候,?对应的查询条件值
package zhongfucheng.core.utils;import java.util.ArrayList;import java.util.List;/** * Created by ozc on 2017/6/7. */public class QueryHelper {    private String fromClause = "";    private String whereClause = "";    private String orderbyClause = "";    private List<Object> objectList;    public static String ORDER_BY_ASC = "asc";    public static String ORDER_BY_DESC = "desc";    //FROM子句只出现一次    /**     * 构建FROM字句,并设置查询哪张表     * @param aClass 用户想要操作的类型     * @param alias  别名     */    public QueryHelper(Class aClass, String alias) {        fromClause = "  FROM " + aClass.getSimpleName() + "  " + alias;    }    //WHERE字句可以添加多个条件,但WHERE关键字只出现一次    /**     * 构建WHERE字句     * @param condition     * @param objects     * @return     */    public QueryHelper addCondition(String condition, Object... objects) {        //如果已经有字符了,那么就说明已经有WHERE关键字了        if (whereClause.length() > 0) {            whereClause += " AND  " + condition;        } else {            whereClause += " WHERE" + condition;        }        //在添加查询条件的时候,?对应的查询条件值        if (objects == null) {            objectList = new ArrayList<>();        }        for (Object object : objects) {            objectList.add(object);        }        return this;    }    /**     *     * @param property 要排序的属性     * @param order 是升序还是降序     * @return     */    public QueryHelper orderBy(String property, String order) {        //如果已经有字符了,那么就说明已经有ORDER关键字了        if (orderbyClause.length() > 0) {            orderbyClause += " ,  " + property +"   " + order;        } else {            orderbyClause += "  ORDER BY " + property+"   " + order;        }        return this;    }    /**     * 返回HQL语句     */    public String returnHQL() {        return fromClause + whereClause + orderbyClause;    }    /**     * 得到参数列表     * @return     */    public List<Object> getObjectList() {        return objectList;    }}

import java.util.ArrayList;
import java.util.List;

/**
* Created by ozc on 2017/6/7.
*/

public class QueryHelper {

   private String fromClause = "";
   private String whereClause = "";
   private String orderbyClause = "";
   private List<Object> objectList;

   public static String ORDER_BY_ASC = "asc";
   public static String ORDER_BY_DESC = "desc";



   //FROM子句只出现一次
   /**
    * 构建FROM字句,并设置查询哪张表
    * @param aClass 用户想要操作的类型
    * @param alias  别名
    */

   public QueryHelper(Class aClass, String alias) {
       fromClause = "  FROM " + aClass.getSimpleName() + "  " + alias;
   }
   //WHERE字句可以添加多个条件,但WHERE关键字只出现一次
   /**
    * 构建WHERE字句
    * @param condition
    * @param objects
    * @return
    */

   public QueryHelper addCondition(String condition, Object... objects) {
       //如果已经有字符了,那么就说明已经有WHERE关键字了
       if (whereClause.length() > 0) {
           whereClause += " AND  " + condition;
       } else {
           whereClause += " WHERE" + condition;
       }
       //在添加查询条件的时候,?对应的查询条件值
       if (objects == null) {
           objectList = new ArrayList<>();
       }

       for (Object object : objects) {
           objectList.add(object);
       }

       return this;
   }
   /**
    *
    * @param property 要排序的属性
    * @param order 是升序还是降序
    * @return
    */

   public QueryHelper orderBy(String property, String order) {

       //如果已经有字符了,那么就说明已经有ORDER关键字了
       if (orderbyClause.length() > 0) {
           orderbyClause += " ,  " + property +"   " + order;
       } else {
           orderbyClause += "  ORDER BY " + property+"   " + order;
       }
       return this;
   }

   /**
    * 返回HQL语句
    */

   public String returnHQL() {
       return fromClause + whereClause + orderbyClause;
   }

   /**
    * 得到参数列表
    * @return
    */

   public List<Object> getObjectList() {
       return objectList;
   }
}
    public String listUI() {        QueryHelper queryHelper = new QueryHelper(Info.class, "i");        //根据info是否为null来判断是否是条件查询。如果info为空,那么是查询所有。        if (info != null) {            if (StringUtils.isNotBlank(info.getTitle())) {                queryHelper.addCondition(" i.title like ? ", "%" + info.getTitle() + "%");            }        }        queryHelper.orderBy("i.createTime", QueryHelper.ORDER_BY_DESC);        infoList = infoServiceImpl.findObjects(queryHelper);        //infoList = infoServiceImpl.findObjects(hql,objectList);        ActionContext.getContext().getContextMap().put("infoTypeMap", Info.INFO_TYPE_MAP);        return "listUI";    }

       QueryHelper queryHelper = new QueryHelper(Info.class, "i");

       //根据info是否为null来判断是否是条件查询。如果info为空,那么是查询所有。
       if (info != null) {
           if (StringUtils.isNotBlank(info.getTitle())) {
               queryHelper.addCondition(" i.title like ? ", "%" + info.getTitle() + "%");
           }
       }
       queryHelper.orderBy("i.createTime", QueryHelper.ORDER_BY_DESC);

       infoList = infoServiceImpl.findObjects(queryHelper);

       //infoList = infoServiceImpl.findObjects(hql,objectList);
       ActionContext.getContext().getContextMap().put("infoTypeMap", Info.INFO_TYPE_MAP);
       return "listUI";
   }

数据回显

前面我们已经完成了条件查询的功能,可以根据用户给出的条件进行查询数据。但是呢,还是有一些小毛病的。我们来看看:

640?wx_fmt=gif
这里写图片描述

当我们查询数据时候,对查询出来的数据进行操作。操作完毕后,它回到的不是我们查询后的数据,而是我们的初始化数据。这明显是不合适的,当用户操作完后,我们应该返回的还是条件查询出来的数据。

还有一点的就是:我们的分页还没写……因此,下面主要解决这两个问题。

首先,我们来分析一下为什么我们操作完毕后,得到的是初始化的数据。我们按照用户的操作来看看到底哪里出了问题。

  1. 用户按条件查询数据,显示查询后的数据

  2. 用户点击编辑/删除对查询后的数据操作,交给Action处理

  3. Action返回给显示页面jsp

  4. JSP页面提交请求到Action中,Action进行处理

  5. 最后Action重定向到listUI

那么在这个过程,我们遇到什么问题呢???

640?wx_fmt=png
这里写图片描述

处理1.0

在Action中使用一个变量封装着查询条件

    /************获取查询条件的值*************************/    private String selectCondition;    public String getSelectCondition() {        return selectCondition;    }    public void setSelectCondition(String selectCondition) {        this.selectCondition = selectCondition;    }
   private String selectCondition;
   public String getSelectCondition() {
       return selectCondition;
   }
   public void setSelectCondition(String selectCondition) {
       this.selectCondition = selectCondition;
   }

当请求到Action时,我们将查询条件的值取出来,发给对应的JSP页面

    public String editUI() {        //得到所有的信息类型        ActionContext.getContext().getContextMap().put("infoTypeMap", Info.INFO_TYPE_MAP);        //外边已经传了id过来了,我们要找到id对应的Info        if (info != null && info.getInfoId() != null) {            //把查询条件发给JSP页面            ActionContext.getContext().getContextMap().put("selectCondition", info.getTitle());            //直接获取出来,后面JSP会根据Info有getter就能读取对应的信息!            info = infoServiceImpl.findObjectById(info.getInfoId());        }        return "editUI";    }

       //得到所有的信息类型
       ActionContext.getContext().getContextMap().put("infoTypeMap", Info.INFO_TYPE_MAP);
       //外边已经传了id过来了,我们要找到id对应的Info
       if (info != null && info.getInfoId() != null) {

           //把查询条件发给JSP页面
           ActionContext.getContext().getContextMap().put("selectCondition", info.getTitle());

           //直接获取出来,后面JSP会根据Info有getter就能读取对应的信息!
           info = infoServiceImpl.findObjectById(info.getInfoId());

       }
       return "editUI";
   }

JSP页面把发送过来的值存储好,通过隐藏域发送给Action

    <%--把查询条件带过去给Action--%>    <s:hidden name="selectCondition"/>
   <s:hidden name="selectCondition"/>

重新抵达到Action的时候,由于Struts2有自动封装的功能,所以可以把查询条件封装到selectCondition变量中。最后操作完重定向到listUI界面

由于是重定向,所以我们需要在struts配置文件中把我们的查询条件带过去:

    <result name="list" type="redirectAction">        <param name="actionName">info_listUI</param>        <!--重定向回去的时候,把查询条件带上-->        <param name="info.title">${selectCondition}</param>    </result>
       <param name="actionName">info_listUI</param>

       <!--重定向回去的时候,把查询条件带上-->
       <param name="info.title">${selectCondition}</param>
   </result>

当然啦,在删除的时候,把查询条件记录下来就行了。

    //删除    public String delete() {        selectCondition = info.getTitle();        String id = info.getInfoId();        infoServiceImpl.delete(id);        return "list";    }
   public String delete() {
       selectCondition = info.getTitle();
       String id = info.getInfoId();
       infoServiceImpl.delete(id);
       return "list";
   }


处理2.0

上面我们的确解决了查询后数据回显的情况,但是如果我们的查询条件是中文的话,会怎么样??

640?wx_fmt=png
这里写图片描述

变成了乱码了…..在解决它之前,我们又来分析一下为什么出现乱码了….

        <!--传输数据的时候需要编码-->        <param name="encode">true</param>
       <param name="encode">true</param>
    if (info != null) {        if (StringUtils.isNotBlank(info.getTitle())) {            selectCondition =  URLDecoder.decode(info.getTitle(),"UTF-8");            info.setTitle(selectCondition);            queryHelper.addCondition(" i.title like ? ", "%" + info.getTitle() + "%");        }    }null) {
       if (StringUtils.isNotBlank(info.getTitle())) {
           selectCondition =  URLDecoder.decode(info.getTitle(),"UTF-8");
           info.setTitle(selectCondition);

           queryHelper.addCondition(" i.title like ? ", "%" + info.getTitle() + "%");
       }
   }

分页

分页对我们来说也不是陌生的事情了,我曾经在写JDBC博文的时候就讲解过分页了:http://blog.youkuaiyun.com/hon_3y/article/details/53790092

分页的复用代码http://blog.youkuaiyun.com/hon_3y/article/details/70051541

我们这一次还是使用回我们的分页复用代码,具体不同的需求,在上面修改即可了。

在dao和daoImpl中添加方法

    /**     *     * @param queryHelper 查询助手,条件查询都交给查询助手来干     * @param currentPage 当前页数     * @return     */    PageResult getPageResult(QueryHelper queryHelper, int currentPage);
   PageResult getPageResult(QueryHelper queryHelper, int currentPage);
    /**     *     * @return 返回查询总记录数的sql语句     */    public String getTotalRecordSql() {        return "SELECT COUNT(*) " + fromClause + whereClause;    }
   public String getTotalRecordSql() {
       return "SELECT COUNT(*) " + fromClause + whereClause;
   }
    public PageResult getPageResult(QueryHelper queryHelper, int currentPage) {        //查询总记录数        Query queryCount = getSession().createQuery(queryHelper.getTotalRecordSql());        if (queryHelper.getObjectList() != null) {            int i =0;            for (Object o : queryHelper.getObjectList()) {                queryCount.setParameter(i, o);                i++;            }        }        Long totalRecord = (Long) queryCount.uniqueResult();        //初始化PageResult对象        PageResult pageResult = new PageResult(currentPage, totalRecord);        //查询具体模块的数据【有查询条件的也可以处理】        Query query = getSession().createQuery(queryHelper.returnHQL());        if (queryHelper.getObjectList() != null) {            int i =0;            for (Object o : queryHelper.getObjectList()) {                query.setParameter(i, o);                i++;            }        }        //设置分页开始和末尾        query.setFirstResult(pageResult.getStartIndex());        query.setMaxResults(pageResult.getLineSize());        List dataList = query.list();        //将条件查询出来的数据设置到Page对象中        pageResult.setList(dataList);        return pageResult;    }

       //查询总记录数
       Query queryCount = getSession().createQuery(queryHelper.getTotalRecordSql());
       if (queryHelper.getObjectList() != null) {
           int i =0;
           for (Object o : queryHelper.getObjectList()) {
               queryCount.setParameter(i, o);
               i++;
           }
       }
       Long totalRecord = (Long) queryCount.uniqueResult();

       //初始化PageResult对象
       PageResult pageResult = new PageResult(currentPage, totalRecord);

       //查询具体模块的数据【有查询条件的也可以处理】
       Query query = getSession().createQuery(queryHelper.returnHQL());
       if (queryHelper.getObjectList() != null) {
           int i =0;
           for (Object o : queryHelper.getObjectList()) {
               query.setParameter(i, o);
               i++;
           }
       }


       //设置分页开始和末尾
       query.setFirstResult(pageResult.getStartIndex());
       query.setMaxResults(pageResult.getLineSize());
       List dataList = query.list();

       //将条件查询出来的数据设置到Page对象中
       pageResult.setList(dataList);
       return pageResult;
   }

在service和serviceImpl中添加方法

    PageResult getPageResult(QueryHelper queryHelper, int currentPage);
    public PageResult getPageResult(QueryHelper queryHelper, int currentPage) {        return baseDao.getPageResult(queryHelper, currentPage);    }
       return baseDao.getPageResult(queryHelper, currentPage);
   }

在Action中调用service的方法

设置我们需要用到的分页属性。

    private int currentPageCount;    private PageResult pageResult;    public int getCurrentPageCount() {        return currentPageCount;    }    public void setCurrentPageCount(int currentPageCount) {        this.currentPageCount = currentPageCount;    }    public PageResult getPageResult() {        return pageResult;    }    public void setPageResult(PageResult pageResult) {        this.pageResult = pageResult;    }int currentPageCount;
   private PageResult pageResult;
   public int getCurrentPageCount() {
       return currentPageCount;
   }
   public void setCurrentPageCount(int currentPageCount) {
       this.currentPageCount = currentPageCount;
   }
   public PageResult getPageResult() {
       return pageResult;
   }
   public void setPageResult(PageResult pageResult) {
       this.pageResult = pageResult;
   }

判断我们的当前页是否为0【如果为0,就代表着刚初始化值,我们设置为1】,调用service的方法得到分页对象

    //当前页数没有值,那么赋值为1    if (currentPageCount == 0) {        currentPageCount = 1;    }    pageResult = infoServiceImpl.getPageResult(queryHelper,currentPageCount);
   if (currentPageCount == 0) {
       currentPageCount = 1;
   }
   pageResult = infoServiceImpl.getPageResult(queryHelper,currentPageCount);

在JSP页面中,我们遍历分页对象的集合就可以获取分页的数据了。

   <s:iterator value="pageResult.list" status="st">

抽取属性

我们的分页属性和查询条件数据不单单只有Info模块用的,于是我们将分页数据抽取到BaseAction中

    /************分页属性*************************/    protected int currentPageCount;    protected PageResult pageResult;    public int getCurrentPageCount() {        return currentPageCount;    }    public void setCurrentPageCount(int currentPageCount) {        this.currentPageCount = currentPageCount;    }    public PageResult getPageResult() {        return pageResult;    }    public void setPageResult(PageResult pageResult) {        this.pageResult = pageResult;    }    /************获取查询条件的值*************************/    protected String selectCondition;    public String getSelectCondition() {        return selectCondition;    }    public void setSelectCondition(String selectCondition) {        this.selectCondition = selectCondition;    }
   protected int currentPageCount;
   protected PageResult pageResult;
   public int getCurrentPageCount() {
       return currentPageCount;
   }
   public void setCurrentPageCount(int currentPageCount) {
       this.currentPageCount = currentPageCount;
   }
   public PageResult getPageResult() {
       return pageResult;
   }
   public void setPageResult(PageResult pageResult) {
       this.pageResult = pageResult;
   }

   /************获取查询条件的值*************************/
   protected String selectCondition;
   public String getSelectCondition() {
       return selectCondition;
   }
   public void setSelectCondition(String selectCondition) {
       this.selectCondition = selectCondition;
   }

修改其他的模块,也能够拥有条件查询和分页查询这两个功能:以用户模块为例。

    //抛出Action异常    public String listUI() throws ServiceException, UnsupportedEncodingException {        QueryHelper queryHelper = new QueryHelper(User.class, "u");        //根据info是否为null来判断是否是条件查询。如果info为空,那么是查询所有。        if (user != null) {            if (org.apache.commons.lang.StringUtils.isNotBlank(user.getName())) {                selectCondition =  URLDecoder.decode(user.getName(),"UTF-8");                user.setName(selectCondition);                queryHelper.addCondition(" u.name like ? ", "%" + user.getName() + "%");            }        }        //当前页数没有值,那么赋值为1        if (currentPageCount == 0) {            currentPageCount = 1;        }        pageResult = userServiceImpl.getPageResult(queryHelper,currentPageCount);        return "listUI";    }
   public String listUI() throws ServiceException, UnsupportedEncodingException {
       QueryHelper queryHelper = new QueryHelper(User.class, "u");
       //根据info是否为null来判断是否是条件查询。如果info为空,那么是查询所有。
       if (user != null) {
           if (org.apache.commons.lang.StringUtils.isNotBlank(user.getName())) {
               selectCondition =  URLDecoder.decode(user.getName(),"UTF-8");
               user.setName(selectCondition);
               queryHelper.addCondition(" u.name like ? ", "%" + user.getName() + "%");
           }
       }
       //当前页数没有值,那么赋值为1
       if (currentPageCount == 0) {
           currentPageCount = 1;
       }
       pageResult = userServiceImpl.getPageResult(queryHelper,currentPageCount);
       return "listUI";
   }
        <s:iterator value="pageResult.list">          <jsp:include page="/common/pageNavigator.jsp"/>
         <jsp:include page="/common/pageNavigator.jsp"/>

处理查询后数据回显的问题:

    public String editUI() {        //把所有的角色查询出来,带过去给JSP页面显示        ActionContext.getContext().getContextMap().put("roleList", roleServiceImpl.findObjects());        //外边已经传了id过来了,我们要找到id对应的User        if (user != null &&user.getId() != null  ) {            //得到查询条件            selectCondition = user.getName();            //直接获取出来,后面JSP会根据User有getter就能读取对应的信息!            user = userServiceImpl.findObjectById(user.getId());            //通过用户的id得到所拥有UserRole            List<UserRole> roles = userServiceImpl.findRoleById(user.getId());            //把用户拥有角色的id填充到数组中,数组最后回显到JSP页面            int i=0;            userRoleIds =  new String[roles.size()];            for (UserRole role : roles) {                userRoleIds[i++] = role.getUserRoleId().getRole().getRoleId();            }        }        return "editUI";    }

       //把所有的角色查询出来,带过去给JSP页面显示
       ActionContext.getContext().getContextMap().put("roleList", roleServiceImpl.findObjects());

       //外边已经传了id过来了,我们要找到id对应的User
       if (user != null &&user.getId() != null  ) {

           //得到查询条件
           selectCondition = user.getName();

           //直接获取出来,后面JSP会根据User有getter就能读取对应的信息!
           user = userServiceImpl.findObjectById(user.getId());

           //通过用户的id得到所拥有UserRole
           List<UserRole> roles = userServiceImpl.findRoleById(user.getId());
           //把用户拥有角色的id填充到数组中,数组最后回显到JSP页面
           int i=0;
           userRoleIds =  new String[roles.size()];
           for (UserRole role : roles) {
               userRoleIds[i++] = role.getUserRoleId().getRole().getRoleId();
           }

       }
       return "editUI";
   }
    <%--把查询条件通过隐藏域带过去给Action--%>    <s:hidden name="selectCondition"></s:hidden>
   <s:hidden name="selectCondition"></s:hidden>
        <action name="user_*" class="zhongfucheng.user.action.UserAction" method="{1}">            <result name="{1}" >/WEB-INF/jsp/user/{1}.jsp</result>            <!--返回列表展示页面,重定向到列表展示-->            <result name="list" type="redirectAction">                <param name="actionName">user_listUI</param>                <param name="user.name">${selectCondition}</param>                <param name="encode">true</param>            </result>        </action>
           <result name="{1}" >/WEB-INF/jsp/user/{1}.jsp</result>

           <!--返回列表展示页面,重定向到列表展示-->
           <result name="list" type="redirectAction">
               <param name="actionName">user_listUI</param>
               <param name="user.name">${selectCondition}</param>
               <param name="encode">true</param>
           </result>
       </action>
    //删除    public String delete() {        if (user != null && user.getId() != null) {            //记载着查询条件            selectCondition = user.getName();            userServiceImpl.delete(user.getId());        }        return "list";    }
   public String delete() {
       if (user != null && user.getId() != null) {

           //记载着查询条件
           selectCondition = user.getName();

           userServiceImpl.delete(user.getId());
       }
       return "list";
   }

总结

如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章,想要获取更多的Java资源的同学,可以关注微信公众号:Java3y


YOLOv8作物病害检测实战源码 这是一套基于YOLOv8n的农田病虫害目标检测系统,对叶片照片做目标检测,识别健康叶片、褐斑病、白粉病、锈病四类,并给出对应防治建议。全流程纯CPU可跑,配套交付完整Python源码、9章实战教程(md/html/pdf三种格式)、100张自造样本及YOLO标签、训练曲线与混淆矩阵截图、Tkinter界面和答辩PPT。 系统围绕五项功能展开:同一套推理逻辑覆盖图像、视频、摄像头三种来源;图形界面选文件即检测,画面叠彩色框标注病名与置信度,右侧面板同步给出症状与防治措施;检测记录自动写入CSV,统计页一键生成四类病害占比饼图;训练结束自动产出损失与精度曲线;内置防治建议文案库,检测命中即回填面板。 选型用YOLOv8n nano档,参数量约320万、权重约6.2MB,CPU单帧几十毫秒,小样本训练5到8分钟完成。数据由data_gen.py程序化绘制100张叶片图,固定随机种子,重跑分布一致,不依赖公开数据集。依赖全部锁版本,教程第7章整理了19条真实报错及排查方法,第8章给出换模型档、换PlantVillage数据集的迁移路径。 适合做计算机视觉方向课程设计或毕业设计的学生,也适合智慧农业方向想了解检测模型如何落进业务面板的学习者。不需要GPU,不需要系统学过目标检测,教程第3章会按需补齐原理。 使用时先pip install -r requirements.txt装好依赖,download_data.py下载预训练权重,data_gen.py生成样本后train.py训练,完成后用main.py infer批量检测或main.py gui启动界面。 立即下载

相关推荐

数据挖掘实战:决策树 + 聚类 + 关联规则,零 Key 离线可跑(Python 源码)

数据挖掘实战包。用 Python 标准库实现 CART 风格决策树、K-Means 聚类与 Apriori 关联规则,在虚构「星河便利店」会员表和购物篮上跑通分类、分群与购物篮分析,并给出准确率、轮廓系数、支持度/置信度/提升度。零第三方依赖、零 API Key 即可离线跑通。含 4 个样例、离线冒烟、中文 README(含「使用方法」)。均为作者原创可运行源码。MIT。作者 blog.csdn.net/mtl1994

产业园区运营负责人如何利用平台实现企业创新需求的精准分析与服务推送?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

科技中介服务机构在技术供需对接中如何实现服务流程的自动化与标准化?.docx

科技中介服务机构在技术供需对接中如何实现服务流程的自动化与标准化?

高校技术转移办公室人员在推动成果转化落地过程中,如何实现科技成果的高效推介与价值评估?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

产业园区如何高效对接企业技术需求与高校科研成果?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

国央企创新负责人如何快速掌握本地科技资源分布与匹配情况?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

科技中介服务机构如何通过数智工具提升技术需求挖掘的精准度?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

国央企创新负责人如何实现科技成果的精准识别与高效筛选?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

政府科技管理者如何在政策支持中更精准地识别和支持高价值科技项目?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

高校技术转移办公室人员如何系统化管理科技成果信息?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

科技中介服务机构如何构建标准化、模块化的智能服务工具?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

全桥LLC谐振变化器参数设计资料(闭环仿真+参数设计报告)

内容概要:本文档系统性地介绍了全桥LLC谐振变换器的闭环仿真建模与关键参数设计方法,涵盖其工作原理、谐振元件(如谐振电感、谐振电容、励磁电感)的计算与优化流程,并结合Simulink或Plecs等仿真平台构建闭环控制系统模型,重点验证变频控制策略下的软开关实现、系统增益特性、效率优化及动态响应性能。资料包含完整的仿真模型、参数设计报告、数学计算书及参考文献,支持从理论分析到工程实践的全流程研究,适用于高频高效DC-DC变换器的研发与教学应用。; 适合人群:电力电子、电气工程及其自动化等相关专业的高校学生、科研人员,以及从事开关电源、新能源变换器、工业电源研发的工程技术人员,具备电路拓扑基础与仿真软件操作能力者更佳。; 使用场景及目标:①深入掌握全桥LLC谐振变换器的工作机理与谐振参数设计准则;②学习并实现闭环反馈控制系统的建模与稳定性分析;③支撑科研课题、课程设计、毕业设计或实际产品开发中的拓扑选型与性能验证需求;④通过仿真与计算联动提升对软开关技术与效率优化的理解与应用能力。; 阅读建议:建议结合所提供的仿真文件与设计文档同步操作,按照“建模—参数计算—仿真验证—性能分析”的流程逐步推进,重点关注频率调节对ZVS/ZCS实现的影响,对比不同负载条件下的闭环响应差异,深化对谐振腔特性和控制策略协同作用的理解。

fab-pm-optimizer-python-entry-py39-20261021-v1-1-0

fab-pm-optimizer-python-entry-py39-20261021-v1-1-0

政府科技管理者如何提升区域科技成果转化项目的评价与筛选效率?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

PSIM-三相维也纳VIENNA整流器电压电流双闭环+中点电位平衡SVPWM控制仿真

内容概要:本文档详细介绍了一种基于PSIM软件实现的三相维也纳(VIENNA)整流器仿真模型,重点实现了电压电流双闭环控制与中点电位平衡的SVPWM调制策略。该仿真系统通过精确的控制算法有效提升了整流器的功率因数,降低了输入电流谐波含量,并解决了三电平拓扑中常见的直流侧中点电位偏移问题,具有较高的工程实用价值,适用于高效率、高功率密度的电力电子系统设计与科研验证。文档还整合了丰富的配套资源,涵盖多种电力电子变换器拓扑结构、先进控制算法及典型应用场景,形成了系统化的技术资料体系,有助于深入理解现代整流技术的核心原理与发展动态。; 适合人群:面向从事电力电子、电气工程、新能源变换系统等领域的科研人员、高校研究生以及具备一定仿真基础的工程技术人员。; 使用场景及目标:①深入研究三相VIENNA整流器的工作机理与控制特性;②掌握电压外环、电流内环双闭环控制结构的设计方法;③理解并实现SVPWM调制技术与中点电位平衡控制策略的协同作用;④开展相关控制算法的仿真验证、性能优化与实验对比,为高性能整流装置的研发提供理论支撑和技术原型。; 阅读建议:建议结合文中列出的其他仿真案例(如PWM整流器、LLC谐振变换器、DAB变换器等)进行横向对比学习,充分利用所提供的PSIM、MATLAB/Simulink等多平台仿真资源,重点关注控制逻辑与主电路的耦合关系,通过参数调试与波形分析深化对系统动态响应和稳态性能的理解,强化“理论—建模—仿真—优化”的闭环研究能力。

产业园区运营负责人如何利用数智工具提升园区企业的技术对接效率?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

jp-host-release.apk

jp-host-release.apk

ICD10 openGauss版

ICD10 openGauss版

上一篇: 纳税服务系统五(登陆与系统拦截)【配置系统、子系统首页、登陆与拦截】...
下一篇: 纳税服务系统总结
Java3y
Java3y 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 1万+粉丝 509原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值