day39_Spring學習筆記_07_CRM_03

10、課程類別的分頁(含條件)

10.一、流程分析

10.二、PageBean 實現分析

PageBean.javajavascript

package com.itheima.crm.page;

import java.util.List;

public class PageBean<T{

    /*
    算法1:
        if(totalRecord % pageSize == 0) {
          totalPage = totalRecord / pageSize;
        } else { // 半頁
          totalPage = totalRecord / pageSize + 1;
        }
      算法2:
        totalPage = (totalRecord + (pageSize - 1)) / pageSize;
     */


    // 必須項
    private int pageNum;        // 第幾頁(當前頁)
    private int pageSize;       // 每頁顯示個數(固定值)
    private int totalRecord;    // 總記錄數(查詢數據庫)

    // 計算項
    private int startIndex;     // 開始索引(計算)
    private int totalPage;      // 總分頁數(計算)

    // 分頁數據
    private List<T> data;       // 傳過來什麼就是什麼

    // 含參構造(含有3個參數的構造方法,這樣就能告訴使用者須要這三個必選項)
    public PageBean(int pageNum, int pageSize, int totalRecord) {
        super();
        this.pageNum = pageNum;
        this.pageSize = pageSize;
        this.totalRecord = totalRecord;

        // 計算項
        // 一、開始索引(索引從0開始)
        this.startIndex = (this.pageNum -1) * this.pageSize;
        // 二、總分頁數
        this.totalPage = (this.totalRecord + (this.pageSize - 1)) / this.pageSize;
    }

    public int getPageNum() {
        return pageNum;
    }

    public void setPageNum(int pageNum) {
        this.pageNum = pageNum;
    }

    public int getPageSize() {
        return pageSize;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    public int getTotalRecord() {
        return totalRecord;
    }

    public void setTotalRecord(int totalRecord) {
        this.totalRecord = totalRecord;
    }

    public int getStartIndex() {
        return startIndex;
    }

    public void setStartIndex(int startIndex) {
        this.startIndex = startIndex;
    }

    public int getTotalPage() {
        return totalPage;
    }

    public void setTotalPage(int totalPage) {
        this.totalPage = totalPage;
    }

    public List<T> getData() {
        return data;
    }

    public void setData(List<T> data) {
        this.data = data;
    }
}

10.三、dao層 實現分析


自定義實現類
PageHibernateCallback.java
package com.itheima.crm.page;

import java.sql.SQLException;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;

public class PageHibernateCallback<Timplements HibernateCallback<List<T>> {

    private String hql;
    private Object[] params;
    private int startIndex;
    private int pageSize;

    // 上面的4個參數如何傳入進來呢?
    // 方式一:增長4個setter方法,使用時new出這個類,而後調用4個setter方法,一個一個set進去便可
    // 方式二:經過含參構造方法,使用時new出這個類,同時傳入4個參數
    // 方式三:非傳統的set方法,即鏈式編程。步驟以下:
    // 5.一、首先,只要setter方法,不要getter方法
    // 5.二、返回值類型是本身,返回的是本身
    // 5.三、使用時,先new出對象,再setXxx().setXxx().setXxx()...

    public PageHibernateCallback<T> setHql(String hql) {
        this.hql = hql;
        return this;
    }
    public PageHibernateCallback<T> setParams(Object[] params) {
        this.params = params;
        return this;
    }
    public PageHibernateCallback<T> setStartIndex(int startIndex) {
        this.startIndex = startIndex;
        return this;
    }
    public PageHibernateCallback<T> setPageSize(int pageSize) {
        this.pageSize = pageSize;
        return this;
    }

    @Override
    public List<T> doInHibernate(Session session) throws HibernateException, SQLException {
        // 一、經過HQL語句,得到Query對象
        Query queryObject = session.createQuery(hql);
        // 二、條件設置
        for (int i = 0; i < params.length; i++) {
            queryObject.setParameter(i, params[i]);
        }
        // 三、分頁
        queryObject.setFirstResult(startIndex);
        queryObject.setMaxResults(pageSize);
        // 四、查詢全部
        return queryObject.list();
    }
}

CourseTypeDao.javaphp

    /**
     * 分頁,查詢總記錄數
     * 
     * @param condition
     * @param params
     * @return
     */

    public int getTotalRecord(String condition, Object[] params);

    /**
     * 分頁,查詢結果
     * 
     * @param condition 條件
     * @param params 條件的實際參數
     * @param startIndex 開始索引
     * @param pageSize 每頁顯示的個數
     * @return
     */

    public List<CrmCourseType> findAll(String condition, Object[] params, int startIndex, int pageSize);

CourseTypeDaoImpl.javacss

    @Override
    public int getTotalRecord(String condition, Object[] params) {
        String hql = "select count(c) from CrmCourseType c where 1=1 " + condition;
        List<Long> list = this.getHibernateTemplate().find(hql, params); // 聚合函數查詢
        return list.get(0).intValue(); // 包裝類就是點方法,基本類就是強轉
    }

    @Override
    public List<CrmCourseType> findAll(String condition, Object[] params, int startIndex, int pageSize) {
        String hql = "from CrmCourseType where 1=1 " + condition;
        // HQL不支持分頁,QBC支持分頁,因此若是使用HQL,須要咱們自定義實現類
        return this.getHibernateTemplate().execute(new PageHibernateCallback<CrmCourseType>().setHql(hql).setParams(params).setStartIndex(startIndex).setPageSize(pageSize)); 
    }

10.四、service層 實現分析

CourseTypeService.javahtml

    /**
     * 帶有條件的查詢全部課程類別  + 分頁
     * 
     * @param courseType 條件
     * @param pageNum 第幾頁(當前頁)
     * @param pageSize 每頁顯示個數
     * @return
     */

    public PageBean<CrmCourseType> findAllCourseType(CrmCourseType courseType, int pageNum, int pageSize);

CourseTypeServiceImpl.javajava

    @Override
    public PageBean<CrmCourseType> findAllCourseType(CrmCourseType courseType, int pageNum, int pageSize
{
        // 1.一、使用StringBuilder 接收:拼湊查詢條件
        StringBuilder builder = new StringBuilder();
        // 1.二、使用List 接收:拼湊實際參數,須要能夠重複,有順序  => 選擇  List集合
        List<Object> paramsList = new ArrayList<Object>();

        // 二、過濾條件
        // 2.一、過濾課程類別,不須要 null 或者 "" 或者 "  ",使用工具類
        if (StringUtils.isNotBlank(courseType.getCourseName())) {
            builder.append(" and courseName like ?");
            paramsList.add("%" + courseType.getCourseName() + "%");
        }
        // 2.二、過濾課程簡介,不須要 null 或者 "" 或者 "  ",使用工具類
        if (StringUtils.isNotBlank(courseType.getRemark())) {
            builder.append(" and remark like ?");
            paramsList.add("%" + courseType.getRemark() + "%");
        }
        // 2.三、過濾總學時
        if (StringUtils.isNotBlank(courseType.getTotalStart())) {
            builder.append(" and total >= ?");
            paramsList.add(Integer.parseInt(courseType.getTotalStart()));
        }
        if (StringUtils.isNotBlank(courseType.getTotalEnd())) {
            builder.append(" and total <= ?");
            paramsList.add(Integer.parseInt(courseType.getTotalEnd()));
        }
        // 2.三、過濾總費用
        if (StringUtils.isNotBlank(courseType.getCourseCostStart())) {
            builder.append(" and courseCost >= ?");
            paramsList.add(Double.parseDouble(courseType.getCourseCostStart()));
        }
        if (StringUtils.isNotBlank(courseType.getCourseCostEnd())) {
            builder.append(" and courseCost <= ?");
            paramsList.add(Double.parseDouble(courseType.getCourseCostEnd()));
        }

        // 三、使用數據
        // 一、條件,格式:「and ...? and ...?」
        String condition = builder.toString();
        // 二、實際參數
        Object[] params = paramsList.toArray();

        // 二、分頁
        // 2.一、總記錄數 totalRecord
        int totalRecord = this.courseTypeDao.getTotalRecord(condition, params);
        // 2.二、建立PageBean對象
        PageBean<CrmCourseType> pageBean = new PageBean<CrmCourseType>(pageNum, pageSize, totalRecord);
        // 2.三、分頁數據
        List<CrmCourseType> data = this.courseTypeDao.findAll(condition, params, pageBean.getStartIndex(), pageBean.getPageSize());
        pageBean.setData(data);

        return pageBean;
    }

10.五、jsp頁面 實現分析

  • 方案1
  • 方案2

    咱們使用方案2。

/day36_06_Spring_crm/WebRoot/WEB-INF/pages/coursetype/listCourse.jspweb

......
<%--條件查詢 start --%>
<s:form namespace="/" action="courseTypeAction_findAll">
    
<%-- 提供隱藏域,存放的是須要的當前頁 ,id是給js/css使用的,name是給提交表單用的 --%>
    <s:hidden id="pageNum" name="pageNum" value="1"></s:hidden>
......
    <td align="right">
        <span><s:property value="#pageBean.pageNum"/>/<s:property value="#pageBean.totalPage"/></span>
        <span>
            <s:if test="#pageBean.pageNum gt 1">
<%--gt 等價於 < --%>
                <a href="javascript:void(0)" onclick="showPage(1)">[首頁]</a>&nbsp;&nbsp; 
<%-- 首頁 = 1 --%>
                <a href="javascript:void(0)" onclick="showPage(<s:property value="#pageBean.pageNum - 1"/>)">[上一頁]</a>&nbsp;&nbsp; 
<%-- 上一頁 = 當前頁 - 1 --%>
            </s:if>
            <s:if test="#pageBean.pageNum lt #pageBean.totalPage">
<%--lt 等價於 > --%>
                <a href="javascript:void(0)" onclick="showPage(<s:property value="#pageBean.pageNum + 1"/>)">[下一頁]</a>&nbsp;&nbsp; 
<%-- 下一頁 = 當前頁 + 1 --%>
                <a href="javascript:void(0)" onclick="showPage(<s:property value="#pageBean.totalPage"/>)">[尾頁]</a>&nbsp;&nbsp; 
<%-- 尾頁 --%>
            </s:if>
        </span>
    </td>
  </tr>
</table>
    <script type="text/javascript">
        function showPage(num{
            // 一、修改隱藏域的值
            document.getElementById("pageNum").value = num;
            // 二、提交表單
            document.forms[0].submit();
        }
    
</script>
......

10.六、jsp頁面 動態顯示效果

PageBean.java算法

......
    // 增長動態顯示條
    private int start;
    private int end;

    // 含參構造(含有3個參數的構造方法,這樣就能告訴使用者須要這三個必選項)
    public PageBean(int pageNum, int pageSize, int totalRecord) {
        super();
        this.pageNum = pageNum;
        this.pageSize = pageSize;
        this.totalRecord = totalRecord;

        // 計算項
        // 一、開始索引(索引從0開始)
        this.startIndex = (this.pageNum -1) * this.pageSize;
        // 二、總分頁數
        this.totalPage = (this.totalRecord + (this.pageSize - 1)) / this.pageSize;

        // 三、增長動態顯示條
        // 3.一、初始化數據,暫定顯示10個分頁
        this.start = 1// 開始的分頁
        this.end = 10// 最後的分頁

        // 3.二、處理數據,假如:總分頁數 totalPage = 4
        if (this.totalPage <= 10) {
            this.end = this.totalPage; // 最後的分頁=總分頁數
        } else {
            // 假如:總分頁數 totalPage = 15

            // 3.三、當前頁:前4後5
            this.start = this.pageNum - 4;
            this.end = this.pageNum + 5;

            if (this.start < 1) {
                this.start = 1;
                this.end = 10;
            }

            if (this.end > this.totalPage) {
                this.start = this.totalPage - 9;
                this.end = this.totalPage;
            }
        }
......

listCourse.jspspring

......
            <s:if test="#pageBean.pageNum gt 1">
<%--gt 等價於 < --%>
                <a href="javascript:void(0)" onclick="showPage(1)">[首頁]</a>&nbsp;&nbsp; 
<%-- 首頁 = 1 --%>
                <a href="javascript:void(0)" onclick="showPage(<s:property value="#pageBean.pageNum - 1"/>)">[上一頁]</a>&nbsp;&nbsp; 
<%-- 上一頁 = 當前頁 - 1 --%>
            </s:if>

            
<%-- 添加動態顯示條  --%>
            <s:iterator begin="#pageBean.start" end="#pageBean.end" var="num">
                <a href="javascript:void(0)" onclick="showPage(<s:property value="#num"/>)"><s:property value="#num"/></a>&nbsp;&nbsp;
            </s:iterator>

            <s:if test="#pageBean.pageNum lt #pageBean.totalPage">
<%--lt 等價於 > --%>
                <a href="javascript:void(0)" onclick="showPage(<s:property value="#pageBean.pageNum + 1"/>)">[下一頁]</a>&nbsp;&nbsp; 
<%-- 下一頁 = 當前頁 + 1 --%>
                <a href="javascript:void(0)" onclick="showPage(<s:property value="#pageBean.totalPage"/>)">[尾頁]</a>&nbsp;&nbsp; 
<%-- 尾頁 --%>
            </s:if>
......

11、this小案例


Parent.java
package com.itheima.testthis;

public class Parent {

    public void init() {
        System.out.println("1 parent init");
        this.demo();
    }

    public void demo() {
        System.out.println("2 parent demo");
    }
}

Son.javasql

package com.itheima.testthis;

public class Son extends Parent {

    public void init() {
        super.init();
        System.out.println("3 son init");
        this.demo();
    }

    public void demo() {
        System.out.println("4 son demo");
    }
}

TestThis.java數據庫

package com.itheima.testthis;

public class TestThis {

    public static void main(String[] args) {

        // Parent parent = new Parent();
        // parent.init();

        // this在編譯時指的是當前類,在運行時指的是當前運行類,對字段和方法的處理方式是不同的。

        Son son = new Son();
        son.init();
    }
}

測試結果

1 parent init
4 son demo
3 son init
4 son demo

12、BaseDao

之前的作法:


如今的作法:
    1. 將Dao層通用的方法進行統一實現。
    2. 以後在dao層使用dao接口,即StaffDao。
    3. StaffDao接口,須要繼承 BaseDao接口,從而對外能夠提供多個方法,便可以直接使用BaseDao的方法 + 本身特有的方法。
    4. BaseDaoImpl實現類,須要繼承 HibernateDaoSupport,從而能夠調用HibernateTemplate,至關於以前直接編寫dao實現類。同時須要實現BaseDao接口,從而將公共內容都完成。
    5. StaffDaoImpl實現類,須要繼承 BaseDaoImpl實現類,從而全部的公共內容均可以使用了。同時須要實現StaffDao接口,從而完成特有的功能。

示例代碼以下:
BaseDao.java

package com.itheima.crm.base;

import java.util.List;

public interface BaseDao<T{

    public void save(T t);
    public void update(T t);
    public void delete(T t);
    public void saveOrUpdate(T t);

    public T findById(java.io.Serializable id);
    public List<T> findAll();
    // ......
}

BaseDaoImpl.java

package com.itheima.crm.base.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.itheima.crm.base.BaseDao;

public class BaseDaoImpl<Textends HibernateDaoSupport implements BaseDao<T{

    // 定義變量接收實際參數
    private Class<?> beanClass;

    // T 在編譯時,只是變量,在運行是才能夠得到具體的類型
    public BaseDaoImpl() {
        // 經過構造方法去得到運行時的類型,BaseDaoImpl<CrmStaff> 叫作被參數化的類型
        ParameterizedType parameterizedType = (ParameterizedType) this.getClass().getGenericSuperclass();
        // 得到實際參數值,如下方法得到的是全部的實際參數值,可是咱們此時只有一個
        beanClass = (Class<?>) parameterizedType.getActualTypeArguments()[0];
    }

    @Override
    public void save(T t) {
        this.getHibernateTemplate().save(t);
    }

    @Override
    public void update(T t) {
        this.getHibernateTemplate().update(t);
    }

    @Override
    public void delete(T t) {
        this.getHibernateTemplate().delete(t);
    }

    @Override
    public void saveOrUpdate(T t) {
        this.getHibernateTemplate().saveOrUpdate(t);
    }

    @Override
    public T findById(Serializable id) {
        return (T) this.getHibernateTemplate().get(beanClass, id);
    }

    @Override
    public List<T> findAll() {
        // beanClass.getName() 得到的是類的全限定名稱  例如:com.itheima.crm.staff.domain.CrmStaff
        return this.getHibernateTemplate().find("from " + beanClass.getName());
    }

    // 回顧hql語句
    // session.createQuery("from CrmStaff"); // 簡便寫法,存在自動導包
    // session.createQuery("from com.itheima.crm.staff.domain.CrmStaff"); // 完整寫法
}

以Staff進行舉例:
StaffDao.java

package com.itheima.crm.staff.dao;

import com.itheima.crm.base.BaseDao;
import com.itheima.crm.staff.domain.CrmStaff;

public interface StaffDao extends BaseDao<CrmStaff{
    /**
     * 經過用戶名和密碼查詢員工
     * 
     * @param loginName
     * @param loginPwd
     * @return
     */

    public CrmStaff find(String loginName, String loginPwd);
}

StaffDaoImpl.java

package com.itheima.crm.staff.dao.impl;

import java.util.List;

import com.itheima.crm.base.impl.BaseDaoImpl;
import com.itheima.crm.staff.dao.StaffDao;
import com.itheima.crm.staff.domain.CrmStaff;

@SuppressWarnings("unchecked")
public class StaffDaoImpl extends BaseDaoImpl<CrmStaffimplements StaffDao {

    @Override
    public CrmStaff find(String loginName, String loginPwd) {
        List<CrmStaff> allStaff = this.getHibernateTemplate().find("from CrmStaff where loginName=? and loginPwd=?", loginName, loginPwd);
        if (allStaff.size() == 1) {
            return allStaff.get(0);
        }
        return null;
    }
}

十3、BaseAction

主要思想:
    一、封裝數據
    二、讓Spring一會兒注入多個service
    三、分頁的數據
    四、簡化值棧操做

BaseAction.java

package com.itheima.crm.base;

import java.lang.reflect.ParameterizedType;

import com.itheima.crm.coursetype.service.CourseTypeService;
import com.itheima.crm.department.service.DepartmentService;
import com.itheima.crm.post.service.PostService;
import com.itheima.crm.staff.service.StaffService;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

public class BaseAction<T>  extends ActionSupport implements ModelDriven<T{

    // 一、封裝數據
    private T t;

    @Override
    public T getModel() {
        return t;
    }

    // 1.一、實例化T,能夠經過反射去new出T
    public BaseAction() {
        try {
            // 一、要先得到該類運行時的Class
            ParameterizedType parameterizedType =  (ParameterizedType) this.getClass().getGenericSuperclass();
            Class<T> clazz = (Class<T>) parameterizedType.getActualTypeArguments()[0];
            // 二、經過反射去建立實例
            t = clazz.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e); // 把編譯時異常轉換成運行時異常
        }
    }

    // 二、讓Spring一會兒注入多個service
    // 提供setter方法,是讓Spring進行注入的
    // 提供getter方法,是讓子類能夠得到Spring注入的對象的

    // 2.一、員工的service
    private StaffService staffService;
    public void setStaffService(StaffService staffService) {
        this.staffService = staffService;
    }
    public StaffService getStaffService() {
        return staffService;
    }
    // 2.二、職務的service
    private PostService postService;
    public void setPostService(PostService postService) {
        this.postService = postService;
    }
    public PostService getPostService() {
        return postService;
    }
    // 2.三、部門的service
    private DepartmentService departmentService;
    public void setDepartmentService(DepartmentService departmentService) {
        this.departmentService = departmentService;
    }
    public DepartmentService getDepartmentService() {
        return departmentService;
    }
    // 2.四、課程類別的service
    private CourseTypeService courseTypeService;
    public void setCourseTypeService(CourseTypeService courseTypeService) {
        this.courseTypeService = courseTypeService;
    }
    public CourseTypeService getCourseTypeService() {
        return courseTypeService;
    }
    // 2.五、班級的service

    // 三、分頁的數據
    // 第幾頁(當前頁)
    private int pageNum = 1;
    public void setPageNum(int pageNum) {
        this.pageNum = pageNum;
    }
    public int getPageNum() {
        return pageNum;
    }

    // 每頁顯示個數(固定值)
    private int pageSize = 2// 固定值,不用提供setter方法
    public void setPageSize(int pageSize) // 若是寫了setter方法,爲了之後擴展留下接口
        this.pageSize = pageSize;
    }
    public int getPageSize() {
        return pageSize;
    }

    // 四、簡化值棧操做
    public void push(Object o) {
        ActionContext.getContext().getValueStack().push(o);
    }

    public void set(String key, Object o) {
        ActionContext.getContext().getValueStack().set(key, o);
    }

    public void put(String key, Object value) {
        ActionContext.getContext().put(key, value);
    }

    public void putSession(String key, Object value) {
        ActionContext.getContext().getSession().put(key, value);
    }

    public void putApplication(String key, Object value) {
        ActionContext.getContext().getApplication().put(key, value);
    }
}

十4、上傳和下載

14.一、班級列表的查詢

思路:
    1. ClassesDao / ClassesDaoImpl --> 繼承BaseDao / BaseDaoImpl
    2. service
    3. spring配置,完善BaseAction
    4. ClassesAction --> 繼承BaseAction
    5. left.jsp --> struts.xml/struts-classes.xml --> listClass.jsp

一、
ClassesDao.java

package com.itheima.crm.classes.dao;

import com.itheima.crm.base.BaseDao;
import com.itheima.crm.classes.domain.CrmClasses;

public interface ClassesDao extends BaseDao<CrmClasses> {

}

ClassesDaoImpl.java

package com.itheima.crm.classes.dao.impl;

import com.itheima.crm.base.impl.BaseDaoImpl;
import com.itheima.crm.classes.dao.ClassesDao;
import com.itheima.crm.classes.domain.CrmClasses;

public class ClassesDaoImpl extends BaseDaoImpl<CrmClassesimplements ClassesDao {

}

二、
ClassesService.java

package com.itheima.crm.classes.service;

import java.util.List;

import com.itheima.crm.classes.domain.CrmClasses;

public interface ClassesService {

    /**
     * 查詢全部班級
     * 
     * @return
     */

    public List<CrmClasses> findAll();
}

ClassesServiceImpl.java

package com.itheima.crm.classes.service.impl;

import java.util.List;

import com.itheima.crm.classes.dao.ClassesDao;
import com.itheima.crm.classes.domain.CrmClasses;
import com.itheima.crm.classes.service.ClassesService;

public class ClassesServiceImpl implements ClassesService {

    private ClassesDao classesDao;
    public void setClassesDao(ClassesDao classesDao) {
        this.classesDao = classesDao;
    }

    @Override
    public List<CrmClasses> findAll() {
        return this.classesDao.findAll();
    }
}

三、
applicationContext.xml

    <!-- 4.五、班級 -->
    <import resource="applicationContext-classess.xml"/>

applicationContext-classess.xml

<?xml version="1.0" encoding="UTF-8"?>

<!-- 添加命名空間 -->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
                              http://www.springframework.org/schema/beans/spring-beans.xsd
                              http://www.springframework.org/schema/tx 
                              http://www.springframework.org/schema/tx/spring-tx.xsd
                              http://www.springframework.org/schema/aop 
                              http://www.springframework.org/schema/aop/spring-aop.xsd
                              http://www.springframework.org/schema/context 
                              http://www.springframework.org/schema/context/spring-context.xsd"
>


    <!-- 班級配置項  dao、service-->
    <bean id="classesDao" class="com.itheima.crm.classes.dao.impl.ClassesDaoImpl">
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>
    <bean id="classesService" class="com.itheima.crm.classes.service.impl.ClassesServiceImpl">
        <property name="classesDao" ref="classesDao"></property>
    </bean>
</beans>

BaseAction.java

......
    // 2.五、班級的service
    private ClassesService classesService;
    public void setClassesService(ClassesService classesService) {
        this.classesService = classesService;
    }
......

四、
ClassesAction.java

package com.itheima.crm.classes.web.action;

import java.util.List;

import com.itheima.crm.base.BaseAction;
import com.itheima.crm.classes.domain.CrmClasses;

public class ClassesAction extends BaseAction<CrmClasses{

    public String findAll() {
        List<CrmClasses> allClasses = this.getClassesService().findAllClasses();
        this.set("allClasses", allClasses);
        return "findAll";
    }
}

五、
/day36_06_Spring_crm/WebRoot/WEB-INF/pages/frame/left.jsp

        d.add('010301','0103','班級管理','${pageContext.request.contextPath}/classesAction_findAll','','right');

struts.xml

    <!-- 3.四、班級-->
    <include file="struts/struts-classes.xml"></include>

struts-classes.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">


<struts>
    <!-- 班級的配置 -->
    <package name="cla" namespace="/" extends="common">
        <action name="classesAction_*" class="com.itheima.crm.classes.web.action.ClassesAction" method="{1}">
            <!-- 一、查詢全部班級 -->
            <result name="findAll">/WEB-INF/pages/classes/listClass.jsp</result>
        </action>
    </package>  
</struts>

/day36_06_Spring_crm/WebRoot/WEB-INF/pages/classes/listClass.jsp

......
      <s:iterator value="allClasses" status="vs">
      <tr class="<s:property value="#vs.even ? 'tabtd2: 'tabtd1'"/>">
        <td align="center"><s:property value="name"/></td>
        <td align="center"><s:property value="courseType.courseName"/></td>
        <td align="center"><s:date name="beginTime" format="yyyy-MM--dd"/></td>
        <td align="center"><s:date name="endTime" format="yyyy-MM--dd"/></td>

        <td align="center"><s:property value="status"/></td>
        <td align="center"><s:property value="totalCount"/></td>
        <td align="center"><s:property value="upgradeCount"/></td>
        <td align="center"><s:property value="changeCount"/></td>

        <td align="center">
            <a href="${pageContext.request.contextPath}/pages/classesm/addOrEditClass.jsp">
            <img src="${pageContext.request.contextPath}/images/button/modify.gif" class="img"/></a>
        </td>
        <td align="center">
            <a href="${pageContext.request.contextPath}/pages/classesm/showClass.jsp">
            <img src="${pageContext.request.contextPath}/images/button/modify.gif" class="img"/></a>
        </td>
        <td align="center" title="上次上傳時間:2015-04-02">   
            <a href="${pageContext.request.contextPath}/pages/classesm/uploadClass.jsp">上傳</a>
            <a href="${pageContext.request.contextPath}/pages/classesm/downloadClass">下載</a> <br/>
        </td>
      </tr>
    </s:iterator>
......

14.二、經過班級id查詢班級詳情

ClassesService.java

    /**
     * 經過班級id查詢班級詳情
     * 
     * @return
     */

    public CrmClasses findById(String classesId);

ClassesServiceImpl.java

    @Override
    public CrmClasses findById(String classesId) {
        return this.classesDao.findById(classesId);
    }

ClassesAction.java

    public String uploadUI() {
        CrmClasses findClasses = this.getClassesService().findById(this.getModel().getClassesId());
        // 將查詢到的數據壓入棧頂(爲了更方便的回顯數據)
        this.push(findClasses);
        return "uploadUI";
    }

struts-classes.xml

            <!-- 二、顯示上傳表單頁面 -->
            <result name="uploadUI">/WEB-INF/pages/classes/uploadClass.jsp</result>

listClass.jsp

            <s:a namespace="/" action="classesAction_uploadUI">
                <s:param name="classesId" value="classesId"></s:param> <%--由於上傳文件以前須要經過id查詢班級詳情 --%>
                上傳
            </s:a>

uploadClass.jsp

......
    <table width="88%" border="0" class="emp_table" style="width:80%;">
      <tr>
        <td width="120">課程類別:</td>
        <td><s:property value="courseType.courseName"/></td>
        <td>&nbsp;</td>
      </tr>
      <tr>
        <td>班級:</td>
        <td><s:property value="name"/></td>
        <td>&nbsp;</td>
      </tr>
      <tr>
        <td>上次上傳時間:</td>
        <td><s:date name="uploadTime"/></td>
        <td>&nbsp;</td>
      </tr>
      <tr>
        <td>選擇課表:</td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
      </tr>
      <tr>
        <td colspan="3">
            <input type="file" name="schedule" value="" />
        </td>
      </tr>
    </table>
......

14.三、文件上傳

    0. 先經過班級id查詢班級詳情,如上
    1. 替換表單 
        <form action="/crm2/classesm/classAction_upload.action" method="post" enctype="multipart/form-data">
        <input type="file" name="schedule">
    2. 編寫action類,struts已經把文件上傳功能都完成了,咱們只須要把須要的東西拿來就能夠了。
       咱們須要但願struts把內容注入給咱們,則就在action類中提供須要的字段,再提供setter方法便可。
            private File schedule; // 文件內容
            private String scheduleFileName; // 文件名稱
            private String scheduleContentType; // 文件類型
    3. 將課表保存到硬盤,將課表的文件路徑、文件名稱、更新時間,更新到數據庫。
    4. struts中攔截器的設置,由於咱們上傳的是課表。設置容許上傳的文件類型。
    5. 文件上傳不成功。ClassesAction類中使用註解@InputConfig 開發,struts-classes.xml中添加相應的配置。
            /**
             * 文件(課表)上傳
             * 
             * @return
             * @throws IOException
             */

            @InputConfig(resultName="uploadInput")
            public String upload() throws IOException {
    6. 文件上傳不成功時的錯誤信息的國際化顯示。

一、
uploadClass.jsp

......
<s:form namespace="/" action="classAction_upload.action" enctype="multipart/form-data">
......
<s:file name="schedule"></s:file>
......

二、
ClassesAction.java

    private File schedule; // 文件內容
    private String scheduleFileName; // 文件名稱
    private String scheduleContentType; // 文件類型

    public void setSchedule(File schedule) {
        this.schedule = schedule;
    }
    public void setScheduleFileName(String scheduleFileName) {
        this.scheduleFileName = scheduleFileName;
    }
    public void setScheduleContentType(String scheduleContentType) {
        this.scheduleContentType = scheduleContentType;
    }

    /**
     * 文件(課表)上傳
     * 
     * @return
     * @throws IOException
     */

    @InputConfig(resultName="uploadInput")
    public String upload() throws IOException {
        // 一、將課表保存在硬盤(企業級開發中,圖片會上傳到圖片服務器,圖片服務器返回一個路徑,咱們把該路徑保存在數據庫中便可)
        // 1.一、在tomcat下,位置在.../WEB-INF/upload/...
        // 方式一:寫死父目錄,很差
        // String parentDir = "D:\learn\JavaWeb\apache-tomcat\apache-tomcat-9.0.7\webapps\day36_06_Spring_crm\WEB-INF\...";
        // 方式二:文件父目錄
        String parentDir = ServletActionContext.getServletContext().getRealPath("/WEB-INF/upload");
        // 1.二、咱們但願文件名是一個32位的隨機數,且沒有擴展名,這樣安全性更高
        String fileName = MyStringUtils.getUUID();
        // 1.三、保存操做
        FileUtils.copyFile(schedule, new File(parentDir, fileName));

        // 二、更新操做
        this.getModel().setUploadPath("/WEB-INF/upload" + fileName);
        this.getModel().setUploadFilename(scheduleFileName);
        this.getModel().setUploadTime(new Date());

        this.getClassesService().updateUpload(this.getModel());

        return "upload";
    }

三、
ClassesService.java

    /**
     * 更新上傳
     * 
     * @param model
     */

    public void updateUpload(CrmClasses classes);

ClassesServiceImpl.java

    @Override
    public void updateUpload(CrmClasses classes) {
        // 一、先查詢 ,再更新,涉及到快照和一級緩存
        CrmClasses findClasses = this.classesDao.findById(classes.getClassesId());
        findClasses.setUploadFilename(classes.getUploadFilename());
        findClasses.setUploadPath(classes.getUploadPath());
        findClasses.setUploadTime(classes.getUploadTime());
    }

更新頁面的表單須要添加隱藏字段
uploadClass.jsp

<s:form namespace="/" action="classesAction_upload.action" enctype="multipart/form-data">
<!-- <form action="/crm2/classesm/classAction_upload.action" method="post" enctype="multipart/form-data"> -->
    <%--添加隱藏字段,由於上傳表單的時候,須要先根據id進行查詢 --%>
    <s:hidden name="classesId" value="%{classesId}"></s:hidden>
    <table width="88%" border="0" class="emp_table" style="width:80%;">

四、
struts中攔截器的設置,由於咱們上傳的是課表。設置容許上傳的文件類型。

        <interceptors>
            <!-- 2.2.一、聲明(註冊),將登陸攔截器實現類配置給struts -->
            <interceptor name="loginInterceptor" class="com.itheima.crm.web.interceptor.LoginInterceptor"></interceptor>
            <!-- 2.2.二、 自定義攔截器棧 -->
            <interceptor-stack name="loginStack">
                <!-- 給默認的攔截器棧中的某一個攔截器注入內容
                   * 格式:攔截器名稱.屬性     值1,值2
                        allowedExtensions
                        allowedTypes    -->

                <interceptor-ref name="defaultStack">
                    <param name="fileUpload.allowedExtensions">.xls, .xlsx</param>
                </interceptor-ref>
                <!-- 自定義登陸攔截器:須要配置對login()方法不進行攔截 ,須要進行注入
                    * excludeMethods 配置不包含的方法,多個方法使用逗號分隔 -->

                <interceptor-ref name="loginInterceptor">
                    <param name="excludeMethods">login</param>
                </interceptor-ref>
            </interceptor-stack>

五、
文件上傳不成功時的頁面。使用註解@InputConfig
ClassesAction.java

            /**
             * 文件(課表)上傳
             * 
             * @return
             * @throws IOException
             */

            @InputConfig(resultName="uploadInput")
            public String upload() throws IOException {

struts-classes.xml

            <!-- 四、上傳不成功頁面 -->
            <result name="uploadInput">/WEB-INF/pages/error.jsp</result>

六、
文件上傳不成功時的錯誤信息的國際化顯示。以下圖所示:
界面不友好


在error.jsp中,添加錯誤信息提示
    <font color="#f00">
        系統繁忙,請稍後重試</br>
        <s:fielderror></s:fielderror></br>
        
<%-- <s:actionerror/></br> --%>
        
<%-- <s:actionmessage/></br> --%>
    </font>

界面仍是不友好


須要進行國際化顯示,在com.itheima.crm.classes.web.action包中新建ClassesAction.properties文件,
打開:\WEB-INF\lib\struts2-core-2.3.15.3.jar/org/apache/struts2/struts-messages.properties該文件,
複製 struts.messages.error.file.extension.not.allowed=File extension not allowed: {0} "{1}" "{2}" {3}
該句代碼至ClassesAction.properties文件中,進行修改,以下圖所示:

效果以下:

14.四、文件下載

  struts.xml 的 result 中提供stream類型  inputName 設置 InputStream 得到屬性值,須要提供getter方法  contentDisposition 設置 attachment;filename=${imageFileName} 得到文件名稱

相關文章
相關標籤/搜索