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;
}
}
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<T> implements 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));
}
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;
}
/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> <%-- 首頁 = 1 --%>
<a href="javascript:void(0)" onclick="showPage(<s:property value="#pageBean.pageNum - 1"/>)">[上一頁]</a> <%-- 上一頁 = 當前頁 - 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> <%-- 下一頁 = 當前頁 + 1 --%>
<a href="javascript:void(0)" onclick="showPage(<s:property value="#pageBean.totalPage"/>)">[尾頁]</a> <%-- 尾頁 --%>
</s:if>
</span>
</td>
</tr>
</table>
<script type="text/javascript">
function showPage(num) {
// 一、修改隱藏域的值
document.getElementById("pageNum").value = num;
// 二、提交表單
document.forms[0].submit();
}
</script>
......
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> <%-- 首頁 = 1 --%>
<a href="javascript:void(0)" onclick="showPage(<s:property value="#pageBean.pageNum - 1"/>)">[上一頁]</a> <%-- 上一頁 = 當前頁 - 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>
</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> <%-- 下一頁 = 當前頁 + 1 --%>
<a href="javascript:void(0)" onclick="showPage(<s:property value="#pageBean.totalPage"/>)">[尾頁]</a> <%-- 尾頁 --%>
</s:if>
......
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
之前的作法:
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<T> extends 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<CrmStaff> implements 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;
}
}
主要思想:
一、封裝數據
二、讓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);
}
}
思路:
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<CrmClasses> implements 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>
......
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> </td>
</tr>
<tr>
<td>班級:</td>
<td><s:property value="name"/></td>
<td> </td>
</tr>
<tr>
<td>上次上傳時間:</td>
<td><s:date name="uploadTime"/></td>
<td> </td>
</tr>
<tr>
<td>選擇課表:</td>
<td> </td>
<td> </td>
</tr>
<tr>
<td colspan="3">
<input type="file" name="schedule" value="" />
</td>
</tr>
</table>
......
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>
六、
文件上傳不成功時的錯誤信息的國際化顯示。以下圖所示:
界面不友好
<font color="#f00">
系統繁忙,請稍後重試</br>
<s:fielderror></s:fielderror></br>
<%-- <s:actionerror/></br> --%>
<%-- <s:actionmessage/></br> --%>
</font>
界面仍是不友好
struts.messages.error.file.extension.not.allowed=File extension not allowed: {0} "{1}" "{2}" {3}
struts.xml 的 result 中提供stream類型 inputName 設置 InputStream 得到屬性值,須要提供getter方法 contentDisposition 設置 attachment;filename=${imageFileName} 得到文件名稱