一、CRM 客戶關係管理系統
CRM : custom releation manager 客戶關係管理系統,用於維護客戶和公司之間關係。 我們要做的是:學校 和 大家 之間關係。
- 完成功能:
- 員工管理: 1、登錄(登錄攔截器、服務器端校驗) 2、查詢(普通查詢、高級查詢) 3、編輯員工(標籤回顯、ajax 二級聯動)
- 課程類別: 1、查詢(查詢所有 + 條件 + 分頁) 2、添加和編輯
- 班級管理: 1、查詢 2、課表的上傳、下載
- 工具類 1、BaseDao 2、BaseAction
二、環境搭建
2.1、導入jar包
2.2、創建數據庫和表
create database if not exists `day36_crmdb`; USE `day36_crmdb`; -------------------------------------------------------- CREATE TABLE `crm_department` ( `depId` varchar(255) NOT NULL PRIMARY KEY, `depName` varchar(50) DEFAULT NULL ); insert into `crm_department`(`depId`,`depName`) values ('2c9091c14c78e58b014c78e67de10001','java學院'), ('2c9091c14c78e58b014c78e68ded0002','諮詢部'); -------------------------------------------------------- CREATE TABLE `crm_post` ( `postId` varchar(255) NOT NULL PRIMARY KEY, `postName` varchar(100) DEFAULT NULL, `depId` varchar(255) DEFAULT NULL, CONSTRAINT FOREIGN KEY (`depId`) REFERENCES `crm_department` (`depId`) ); insert into `crm_post`(`postId`,`postName`,`depId`) values ('2c9091c14c78e58b014c78e6b34a0003','總監','2c9091c14c78e58b014c78e67de10001'), ('2c9091c14c78e58b014c78e6d4510004','講師','2c9091c14c78e58b014c78e67de10001'), ('2c9091c14c78e58b014c78e6f2340005','主管','2c9091c14c78e58b014c78e68ded0002'); -------------------------------------------------------- CREATE TABLE `crm_staff` ( `staffId` varchar(255) NOT NULL PRIMARY KEY, `loginName` varchar(100) DEFAULT NULL, `loginPwd` varchar(100) DEFAULT NULL, `staffName` varchar(100) DEFAULT NULL, `gender` varchar(20) DEFAULT NULL, `onDutyDate` datetime DEFAULT NULL, `postId` varchar(255) DEFAULT NULL, CONSTRAINT FOREIGN KEY (`postId`) REFERENCES `crm_post` (`postId`) ); insert into `crm_staff`(`staffId`,`loginName`,`loginPwd`,`staffName`,`gender`,`onDutyDate`,`postId`) values ('2c9091c14c78e58b014c78e5c32a0000','jack','81dc9bdb52d04dc20036dbd8313ed055','管理員',NULL,NULL,NULL), ('2c9091c14c78e58b014c78e759b40006','rose','81dc9bdb52d04dc20036dbd8313ed055','肉絲','女','2013-04-16 00:00:00','2c9091c14c78e58b014c78e6f2340005'), ('2c9091c14c78e58b014c78e7ecd90007','tom','81dc9bdb52d04dc20036dbd8313ed055','湯姆','男','2014-04-24 00:00:00','2c9091c14c78e58b014c78e6d4510004'); -------------------------------------------------------- CREATE TABLE `crm_course_type` ( `courseTypeId` varchar(255) NOT NULL PRIMARY KEY, `courseCost` double DEFAULT NULL, `total` int(11) DEFAULT NULL, `courseName` varchar(500) DEFAULT NULL, `remark` varchar(5000) DEFAULT NULL ); insert into `crm_course_type`(`courseTypeId`,`courseCost`,`total`,`courseName`,`remark`) values ('2c9091c14c78e58b014c78e829b70008',2000,1000,'java基礎',''), ('2c9091c14c78e58b014c78e867b80009',18000,4000,'java就業',''); -------------------------------------------------------- CREATE TABLE `crm_classes` ( `classesId` varchar(50) NOT NULL PRIMARY KEY, `courseTypeId` varchar(255) DEFAULT NULL, `name` varchar(50) DEFAULT NULL, `beginTime` datetime DEFAULT NULL, `endTime` datetime DEFAULT NULL, `status` varchar(20) DEFAULT NULL, `totalCount` int(11) DEFAULT NULL, `upgradeCount` int(11) DEFAULT NULL, `changeCount` int(11) DEFAULT NULL, `runoffCount` int(11) DEFAULT NULL, `remark` varchar(500) DEFAULT NULL, `uploadTime` datetime DEFAULT NULL, `uploadPath` varchar(200) DEFAULT NULL, `uploadFilename` varchar(100) DEFAULT NULL, CONSTRAINT FOREIGN KEY (`courseTypeId`) REFERENCES `crm_course_type` (`courseTypeId`) ) ; insert into `crm_classes`(`classesId`,`courseTypeId`,`name`,`beginTime`,`endTime`,`status`,`totalCount`,`upgradeCount`,`changeCount`,`runoffCount`,`remark`,`uploadTime`,`uploadPath`,`uploadFilename`) values ('2c9091c14c78e58b014c78e8cc62000a','2c9091c14c78e58b014c78e829b70008','1期','2015-03-10 00:00:00','2015-04-30 00:00:00',NULL,80,2,0,2,'','2015-04-02 16:33:09','/WEB-INF/upload/0d7a042741544da988b2d2462c683e57','(第173期)2015年01月22日 JavaEE就業班.xls'), ('2c9091c14c78e58b014c78e9106e000b','2c9091c14c78e58b014c78e829b70008','2期','2015-04-28 00:00:00','2015-05-27 00:00:00',NULL,67,0,0,0,'',NULL,NULL,NULL), ('2c9091c14c78e58b014c78e9601a000c','2c9091c14c78e58b014c78e867b80009','1期ee','2015-03-29 00:00:00','2015-07-13 00:00:00',NULL,120,0,0,0,'',NULL,NULL,NULL);
ER圖如下:
2.3、項目目錄命名規範
com.itheima.crm.子模塊.分層 例如: com.itheima.crm.staff.dao.impl 員工dao層和實現類 com.itheima.crm.staff.service.impl 員工service層和實現類 com.itheima.crm.staff.web.action 員工web層 com.itheima.crm.staff.domain 員工javabean
2.4、編寫PO類+對應的配置文件Xxx.hbm.xml
僅以 CrmClasses.java、CrmClasses.hbm.xml 和 CrmCourseType.java、CrmCourseType.hbm.xml 爲示例: CrmClasses.java
package com.itheima.crm.classes.domain; import java.util.Date; import com.itheima.crm.coursetype.domain.CrmCourseType; public class CrmClasses { /* CREATE TABLE `crm_classes` ( `classesId` varchar(50) NOT NULL PRIMARY KEY, `courseTypeId` varchar(255) DEFAULT NULL, `name` varchar(50) DEFAULT NULL, `beginTime` datetime DEFAULT NULL, `endTime` datetime DEFAULT NULL, `status` varchar(20) DEFAULT NULL, `totalCount` int(11) DEFAULT NULL, `upgradeCount` int(11) DEFAULT NULL, `changeCount` int(11) DEFAULT NULL, `runoffCount` int(11) DEFAULT NULL, `remark` varchar(500) DEFAULT NULL, `uploadTime` datetime DEFAULT NULL, `uploadPath` varchar(200) DEFAULT NULL, `uploadFilename` varchar(100) DEFAULT NULL, CONSTRAINT FOREIGN KEY (`courseTypeId`) REFERENCES `crm_course_type` (`courseTypeId`) ) ; */ private String classesId; private String name; // 班級名稱 private Date beginTime; // 開班時間 private Date endTime; // 畢業時間 private String status; // 狀態(未開課/已開課/已結束)數據庫不需要保存,頁面通過計算獲得,此字段可以刪除 private Integer totalCount; // 學生總數 private Integer upgradeCount; // 升學數 private Integer changeCount; // 轉班數(轉來) private Integer runoffCount; // 退費數(流失) private String remark; // 其他說明 private Date uploadTime; // 上傳時間 private String uploadPath; // 上傳課表路徑 private String uploadFilename; // 上傳課表名稱 // 多對一:多個班級共享【一個課程類別】 private CrmCourseType courseType; // getter 和 setter 方法 // ...... }
CrmClasses.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.itheima.crm.classes.domain.CrmClasses" table="crm_classes"> <id name="classesId"> <generator class="uuid"></generator> </id> <property name="name"></property> <property name="beginTime" type="date"></property> <property name="endTime" type="date"></property> <property name="status"></property> <property name="totalCount"></property> <property name="upgradeCount"></property> <property name="changeCount"></property> <property name="runoffCount"></property> <property name="remark"></property> <property name="uploadTime"> <column name="uploadTime" sql-type="datetime"></column> </property> <property name="uploadPath"></property> <property name="uploadFilename"></property> <!-- 多對一:多個班級共享【一個課程類別】 --> <many-to-one name="courseType" class="com.itheima.crm.coursetype.domain.CrmCourseType" column="courseTypeId"></many-to-one> </class> </hibernate-mapping>
CrmCourseType.java
package com.itheima.crm.coursetype.domain; import java.util.HashSet; import java.util.Set; import com.itheima.crm.classes.domain.CrmClasses; public class CrmCourseType { /* CREATE TABLE `crm_course_type` ( `courseTypeId` varchar(255) NOT NULL PRIMARY KEY, `courseCost` double DEFAULT NULL, `total` int(11) DEFAULT NULL, `courseName` varchar(500) DEFAULT NULL, `remark` varchar(5000) DEFAULT NULL ); */ private String courseTypeId; private Double courseCost; // 課程費用 private Integer total; // 總課時 private String courseName; // 課程類別名稱 private String remark; // 課程介紹模板 // 一對多:一個課程類別有【多個班級】 private Set<CrmClasses> classesSet = new HashSet<CrmClasses>(); // getter 和 setter 方法 // ...... }
CrmCourseType.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.itheima.crm.coursetype.domain.CrmCourseType" table="crm_course_type"> <id name="courseTypeId"> <generator class="uuid"></generator> </id> <property name="courseCost"></property> <property name="total"></property> <property name="courseName"></property> <property name="remark"></property> <!-- 一對多:一個課程類別有【多個班級】 --> <set name="classesSet"> <key column="courseTypeId"></key> <one-to-many class="com.itheima.crm.classes.domain.CrmClasses"/> </set> </class> </hibernate-mapping>
2.5、spring 配置
2.5.1、源碼文件夾的使用
- 注意1:如何移除源碼文件夾屬性
- 注意2:如何添加源碼文件夾屬性
- 注意3:清除classes目錄下的文件並再次編譯 選中項目 --> Project --> Clean… --> 選擇要清理的項目 --> Ok 即可。
2.5.2、spring 配置文件位置
- 在applicationContext.xml 中配置其他 applicationContext.-staff.xml 的引用,如下圖所示:
2.5.3、web.xml 配置
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <!-- 1.1、spring配置文件位置 方式1: 【建議該方式】 <param-value>classpath:spring/applicationContext.xml</param-value> 需要在applicationContext.xml 配置<import> 導入其他 applicationContext-staff.xml(例如) 文件 方式2: <param-value>classpath:spring/applicationContext*.xml</param-value> 加載所有,不需要配置<import> 導入其他配置文件 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/applicationContext.xml</param-value> </context-param> <!-- 1.2、 加載spring配置文件所使用的監聽器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
2.5.4、spring 配置文件內容
applicationContext.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"> <!-- 公共配置項 --> <!-- 1.1、加載properties配置文件 --> <context:property-placeholder location="classpath:JdbcInfo.properties"/> <!-- 1.2、配置數據源,基本四項 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property> <property name="user" value="${jdbc.user}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!-- 2、配置 LocalSessionFactoryBean,獲得SessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> </props> </property> <property name="mappingLocations" value="classpath:com/itheima/crm/*/domain/*.hbm.xml"></property> </bean> <!-- 3、事務管理 --> <!-- 3.1、 事務管理器 :HibernateTransactionManager --> <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <!-- 3.2 、事務詳情 ,給ABC進行具體的事務設置 ,增刪改:讀寫,查詢:只讀--> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="add*"/> <tx:method name="update*"/> <tx:method name="delete*"/> <tx:method name="find*" read-only="true"/> </tx:attributes> </tx:advice> <!-- 3.3、AOP編程,從 ABCD 業務中 篩選出 ABC,如果強制使用cglib代理 : proxy-target-class="true" --> <aop:config> <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.itheima.crm.*.service..*.*(..))"/> </aop:config> <!-- 導入其他配置文件 --> <import resource="applicationContext-staff.xml"/> </beans>
2.6、struts 配置
2.6.1、struts 配置文件位置
- struts 的配置文件有一個要求:struts的根文件struts.xml必須放在類路徑下,即在源碼文件夾下(也即classes目錄下)
- struts.xml 加載其它 struts-staff.xml
struts.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> <!-- 1、常量配置 --> <!-- 1.1、開發模式 --> <constant name="struts.devMode" value="true"></constant> <!-- 1.2、標籤主題:簡單風格 --> <constant name="struts.ui.theme" value="simple"></constant> <!-- 2 、配置公共項 --> <package name="common" namespace="/" extends="struts-default"> </package> <!-- 3、 加載其他配置文件 --> <include file="struts/struts-staff.xml"></include> </struts>
- 其他struts-staff.xml配置,繼承 struts.xml配置的公共項
struts-staff.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="sta" namespace="/" extends="common"> </package> </struts>
2.6.2、web.xml 配置
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <!-- 1.1、spring配置文件位置 方式1: 【建議該方式】 <param-value>classpath:spring/applicationContext.xml</param-value> 需要在applicationContext.xml 配置<import> 導入其他 applicationContext-staff.xml(例如) 文件 方式2: <param-value>classpath:spring/applicationContext*.xml</param-value> 加載所有,不需要配置<import> 導入其他配置文件 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/applicationContext.xml</param-value> </context-param> <!-- 1.2、 加載spring配置文件所使用的監聽器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 2、struts 前端控制器的配置 --> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
2.7、代碼編寫思路
三、員工登錄
思路: 1. 編寫dao層:通過賬號和密碼查詢 2. 編寫service層:主要事務管理(已經配置) 3. 配置spring 4. jsp 登錄表單 5. struts-staff.xml 配置 6. StaffAction編寫 通過service查詢 查詢到結果:將信息保存session作用域,重定向首頁。(action方法中直接return了,重定向在xml中完成) 沒有結果:在request作用域保存提示信息,請求轉發顯示提示信息。(在struts中,request作用域 == 值棧)
3.1、dao 層
- 注意:之後我們在spring配置dao層時,需要注入SessionFactory。
StaffDao.java
package com.itheima.crm.staff.dao; import com.itheima.crm.staff.domain.CrmStaff; public interface StaffDao { /** * 通過用戶名和密碼查詢 * * @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 org.springframework.orm.hibernate3.support.HibernateDaoSupport; import com.itheima.crm.staff.dao.StaffDao; import com.itheima.crm.staff.domain.CrmStaff; public class StaffDaoImpl extends HibernateDaoSupport implements StaffDao { @Override public CrmStaff find(String loginName, String loginPwd) { List<CrmStaff> allStaff = this.getHibernateTemplate().find("from crm_staff where loginName=? and loginPwd=?", loginName, loginPwd); if (allStaff.size() == 1) { return allStaff.get(0); } return null; } }
3.2、service 層
StaffService.java
package com.itheima.crm.staff.service; import com.itheima.crm.staff.domain.CrmStaff; public interface StaffService { /** * 用戶登錄 * * @param staff * @return */ public CrmStaff login(CrmStaff staff); }
StaffServiceImpl.java
package com.itheima.crm.staff.service.impl; import com.itheima.crm.staff.dao.StaffDao; import com.itheima.crm.staff.domain.CrmStaff; import com.itheima.crm.staff.service.StaffService; public class StaffServiceImpl implements StaffService { private StaffDao staffDao; public void setStaffDao(StaffDao staffDao) { this.staffDao = staffDao; } @Override public CrmStaff login(CrmStaff staff) { return staffDao.find(staff.getLoginName(), staff.getLoginPwd()); } }
3.3、spring 配置
applicationContext-staff.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="staffDao" class="com.itheima.crm.staff.dao.impl.StaffDaoImpl"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <bean id="staffService" class="com.itheima.crm.staff.service.impl.StaffServiceImpl"> <property name="staffDao" ref="staffDao"></property> </bean> </beans>
3.4、jsp 文件位置
- 實際開發中,所有的jsp頁面在WEB-INF目錄下。(因爲這樣,就不能通過瀏覽器直接訪問它們了)
- 例如:WEB-INF/pages/模塊/*.jsp,如下圖所示:
3.5、修改登錄表單
- 登錄表單位置:/day36_06_Spring_crm/WebRoot/WEB-INF/pages/login.jsp
- 表單是否需要struts標籤(<%@ taglib uri="/struts-tags" prefix="s"%>),取決於:是否回顯。要回顯,就需要struts標籤。
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML><HEAD> <STYLE> .cla1 { FONT-SIZE: 12px; COLOR: #4b4b4b; LINE-HEIGHT: 18px; TEXT-DECORATION: none } .login_msg{ font-family:serif; } .login_msg .msg{ background-color: #acf; } .login_msg .btn{ background-color: #9be; width: 73px; font-size: 18px; font-family: 微軟雅黑; } </STYLE> <TITLE></TITLE> <script type="text/javascript"> if(self != top){ top.location = self.location; } </script> <META http-equiv=Content-Type content="text/html; charset=utf-8"> <LINK href="${pageContext.request.contextPath}/css/style.css" type=text/css rel=stylesheet> <META content="MSHTML 6.00.2600.0" name=GENERATOR></HEAD> <BODY leftMargin=0 topMargin=0 marginwidth="0" marginheight="0" background="${pageContext.request.contextPath}/images/rightbg.jpg"> <div ALIGN="center"> <table border="0" width="1140px" cellspacing="0" cellpadding="0" id="table1"> <tr> <td height="93"></td> <td></td> </tr> <tr> <td background="${pageContext.request.contextPath}/images/right.jpg" width="740" height="412"></td> <td class="login_msg" width="400"> <!-- 表單 --> <s:form namespace="/" action="staffAction_login"> <img src="${pageContext.request.contextPath}/images/title.png" width="185" height="26"/> <br/> <font color="#ff0000"> <s:fielderror></s:fielderror> </font> <br/> 用戶名:<s:textfield name="loginName" cssClass="msg"></s:textfield><br/><br/> 密 碼:<s:password name="loginPwd" cssClass="msg" showPassword="true"></s:password><br/><br/> <s:submit value="登錄" cssClass="btn"></s:submit> </s:form> <!-- <form action="${pageContext.request.contextPath}/pages/frame.jsp" method="post"> <img src="${pageContext.request.contextPath}/images/title.png" width="185" height="26"/> <br/> <font color="#ff0000"> 錯誤提示 </font> <br/> 用戶名:<input type="text" name="loginName" class="msg" /><br/><br/> 密 碼:<input type="password" class="msg" /><br/><br/> <input type="submit" class="btn" value="登錄 " /> </form> --> <!-- jsp的頁面,作用:測試用,用完後刪除掉--> <a href="${pageContext.request.contextPath}/pages/frame.jsp">jsp頁面</a> </td> </tr> </table> <script type="text/javascript"> /* s標籤中直接編寫JavaScript代碼時,不支持el表達式,只能提供單獨的函數 function registerUrl() { document.location='${pageContext.request.contextPath}/uiAction_staff_register'; } */ </script> </div> </BODY></HTML>
3.6、struts-staff.xml 配置
- /day36_06_Spring_crm/config/struts/struts-staff.xml
struts-staff.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="sta" namespace="/" extends="common"> <action name="staffAction_*" class="com.itheima.crm.staff.web.action.StaffAction" method="{1}"> <!-- 1、登錄成功 --> <result name="success" type="redirectAction">staffAction_home</result> <!-- 2、登錄不成功,需要重新登錄 --> <result name="login">/WEB-INF/pages/login.jsp</result> <!-- 3、返回 首頁--> <result name="home">/WEB-INF/pages/frame.jsp</result> </action> </package> </struts>
3.7、Action實現類
StaffAction.java
package com.itheima.crm.staff.web.action; import com.itheima.crm.staff.domain.CrmStaff; import com.itheima.crm.staff.service.StaffService; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ModelDriven; public class StaffAction extends ActionSupport implements ModelDriven<CrmStaff> { // **************************************************************** // 公共代碼 // 封裝數據 private CrmStaff staff = new CrmStaff(); @Override public CrmStaff getModel() { return staff; } // 默認按照名稱進行注入 private StaffService staffService; public void setStaffService(StaffService staffService) { this.staffService = staffService; } // **************************************************************** // 業務代碼(功能代碼) /** * 員工登錄 * * @return */ public String login() { // 1、查詢員工 CrmStaff findStaff = staffService.login(staff); // 2、判斷是否成功 if (findStaff != null) { // 登錄成功 // 3.1、把數據保存在session作用域 ActionContext.getContext().getSession().put("loginStaff", findStaff); // 3.2、重定向至首頁,需要在 struts-staff.xml 中進行配置 return "success"; } // 4、登錄不成功,添加錯誤顯示信息 this.addFieldError("", "登錄名或密碼錯誤"); // 5、請求轉發顯示 return "login"; } /** * 顯示首頁 * * @return */ public String home() { return "home"; } }
3.8、密碼加密
- /day36_06_Spring_crm/src/com/itheima/crm/utils/MyStringUtils.java
編寫我的工具類 MyStringUtils.java
package com.itheima.crm.utils; import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class MyStringUtils { /** * 獲得MD5加密後的數據 * * @param value 明文 * @return 密文 */ public static String getMD5Value(String value) { try { // 1、獲得jdk所提供的消息摘要算法的工具類 MessageDigest messageDigest = MessageDigest.getInstance("MD5"); // 2、加密操作,加密的結果是十進制,需要轉換爲16進制 byte[] md5ValueByteArray = messageDigest.digest(value.getBytes()); BigInteger bigInteger = new BigInteger(1, md5ValueByteArray); return bigInteger.toString(16); } catch (NoSuchAlgorithmException e) { // 法一:拋出異常 throw new RuntimeException(e); // 法二:如果出現了異常,將返回默認值 // return value; } } }
- 修改service層代碼
package com.itheima.crm.staff.service.impl; import com.itheima.crm.staff.dao.StaffDao; import com.itheima.crm.staff.domain.CrmStaff; import com.itheima.crm.staff.service.StaffService; import com.itheima.crm.utils.MyStringUtils; public class StaffServiceImpl implements StaffService { private StaffDao staffDao; public void setStaffDao(StaffDao staffDao) { this.staffDao = staffDao; } @Override public CrmStaff login(CrmStaff staff) { // MD5加密操作 String loginPwd = MyStringUtils.getMD5Value(staff.getLoginPwd()); return staffDao.find(staff.getLoginName(), loginPwd); } }
四、UiAction
- 配置公共jsp訪問的action
struts.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> <!-- 1、常量配置 --> <!-- 1.1、開發模式 --> <constant name="struts.devMode" value="true"></constant> <!-- 1.2、標籤主題:簡單風格 --> <constant name="struts.ui.theme" value="simple"></constant> <!-- 2 、配置公共項 --> <package name="common" namespace="/" extends="struts-default"> <!-- 2.1、配置公共jsp訪問的action 版本1:通過自定義action實現,自定義的action繼承父類ActionSupport <action name="uiAction" class="com.itheima.crm.web.action.UiAction"> <result name="success">/WEB-INF/pages/frame/top.jsp</result> </action> 版本2:直接通過父類ActionSupport <action name="uiAction" class="com.opensymphony.xwork2.ActionSupport"> <result name="success">/WEB-INF/pages/frame/top.jsp</result> </action> 能否將class屬性刪除呢? 因爲class屬性的默認值就是“ActionSupport” <action name="uiAction"> <result name="success">/WEB-INF/pages/frame/top.jsp</result> </action> name屬性值也可以刪除掉,因爲其默認值也是“success” <action name="uiAction"> <result>/WEB-INF/pages/frame/top.jsp</result> </action> 版本3:使用通配符 <action name="uiAction_*_*"> <result>/WEB-INF/pages/{1}/{2}.jsp</result> </action> uiAction_*_* 第一個星匹配的是文件夾的名稱,通過{1}獲取 第二個星匹配的是jsp文件名稱,通過{2}獲取 例如: uiAction_frame_top 匹配的是 /WEB-INF/pages/frame/top.jsp --> <action name="uiAction_*_*"> <result>/WEB-INF/pages/{1}/{2}.jsp</result> </action> </package> <!-- 3、 加載其他配置文件 --> <include file="struts/struts-staff.xml"></include> </struts>
五、登錄攔截器
必須是登錄狀態,才能訪問首頁,否則不能訪問。
- 回顧登錄攔截器實現類
- struts中的配置
- 先註冊,將登錄攔截器實現類配置給struts
- 再使用 2.1 每一個action單獨使用登錄攔截器 2.2 將多個攔截器打包生成自定義棧,在action中使用自定義棧 2.3 使用自定義的棧,把默認的棧覆蓋(即把自定義棧聲明成默認的棧)
- 功能:判斷session作用域中是否有用戶信息,如果有就放行,如果沒有就攔截掉。
5.1、實現類
LoginInterceptor.java
package com.itheima.crm.web.interceptor; import com.itheima.crm.staff.domain.CrmStaff; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor; public class LoginInterceptor extends MethodFilterInterceptor { @Override protected String doIntercept(ActionInvocation invocation) throws Exception { // 判斷session作用域中是否有用戶信息,如果有就放行,如果沒有就攔截掉。 CrmStaff crmStaff = (CrmStaff) ActionContext.getContext().getSession().get("loginStaff"); if (crmStaff == null) { // 同理:StaffAction.java中的login()方法一樣: // 1、獲得當前運行的action Object action = invocation.getAction(); // 2、判斷:在運行時的action對象是否是ActionSupport對象 if (action instanceof ActionSupport) { // 如果是,就進行強轉 ActionSupport actionSupport = (ActionSupport) action; // 4、登錄不成功,添加錯誤顯示信息 actionSupport.addFieldError("", "請重新登錄"); } // 沒有登錄,需要登錄 return "login"; } // 已經登錄了,就放行 return invocation.invoke(); } }
5.2、struts.xml 中的配置
struts.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> <!-- 1、常量配置 --> <!-- 1.1、開發模式 --> <constant name="struts.devMode" value="true"></constant> <!-- 1.2、標籤主題:簡單風格 --> <constant name="struts.ui.theme" value="simple"></constant> <!-- 2 、配置公共項 --> <package name="common" namespace="/" extends="struts-default"> <!-- 2.2、登錄攔截器的配置 前提:都要先聲明 方式一:每一個action單獨使用登錄攔截器,需要多次引用,否則默認的攔截器將被覆蓋 <action name="uiAction_*_*"> <result>/WEB-INF/pages/{1}/{2}.jsp</result> <interceptor-ref name="defaultStack"></interceptor-ref> <interceptor-ref name="loginInterceptor"></interceptor-ref> </action> 方式二:將多個攔截器打包生成自定義棧,在action中使用自定義棧 <interceptor-stack name="loginStack"> <interceptor-ref name="defaultStack"></interceptor-ref> <interceptor-ref name="loginInterceptor"></interceptor-ref> </interceptor-stack> <action name="uiAction_*_*"> <result>/WEB-INF/pages/{1}/{2}.jsp</result> <interceptor-ref name="loginStack"></interceptor-ref> </action> 方式三:使用自定義的棧,把默認的棧覆蓋(即把自定義棧聲明成默認的棧) <default-interceptor-ref name="loginStack"></default-interceptor-ref> <action name="uiAction_*_*"> <result>/WEB-INF/pages/{1}/{2}.jsp</result> <interceptor-ref name="loginStack"></interceptor-ref> </action> --> <interceptors> <!-- 2.2.1、聲明(註冊),將登錄攔截器實現類配置給struts --> <interceptor name="loginInterceptor" class="com.itheima.crm.web.interceptor.LoginInterceptor"></interceptor> <!-- 2.2.2、 自定義攔截器棧 --> <interceptor-stack name="loginStack"> <interceptor-ref name="defaultStack"></interceptor-ref> <!-- 自定義登錄攔截器:需要配置對login()方法不進行攔截 * excludeMethods 配置不包含的方法,多個方法使用逗號分隔 --> <interceptor-ref name="loginInterceptor"> <param name="excludeMethods">login</param> </interceptor-ref> </interceptor-stack> </interceptors> <!-- 2.2.3、 使用自定義的棧,把默認的棧覆蓋(即把自定義棧聲明成默認的棧)--> <default-interceptor-ref name="loginStack"></default-interceptor-ref> <!-- 2.2.4、配置全局結果集 --> <global-results> <result name="login">/WEB-INF/pages/login.jsp</result> </global-results> <!-- 2.1、配置公共jsp訪問的action --> <action name="uiAction_*_*"> <result>/WEB-INF/pages/{1}/{2}.jsp</result> <interceptor-ref name="loginStack"></interceptor-ref> </action> </package> <!-- 3、 加載其他配置文件 --> <include file="struts/struts-staff.xml"></include> </struts>
5.3、登錄攔截器總結圖解
六、查詢所有員工
思路: 1. dao層:findAll() 2. service層:findAllStaff() 3. action類:findAll() --> staffAction_findAll 4. jsp頁面:顯示數據
6.1、dao 層
StaffDao.java
/** * 查詢所有員工 * * @return */ public List<CrmStaff> findAll();
StaffDaoImpl.java
@Override public List<CrmStaff> findAll() { return this.getHibernateTemplate().find("from CrmStaff"); }
6.2、service層
StaffService.java
/** * 查詢所有員工 * * @return */ public List<CrmStaff> findAllStaff();
StaffServiceImpl.java
@Override public List<CrmStaff> findAllStaff() { return this.staffDao.findAll(); }
6.3、jsp入口
- /day36_06_Spring_crm/WebRoot/WEB-INF/pages/frame/left.jsp
6.4、action類
StaffAction.java
...... /** * 查詢所有員工 * * @return */ public String findAll() { // 1、查詢所有員工 List<CrmStaff> allStaff = staffService.findAllStaff(); // 2、將查詢的結果放入值棧中,以方便jsp頁面獲得數據(原則:無論你怎麼放,頁面上能取的出來就行) // 方式一:context(大map中),使用put(key, value) 方法,jsp頁面使用 “#key” 方式獲得 // 示例:ActionContext.getContext().put(key, value); // 方式二:root(值棧中),使用push(Object)方法,一般我們的查詢結果爲javabean 或者 爲Map時,jsp頁面使用 “屬性”或者“key” 方式獲得 // 示例:ActionContext.getContext().getValueStack().push(obj); // 方式三:root(值棧中),使用set(key, value),一般我們的查詢的結果爲 集合List 時,jsp頁面使用 “key” 方式獲得 // 注意:set(key, value) 的底層使用的是 new Map(key, value),再將Map集合 push(Map) // 這裏我們使用方式一 ActionContext.getContext().put("allStaff", allStaff); return "findAll"; } ......
6.5、jsp展示
- /day36_06_Spring_crm/WebRoot/WEB-INF/pages/staff/listStaff.jsp
- debug調試結果:
6.6、web.xml 配置過濾器
- OpenSessionInViewFilter,作用:延遲關閉session
- 注意:必須配置在struts 的前端控制器之前
<!-- 配置spring 過濾器,延時session的關閉 --> <filter> <filter-name>OpenSession</filter-name> <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class> </filter> <filter-mapping> <filter-name>OpenSession</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
- 查詢所有員工截圖: