2.基于SSH框架的CRM系统学习-员工登陆

1. Dao层编写

1) Dao层接口

登录功能即在数据库中查找有无该员工,即:

public interface StaffDao {
	/**
	 * 通过用户名和密码查询
	 * @param loginName
	 * @param loginPwd
	 * @return
	 */
	public CrmStaff find(String loginName, String loginPwd);
}

2) Dao层实现类

由于采用Hibernate,故实现类继承HibernateDaoSupport类,sessionFactory在spring配置文件内已经注入。若能在数据库中根据登录名和密码找到员工则返回员工类的对象,找不到返回null。

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

注意点:

  • 按条件查询函数find(String sql, Object args..),返回List集合

2. Service层编写

1) Service层接口

登陆功能,返回员工类对象,方便存入session域中

public interface StaffService {
	public CrmStaff login(CrmStaff staff);
}

2) Service层实现类

Service层一般还要对数据进行一些处理,这里对密码进行了MD5加密,即数据库内存储的密码非明文密码。

在Service层有Dao层对象,但不能new出来,而是要写出其set方法以使spring可以为其注入。

public class StaffServiceImpl implements StaffService{

	private StaffDao staffDao;
	public void setStaffDao(StaffDao staffDao) {
		this.staffDao = staffDao;
	}
	@Override
	public CrmStaff login(CrmStaff staff) {
		String loginPwd = MyStringUtils.getMD5Value(staff.getLoginPwd());
		return staffDao.find(staff.getLoginName(), loginPwd);
	}
}

这里使用了自定义的MD5加密方法,封装在MyStringUtils里

public static String getMD5Value(String value) {		
    try {
        //1 获得jdk提供的消息摘要算法工具类
        MessageDigest messageDigest = MessageDigest.getInstance("MD5");
        //2 加密
        byte[] md5ValueByteArray = messageDigest.digest(value.getBytes());
        //3 将10进制转化为16进制
        BigInteger bigInteger = new BigInteger(1, md5ValueByteArray);
        
        return bigInteger.toString(16);
    } catch (NoSuchAlgorithmException e) {
        return value;
    }


3. Spring配置

在applicationContext-staff.xml中添加配置

	<!-- 员工配置项 -->
	<bean id="staffDao" class="com.web.crm.staff.dao.StaffDaoImpl">
		<property name="sessionFactory" ref="sessionFactory"></property>
	</bean>
	
	<bean id="staffService" class="com.web.crm.staff.service.impl.StaffServiceImpl">
		<property name="staffDao" ref="staffDao"></property>
	</bean>

4. 修改登陆表单

注意点:

  • 所有的jsp页面都应放在WEB-INF下,这样就无法通过浏览器直接访问,因为struts拦截器只拦截action而不拦截页面。

使用struts标签修改form表单,这样可以回显

<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"></s:password><br/><br/>
           
    <s:submit value="登陆" cssClass="btn"></s:submit>					

</s:form>

5. 编写Action实现类

不同的模块在不同的Action类里写,这里员工登陆新建一个StaffAction实现类,其父类为ActionSupport,并实现ModelDriven接口以实现从页面传来的参数自动封装。这里的写法都是固定的:

public class StaffAction extends ActionSupport implements ModelDriven<CrmStaff> {
    //封装数据,这里必须要new出来
	private CrmStaff staff = new CrmStaff();

	@Override
	public CrmStaff getModel() {
		
		return staff;
	}
    //默认按照名称注入
	private StaffService staffService;
	public void setStaffService(StaffService staffService) {
		this.staffService = staffService;
	}
员工登陆方法书写的思路是:数据库查询员工->返回对象不为空表示有该员工->将对象保存在session域中->重定向到首页;返回对象为空->向错误域中保存错误信息->请求转发到登陆页面
public String login() {
    CrmStaff crmStaff = staffService.login(staff);
    if (crmStaff != null) {
        //成功,向session域内保存登陆信息
        ActionContext.getContext().getSession().put("loginStaff", crmStaff);
        return "success";
    }
    //不成功
    this.addFieldError("", "用户名或密码错误");
    //请求转发
    return "login";
}

6. 设置登陆拦截器

实际应用过程中,用户必须登陆后才能访问其他页面,如果未经登陆就访问其他action,应当有一个拦截器对其进行拦截。因此我们需要编写一个自定义拦截器,该类需要继承MethodFilterInterceptor 类,并重写其doIntercept方法:

public class LoginInterceptor extends MethodFilterInterceptor {
	@Override
	public String doIntercept(ActionInvocation invocation) throws Exception {
		
		//判断session作用域是否有用户信息,如果有放行,如果没有拦截。
		
		Object obj = ActionContext.getContext().getSession().get("loginStaff");
		if(obj == null){
			/**友好信息 start*/
			// 1 获得当前运行action
			Object action = invocation.getAction();
			// 2 判断运行时是否是ActionSupport
			if(action instanceof ActionSupport){
				ActionSupport actionSupport = (ActionSupport) action;
				actionSupport.addFieldError("", "请登录");
			}
			/**友好信息 end*/
			
			// 没有登录,需要登录
			return "login";
		}
		
		//登录,放行
		return invocation.invoke();
	}
}
自定义拦截器类写完后,我们需要将其配置在公共的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>
	<constant name="struts.devMode" value="true"></constant>
	<constant name="struts.ui.theme" value="simple"></constant>
	<!-- 公共项 -->
	<package name="common" namespace="/" extends="struts-default">
		<!-- 拦截器配置 -->
		<interceptors>
			<!-- @1 声明(注册)拦截器 -->
			<interceptor name="loginInterceptor" class="com.web.crm.web.interceptor.LoginInterceptor"></interceptor>
			<!-- @2 自定义拦截器栈 -->
			<interceptor-stack name="loginStack">
				<interceptor-ref name="defaultStack"></interceptor-ref>
				<!-- 自定义拦截器需要对login不拦截 -->
				<interceptor-ref name="loginInterceptor">
					<param name="excludeMethods">login</param>
				</interceptor-ref>
			</interceptor-stack>
		</interceptors>
		<!-- @3 声明默认 -->
		<default-interceptor-ref name="loginStack"></default-interceptor-ref>
		<!-- @4 全局结果集 -->
		<global-results>
			<result name="login">/WEB-INF/pages/login.jsp</result>
		</global-results>
		<!-- 配置公共jsp访问action -->
		<action name="UIAction_*_*">
			<result>/WEB-INF/pages/{1}/{2}.jsp</result>
		</action>
	</package>
	
	<include file="struts/struts-staff.xml"></include>
</struts>

注意全局结果集的写法,对应之前Action类中login方法,若session中不存在员工对象则返回login,然后页面转发到login.jsp

在上面的xml中我们额外写了一个名为UIAction的action,这个动作的目的在于使其他jsp页面上的链接可以通过action访问到其他页面,并且必须通过拦截器,用法如:

<frameset rows="90,*" framespacing="0px" frameborder="no">
	<frame src="${pageContext.request.contextPath}/UIAction_frame_top.action" scrolling="no"/>
    <frameset id="main" cols="170,9,*" framespacing="0px" frameborder="no" >
        <frameset rows="30,*,40" framespacing="0px" frameborder="no" >
			<frame src="${pageContext.request.contextPath}/UIAction_frame_left1.action" scrolling="no"/>
            <frame src="${pageContext.request.contextPath}/UIAction_frame_left.action" scrolling="no"/>
            <frame src="${pageContext.request.contextPath}/UIAction_frame_left2.action" scrolling="no"/>
        </frameset>
        <frame src="${pageContext.request.contextPath}/UIAction_frame_control.action" scrolling="no"/>
        <frame src="${pageContext.request.contextPath}/UIAction_frame_right.action" name="right" scrolling="yes"/>
	</frameset>
</frameset>

7. 员工登陆动作的xml配置

在struts-staff.xml中添加如下配置

<package name="sta" namespace="/" extends="common">
    <action name="staffAction_*" class="com.web.crm.staff.web.action.StaffAction" method="{1}">
        <result name="success" type="redirectAction">staffAction_home</result>			
        <result name="home">/WEB-INF/pages/frame.jsp</result>
        <result name="findAll">/WEB-INF/pages/staff/listStaff.jsp</result>
        <result name="editUI">/WEB-INF/pages/staff/editStaff.jsp</result>
    </action>		
</package>

注意:

  • action的name我们采用通配符的方式,因此我们在调用action时实际写法为“staffAction_method”,method为我们所写的Action类中的方法,这里调用登陆的方法即为staffAction_login


至此员工登陆功能编写完毕,整个思路流程如下:

  1. 写Dao层,注意点是继承HibernateDaoSupport类,并注意查询语句写法。
  2. 写Service层,额外的功能在该层编写,如本例中的密码MD5加密。
  3. 配置spring对应的xml文件,即写<bean>。
  4. 修改jsp页面的form表单,登陆功能比较简单。
  5. 编写登陆的Action实现类,继承ActionSupport类并实现ModelDriven接口以实现对表单对象的自动封装,之后编写登陆方法。
  6. 配置struts对应的xml文件,注意通配符的写法。
  7. 编写登陆拦截器,自定义拦截器类并将其配置在xml中,本例写法为自定义一个拦截器栈并将其设为默认栈。


猜你喜欢

转载自blog.csdn.net/m0_37683852/article/details/80774090
今日推荐