一、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
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
public interface StaffDao {
/**
* 通过用户名和密码查询
*
* @param loginName
* @param loginPwd
* @return
*/
public CrmStaff find(String loginName, String loginPwd);
}
StaffDaoImpl.java
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
public interface StaffService {
/**
* 用户登录
*
* @param staff
* @return
*/
public CrmStaff login(CrmStaff staff);
}
StaffServiceImpl.java
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
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
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
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>
- 查询所有员工截图: