S2SH整合开发——登录

本文用S2SH实现用户登录。

框架图

这里写图片描述
Modle层就是对应的数据库表的实体类(如User类)。

Dao层,一般可以再分为***Dao接口和***DaoImpl实现类,如userDao接口和userDaoImpl实现类,接口负责定义数据库curd的操作方法,实现类负责具体的实现,即实现Dao接口定义的方法。
一个DAO单独对1个表进行CURD/排序/分页等操作。

Service层,引用对应的Dao层数据库操作,在这里可以编写自己需要的代码(比如简单的判断),也可以再细分为Service接口和ServiceImpl实现类。
一个Service可以操作几个DAO。

Action层:引用对应的Service层实现业务逻辑,在这里结合Struts的配置文件,跳转到指定的页面,当然也能接受页面传递的请求数据,也可以做些计算处理、前端输入合法性检验(前端可修改网页绕过前端合法性检验,需在后台加一层)。

Model层开发

model层开发主要包括创建实体类及映射文件。

实体类创建

UseInfo:

package com.digital.entity;

import java.util.Date;

public class UserInfo {
    private int id;
    private String userName;
    private String password;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }


    // 无参构造
    public UserInfo() {
    }

    // 有参构造
    public UserInfo(String userName, String password, Date regDate) {
        this.userName = userName;
        this.password = password;
    }

}

创建映射文件

UserInfo.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 package="com.digital.entity">
    <class name="UserInfo" table="user_info" catalog="digital">
        <id name="id" type="java.lang.Integer">
            <column name="id" />
            <generator class="native"></generator>
        </id>
        <property name="userName" type="java.lang.String">
            <column name="userName" length="16" not-null="true" />
        </property>
        <property name="password" type="java.lang.String">
            <column name="password" length="16" not-null="true" />
        </property>
    </class>
</hibernate-mapping>

Spring与Hibernate的整合

先回顾一下Hibernate的运行过程:

  1. 通过Configuration().configure();读取并解析hibernate.cfg.xml配置文件
  2. 由hibernate.cfg.xml中的<mapping resource="xxx.hbm.xml"/>读取并解析映射信息
  3. 通过config.buildSessionFactory();//创建SessionFactory
  4. sessionFactory.openSession();//打开Sesssion
  5. session.beginTransaction();//创建事务Transation
  6. persistent operate持久化操作 //一般指Save这个方法
  7. session.getTransaction().commit();//提交事务
  8. 关闭Session

很关键的就是sessionFacctory了,Spring整合Hibernate的目的就在于用Spring的IoC容器来管理Hibrenate的SessionFactory(把它当成了一个Bean),同时让Hibernate使用Spring的声明式事务,而这些都是在spring配置文件中完成的。

applicationContext中整合Hibernate的部分:

<?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:p="http://www.springframework.org/schema/p"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">      


    <!-- 配置数据源 -->
    <bean id="dataSource"  
        class="com.mchange.v2.c3p0.ComboPooledDataSource">  
        <property name="driverClass" value="com.mysql.jdbc.Driver" />  
        <property name="jdbcUrl" value="jdbc:mysql:///digital" />  
        <property name="user" value="root" />  
        <property name="password" value="admin" />   
        <property name="minPoolSize" value="5" />  
        <property name="maxPoolSize" value="10" />
    </bean>  

    <!-- 配置Hibernate的sessionFactory实例 -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <!-- 配置数据源属性 -->
        <property name="dataSource">
            <ref bean="dataSource" />
        </property>
        <!-- 配置 Hibernate的基本属性-->
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">
                    org.hibernate.dialect.MySQLDialect
                </prop>
            </props>
        </property>
        <!-- 配置 Hibernate映射文件的位置及名称-->
        <property name="mappingResources">
            <list>
                <value>com/digital/entity/UserInfo.hbm.xml</value>
            </list>
        </property>
    </bean>

    <!-- 声明Hibernate事务管理器 -->
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <!--  定义事务通知 ,需要事务管理器  --> 
    <tx:advice id="txAdvice" transaction-manager="transactionManager">   
      <!-- 指定事务传播规则 -->
      <tx:attributes>
        <!-- 对所有方法应用REQUIRED事务规则 -->
        <tx:method name="*" propagation="REQUIRED" /> 
      </tx:attributes>
    </tx:advice>

    <!--定义切面,并将事务通知和切面组合(定义哪些方法应用事务规则) -->
    <aop:config>
        <!-- 对com.digital.service包下的所有类的所有方法都应用事务规则 -->
        <aop:pointcut id="serviceMethods" expression="execution(* com.digital.service.*.*(..))" /> 
        <!--  将事务通知和切面组合   --> 
        <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods" /> 
    </aop:config>

DAO层开发

DAO层主要实现与数据库交互的代码:

UserInfoDAO接口

package com.digital.dao;

import java.util.List;
import com.digital.entity.*;

public interface UserInfoDAO {
    public List<UserInfo> search(UserInfo cond);

}

UserInfoDAOImpl

package com.digital.dao.impl;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Example;

import com.digital.dao.UserInfoDAO;
import com.digital.entity.UserInfo;

public class UserInfoDAOImpl implements UserInfoDAO {

    SessionFactory sessionFactory;
    //通过注入方式获得实例
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    @Override
    public List<UserInfo> search(UserInfo cond) {
        List<UserInfo> uiList = null;
        // 获得session
        Session session = sessionFactory.getCurrentSession();
        // 创建Criteria对象
        Criteria c = session.createCriteria(UserInfo.class);
        // 使用Example工具类创建示例对象
        Example example = Example.create(cond);
        // 为Criteria对象指定示例对象example作为查询条件
        c.add(example);
        // 执行查询
        uiList = c.list();
        // 返回结果
        return uiList;
    }
}

添加DAO的bean到applicationContext

<!-- 定义com.digital.dao.impl.UserInfoDAOImpl类-->
<bean id="userInfoDAO" class="com.digital.dao.impl.UserInfoDAOImpl">      
    <property name="sessionFactory" ref="sessionFactory" /></bean>

Service层开发

UserInfoService接口

package com.digital.service;

import java.util.List;
import com.digital.entity.*;

public interface UserInfoService {
    public List<UserInfo> login(UserInfo cond);
}

UserInfoServiceImpl

package com.digital.service.impl;

import java.util.List;

import com.digital.dao.UserInfoDAO;
import com.digital.entity.UserInfo;
import com.digital.service.UserInfoService;

public class UserInfoServiceImpl implements UserInfoService {

    UserInfoDAO userInfoDAO;    
    //注入获得实例
    public void setUserInfoDAO(UserInfoDAO userInfoDAO) {
        this.userInfoDAO = userInfoDAO;
    }

    @Override
    public List<UserInfo> login(UserInfo cond) {
        return userInfoDAO.search(cond);
    }

}

添加Service的bean到applicationContext

<!-- 定义UserInfoServiceImpl类,并为其userInfoDAO属性注入值-->
<bean id="userInfoService" class="com.digital.service.impl.UserInfoServiceImpl">      
    <property name="userInfoDAO" ref="userInfoDAO" />
</bean>

Action开发

package com.digital.action;

import java.util.List;

import com.digital.entity.*;
import com.digital.service.UserInfoService;
import com.opensymphony.xwork2.ActionSupport;

public class UserInfoAction extends ActionSupport {

    UserInfo ui;

    public UserInfo getUi() {
        return ui;
    }

    public void setUi(UserInfo ui) {
        this.ui = ui;
    }

    UserInfoService userInfoService;

    public void setUserInfoService(UserInfoService userInfoService) {
        this.userInfoService = userInfoService;
    }

    public String doLogin() throws Exception {
        List<UserInfo> uiList = userInfoService.login(ui);
        if (uiList.size() > 0) {
            // 登录成功,转发到到index.jsp
            return "index";
        } else {
            // 登录失败,重定向到login.jsp
            return "login";
        }

    }

}

Spring整合Struts2

先来回顾一下struts2执行原理:

这里写图片描述

此外,struts2还有个很重要的valuestack来保存action等东西:

这里写图片描述

创建action对象的方法有很多,一种是利用struts2本身的反射机制,通过ObjectFactory来创建action对象。第二个就是把创建对象委托给其他容器,例如spring。
Spring整合Struts2的目的在于使用Spring IOC容器来管理Struts2的Action。

web.xml配置

ssh框架中,我们通过配置就可以实现spring容器随着Tomcat/Jboss等的启动而自动启动,而无需我们手动开启。这是通过监听器来实现的,当spring容器启动后,自动读取并加载相应的配置文件。

<!-- 指定以Listerner方式启动Spring -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 指定Spring配置文件的位置 -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>
<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>

添加UserInfoAction的bean到applicationContext

用prototype,每个用户都会创建一个新的Bean实例。

<!-- 定义UserInfoAction类 ,并为其中属性userInfoService注入值 -->
<bean name="uiAction" class="com.digital.action.UserInfoAction" scope="prototype">
    <property name="userInfoService" ref="userInfoService" />
</bean>

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.i18n.encoding" value="utf-8"></constant>
    <!-- 定义一个名称为digital的包,继承struts 2的默认包,指定命名空间为"/" -->
    <package name="digital" namespace="/" extends="struts-default">
        <!-- 为类中的方法配置映射 -->
        <action name="doLogin" class="uiAction" method="doLogin"><!--class引用bean实例-->
            <result name="index" type="dispatcher">index.jsp</result>
            <result name="login" type="redirect">login.jsp</result>
        </action>
    </package>
</struts>    
关于dispatcher和redirect的区别

这里写图片描述

dispatcher用于两个组件协同工作的时候,而redirect用于一个工作完成之后开始下一个工作,重定向之后当前页面的所有数据信息在下一个页面将全部失效,也就是说,使用redirect跳转页面的时候不能把当前页面的参数传递到下一个页面。
比如:登录成功之后应该用redirect重定向不能用dispatcher,因为登录成功表示一个工作已经完成,如果用重定向的话,由于地址还是原来的地址,用户刷新页面之后又会要求重新登录,不符合常理。

创建交互页面

login.jsp

<%@ page language="java" import="java.util.*" pageEncoding="gbk"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>登录页</title>
</head>

<body>
    <s:form action="doLogin">
        <table>
            <tr>
                <s:textfield name="ui.userName" label="用户名" />
            </tr>
            <tr>
                <s:textfield name="ui.password" label="密码" />
            </tr>
            <tr>
                <s:submit value="登录" />
            </tr>
        </table>
    </s:form>

</body>
</html>

登录成功页面
index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<html>
  <head>    
    <title>系统首页面</title>
  </head>  
  <body>
      欢迎您,登录成功!
  </body>
</html>

Server MyEclipse Tomcat v8.5 was unable to start within 45 seconds. If the server requires more time…

解决办法是在Workpaces->.metadata->.plugins->org.eclipse.wst.server.core->servers.xml修改timeout大一点就行了,项目一大,所需的时间也就会越长。

执行流程

  1. 从页面开始,提交表单或者点击链接会触发一个action(doLogin)

  2. action交给struts2处理,读取src目录struts.xml文件,在配置中找到对应的action

  3. 根据class=”XXXAction”交给Spring(为什么struts的action会交给spring处理呢?
    原因是:Struts2提供一个jar包:struts2-spring-plugin-2.1.2.jar,有个struts.properties文件配置了这样一句话:struts.objectFactory.spring.autoWire = name。
    也就是有了上面那个jar包之后,根据name自动提交给Spring处理,读取Spring容器的配置文件/WebRoot/WEB-INF/applicationContext.xml文件。 根据applicationContext.xml配置文件找到xxx.xxx.action.xxxAction类,
    其中有一个属性xxxService,并提供了setxxxService()方法,由applicationContext.xml文件得知该xxxService对象由Spring容器依赖注入,set注入。

  4. 取得xxxService对象(接口对接口实现类的一个引用)后,调用它的方法。后面的就是访问DAO了,一长串省略号代替

  5. 执行的结果会在action的对应的方法中以字符串的形式给出。然后根据配置文件中的result.找到下一步要执行的动作,是跳转到页面显示还是继续交给其他的action处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值