day37_Spring學習筆記_05_CRM_01

一、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">
                    &nbsp;<img src="${pageContext.request.contextPath}/images/title.png" width="185" height="26"/>
                    <br/>
                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                    <font color="#ff0000">
                        <s:fielderror></s:fielderror>
                    </font> 
                    <br/>
                    用戶名:<s:textfield name="loginName" cssClass="msg"></s:textfield><br/><br/>
                    密&nbsp;碼:<s:password name="loginPwd" cssClass="msg" showPassword="true"></s:password><br/><br/>
                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                    <s:submit value="登錄" cssClass="btn"></s:submit>         
                </s:form>
                <!-- 
                <form action="${pageContext.request.contextPath}/pages/frame.jsp" method="post">
                    &nbsp;<img src="${pageContext.request.contextPath}/images/title.png" width="185" height="26"/>
                    <br/>
                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                    <font color="#ff0000">
                        錯誤提示
                    </font> 
                    <br/>
                    用戶名:<input type="text" name="loginName" class="msg" /><br/><br/>
                    密&nbsp;碼:<input type="password" class="msg" /><br/><br/>
                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                    <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中的配置
    1. 先註冊,將登錄攔截器實現類配置給struts
    2. 再使用 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>
  • 查詢所有員工截圖:
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章