BOS2

内容(1)在业务中会重复性的增删改查的操作做Dao的封装来简化,Dao层的开发。

  (2)Spring Data JPA :主要针对的就是Spring唯一没有简化到的业务逻辑代码,至此,开发者练仅剩的实现持久层业务逻辑的工作都省了,唯一要做到,就只是声明持久层的接口,其他都交给Spring Data JPA来帮你完成!

  (3)建表--》实体类               封装dao---->spring data  jpa   Respository接口(重点)   业务层封装

  (4)Action封装  共性:接收客户端请求,封装数据到Model         需要继承和实现,重复性代码。    操作request和response都封装到BaseAction  操作 请求数据-request.getParameter/values

  (5)封装好之后实现用户的登录,封装是为了后面的代码简化,不会太繁琐。

 

1、使用PD根据大纲绘制用户表

  建模工具来设计表。

  PD的作用,通过建模工具    绘制表设计---->根据不同数据库生成不同脚本!mysql--->oracle

  PD是绘制表设计图例,xxx.pdm文件--->pd---->生成不同数据库脚本。

  

  安装好之后,new一个Physical Data  Model:物理数据模型。这个模型就会建立图例生成底层的sql。

  密码用MD5加密,一般是32位。

  tools--->PDM Generation Options可以切换成oracle数据库。

  

但是需要去掉引号,

mysql-->source  拖入文件也可以执行.sql文件。

 

2、通过表反向生成实体类

        <!-- hibernate-tools 反向生成实体类 -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-tools</artifactId>
        </dependency>
        <plugins>
            <!--通过命令直接生成实体类 和注解或配置文件 User.hbm.xml-->
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>hibernate3-maven-plugin</artifactId>
                <configuration>
                    <components>
                        <component>
                            <!-- 命令 可以生成实体类对应映射文件 User.hbm.xml -->
                            <name>hbm2hbmxml</name>
                            <implementation>jdbcconfiguration</implementation>
                            <!-- 文件输出位置 -->
                            <outputDirectory>target/generated-resources/hibernate</outputDirectory>
                        </component>
                        <component>
                            <!-- 命令 生成实体类的 但是不会生成注解的 -->
                            <name>hbm2java</name>
                            <implementation>jdbcconfiguration</implementation>
                            <outputDirectory>target/generated-sources/hibernate</outputDirectory>
                        </component>
                    </components>
                    <componentProperties>
                        <!-- 该配置文件必须存放该目录下 作用: 根据表生成实体类 定义实体类生成规范 -->
                        <revengfile>src/main/resources/reveng.xml</revengfile>
                        <!-- hibernate.properties 文件 插件需要连接数据库 配置信息 -->
                        <propertyfile>src/main/resources/hibernate.properties</propertyfile>
                        <!-- 生成实体类默认生成包名 -->
                        <packagename>cn.itcast.mavenbos.domain</packagename>
                        <jdk5>true</jdk5>
                        <!-- true 生成注解 /false 没有注解 -->
                        <ejb3>true</ejb3>
                    </componentProperties>
                </configuration>
            </plugin>
View Code

  Domain模块

  插件已经安装成功

  将需要的配置文件拷贝到src/main/resource目录

  Reveng.xml定义实体类生成规则,表名的定义   主键策略生成     字段属性名定义  长度

  Hibernate.properties文件 插件连接数据库信息

  (1)Hibernate.properties

    

hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.connection.url=jdbc:mysql:///zero_bos
hibernate.connection.username=root
hibernate.connection.password=123

  (2)reveng.xml可以先不定义

  (3)独立执行bos-domain       hibernate3:hbm2java 命令;

    项目右键----->run  as----->Maven build---->Goals: hibernate3:hbm2java    ------>run

    定义reveng.xml 文件 定义实体类生成规则 

    <!-- match-table:访问表的 (代表这个表能够被找到).对于数据库zero_bos下面t_user表定义实体类生成规则 -->
    <schema-selection match-table="t_user" match-catalog="zero_bos" />
    <!-- 实体类生成规则定义 -->
    <table name="t_user" catalog="zero_bos"
        class="com.zero.bos.domain.user.User">
        <primary-key>
    <!-- uuid主键(字符)  identity:主键自增长-->
            <generator class="uuid"></generator>
        </primary-key>
    </table>
</hibernate-reverse-engineering>

  配置好reveng.xml之后再重新运行一下。

  就会生成主键为uuid的User类。

  

     @GenericGenerator(name="generator", strategy="uuid")@Id @GeneratedValue(generator="generator")
    
    @Column(name="ID", unique=true, nullable=false, length=32)
    public String getId() {
        return this.id;
    }

3、Spring data jpa学习

  Maven配置  在domain.xml已经引入相关spring data jpa

  模块开始配置  applicationContext-domain.xml来进行domain与spring的整合。

  

  (1)首先domain需要一个注册文件来注册实体类

    entityManagerFactory管理实体类

  在resources中的

  hibernate.properties是反向代理工具用来通过数据库表来生成实体类的

  jdbc.properties是数据库连接池使用的外部配置文件

  配置文件需要写入(1)数据库连接池(2)entityManagerFactory工厂类型sessionFactory

  context配置文件需要:(1)引入数据库连接池外部配置文件(2)包扫码:扫码注解(类似@Controller)(3)配置连接池信息(4)EntityManagerFactory

  全部配置文件:

  applicationContest-domian.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:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/data/jpa
    http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
    <!-- 数据库    连接池    jpa EntityManagerFactory    连接池需要的外部配置文件 -->
    <context:property-placeholder location="classpath:jdbc.properties" />
    <!-- 开始Spring注解@Controller @Service @Respository @Autowired @Scope -->
    <context:component-scan base-package="com.zero.bos"></context:component-scan>
    <!-- 配置连接池信息 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!-- 配置 连接数据库参数 c3p0 连接池 -->
        <property name="driverClass" value="${jdbc.driverClass}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="user" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>
    
    <!-- sessionFactory   类似EntityMangerFactory        spring data jpa 配置学习 参照官方文档 EntityManagerFacotry -->
    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <!-- 自动扫描实体类 包以及子包 -->
        <property name="packagesToScan" value="com.zero.bos.domain" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="database" value="MYSQL" />
                <!-- 自动建表 -->
                <property name="generateDdl" value="true" />
                <!-- 方言 -->
                <property name="databasePlatform" value="${jdbc.dialect}"></property>
                <!-- 显示sql -->
                <property name="showSql" value="true"></property>
            </bean>
        </property>
    </bean>





</beans>
View Code

jdbc.properties文件内容:  

jdbc.url=jdbc:mysql:///zero_bos
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=123
jdbc.dialect=org.hibernate.dialect.MySQL5Dialect

测试:(1)main方法进行加载applicationContext-domain.xml就自动建表

   (2)启动tomcat,也会自动加载,但是因为tomcat是首先加载web.xml的所以,需要在web.xml中添加applicationContext-domain.xml

    

    <!-- spring配置文件位置 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml,classpath:applicationContext-domain.xml</param-value>
    </context-param>

  run as---->tomcat:run。查看数据库是否有自动建表即可。(如果没有检查包扫码的路径是否正确)

  

  

 4、Spring Data Jpa配置说明

  接口需要能够被spring data  jpa 识别,否则无法通过接口生成实现类。

  不需要程序员进行接口实现类的编写,它会自动生成实体类。

  官方标准

    <?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:jpa="http://www.springframework.org/schema/data/jpa"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/data/jpa
        http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
        <jpa:repositories base-package="com.acme.repositories" />
    </beans>

  (1)引入jpa相关的三个名称空间就可以使用

  (2)配置Spring Data Jpa 接口扫码

   

    <!-- Spring data jpa接口扫码 -->
    <jpa:repositories base-package="com.zero.bos.dao"></jpa:repositories>

  (3)dao包以及子包下的接口都可被扫码到。

  

  下面是官方文档Demo。Interface

import org.springframework.data.repository.Repository;

import com.zero.bos.domain.user.User;

//接口定义使用说明
public interface UserDao extends Repository<User, String> {
    
}

 查看Repository的目录接口,如下图

 

  它有增删改查和分页,我们最终是使用JpaRepository

   

   

  这里可以看到接口的各种方法。但是好像看不到update方法,原因是save既可以save又可以update。

  它是根据oid来进行识别的,如果oid是一个托管态的就save,如果oid是一个瞬时态的就update。

  这里要确定接口包是可以被扫码的。

  测试可以编写一个测试类。

  

package com.zero.bos.dao.user.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.zero.bos.domain.user.User;
import com.zero.bos.user.UserDao;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext-domain.xml")
public class UserDaoTest {
    
    //注册接口实现类
    @Autowired
    private UserDao userDao;
    
    @Test // 测试方法 不能有static 方法不能有参数 无返回值 否则无法进行测试    insert  DML语句,需要加事务管理,所以建议不要在dao测而是在业务层测。
    public void testAdd() {
        User u=new User();
        u.setUsername("admin");
        u.setPassword("123");
        userDao.save(u);
    }
}
View Code

  但是编写测试类运行后会报错,因为是设计到增删改查就涉及到事务,所以需要配置事务。

  

  上面这个错误是spring的包扫码路径问题,配置里写的是一个没有存在的包路径

  

    <!-- 开始Spring注解@Controller @Service @Respository @Autowired @Scope -->
    <context:component-scan base-package="com.zero.bos"></context:component-scan>

  官方建议要在业务层进行测试,而不是在dao层。

  所以编写业务层(service)代码。

  (1)业务层模块编写UserService和UserServiceImpl

  UserService

package com.zero.bos.service.user;

import java.util.List;

import com.zero.bos.domain.user.User;

public interface UserService {
    
    public void save(User user);
    
    public void delete(String id);
    
    public void delete(User user);
    
    public User findUserById(String id);
    
    public List<User> findAll();
    
    public void updateUser(User user);
    
}
View Code

  UserServiceImpl

package com.zero.bos.service.user.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.zero.bos.domain.user.User;
import com.zero.bos.service.user.UserService;
import com.zero.bos.user.UserDao;

@Service
@Transactional
public class UserServiceImpl implements UserService{
    
    @Autowired
    private UserDao userDao;
    
    @Override
    public void save(User user) {
        userDao.save(user);
    }

    @Override
    public void delete(String id) {
        // id 是一个瞬时对象
        userDao.delete(id);
    }

    @Override
    public void delete(User user) {
        userDao.delete(user);
    }

    @Override
    public User findUserById(String id) {
        return userDao.findOne(id);
    }

    @Override
    public List<User> findAll() {
        return userDao.findAll();
    }

    @Override
    public void updateUser(User user) {
        //update  要是一个托管对象
        userDao.save(user);
    }

}
View Code

  编写applicationContext-service.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:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/data/jpa
    http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">

    <!-- spring data jpa 事务管理 -->
    <bean id="transactionManager"  class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory"  ref="entityManagerFactory"></property>
    </bean>
    
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
</beans>
View Code

之后就可以进行业务层测试了。

  测试代码

package com.zero.userService.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.zero.bos.domain.user.User;
import com.zero.bos.service.user.UserService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:applicationContext-domain.xml","classpath:applicationContext-service.xml"})
public class UserServiceTest {
    
    @Autowired
    private UserService userService;
    
    @Test
    public void testAdd() {
        User u=new User();
        u.setUsername("admin");
        u.setPassword("123");
        userService.save(u);
    }
}
View Code

  注意:一定要注意jps扫码包的路径和bean的id,能复制千万不要自己写,不要怕麻烦。

  例如:报错信息是:java.lang.IllegalStateException: Failed to load ApplicationContext 

    <!-- Spring data jpa接口扫码 -->
    <jpa:repositories base-package="com.zero.bos.dao"></jpa:repositories>

  类似的包扫码路径不对,扫描不到。

   之后就可以正常的执行save操作了。

   对象的ID和数据库表里的ID一致就叫做OID。

  

    @Test
    public void testUpdate() {
        User user=new User();
        user.setId("40288ce76281379e016281379f0f0000");
        user.setUsername("霸天虎");
        userService.updateUser(user);
    }

但是上面的代码会报错

  not-null。测upadate的时候爆粗。

  原因:这个修改是做的 全字段修改(update操作会把所有的字段都修改,上面的代码会将password置为null,因为没有赋值。但是数据库表的约束是password为非null)。

  所以给password付一个值就可以了。

  如果通过快照的方式 也不行。

  

User user = userService.findUserById("40288ce76281379e016281379f0f0000");
user.setUsername("刘德华");

  因为entityManager默认是没有快照的。

  如果是hibernate的话查询后修改就会同步到数据库中。

 4、 门面类:

     其实门面类就是将多个业务层分装到一个类中,之后通过门面类来统一管理。

    

    @Test
    public void testAdd() {
        User u=new User();
        u.setUsername("王五");
        u.setPassword("123");
        facadeService.getUserService().save(u);
    }

不要忘记@Service的注解。

  通过门面类来调用不同的业务层对象实例。

 5、JPQL查询说明(spring data jpa查询使用说明)

 (1):根据方法名称  自动生成  jpql语句

  

如上图。

  

定义接口

//接口定义使用说明
//参数为查询的目标类型和主键类型,<User>通过User来操作对象。User类的id为String类型,
public interface UserDao extends JpaRepository<User, String> {
    //用户名和密码查询用户  接口定义方法1:JPQL语句(HQL)2:根据接口方法名称      自动生成对应语句   3:命名查询   4:本地sql查询     5;参数占位符查询
    //1、根据接口方法名称   自动生成SQL语句
    public User findByUsernameAndPassword(String username,String password);
}

  userDao业务方法   必须符合命名规范  不用编写JPQL语句

  业务层调用即可。

  UserService

    //登录
    public User login(String name,String password);

  UserServiceImpl

 

    @Override
    public User login(String name, String password) {
        return userDao.findByUsernameAndPassword(name, password);
    }

  UserServiceTest

    @Test
    public void testLogin() {
        System.out.println(userService.login("zhangsan","123"));    
    }

(2)命名查询    将jpql通一放在实体类上

  实体类上面通一管理JPQL语句,JPQL就是一种面向对象关系的语句,类似HQL

   

测试代码中调用login方法会去找实体类的User.login。将参数带入。
//实体类通一管理jpql语句

@NamedQuery(name="User.login",query="from User where username=? and password=?")

命名查询的特点就是 方法名可以自定义

要求使用@NamedQuery 注解  在目标查询实体类上声明  接口UserDao声明方法 名称login

@Entity
@Table(name="t_user",catalog="zero_bos")
//实体类统一管理jpql语句
@NamedQuery(name="User.login",query="from User where username=? and password=?")
public class User  implements java.io.Serializable {

测试类中

    @Test
    public void testLogin() {
        System.out.println(userService.login("zhangsan","123"));    
    }

第三种方式:注解查询。

  第一种和第二种都有自己的缺点:第一种比较复杂;第二种需要把JPQL语句写在实体类上

  第三种是把JQPL写在UserDao接口方法上面。

  例子:

  UserDao

    @Query("from User where username=?1 and password=?2")
    public User login1(String name,String password);

UserServiceImpl

    @Override
    public User login(String name, String password) {
//        return userDao.findByUsernameAndPassword(name, password);
        return userDao.login1(name, password);
    }

测试结果,通过。

  方法和语句都写在接口方法里面。

如果想写SQL语句,也可以。通过本地SQL查询

第四种:SQL查询

   

//第四种方法  SQL数据库语言
    @Query("select * from t_user where username=?1 and password=?2")
    public User login2(String name,String password);

上面的方式是不行的,因为程序是不知道你使用的是SQL而不是JPQL。因此需要告知程序使用的 是SQL还是JPQL

可以看到Query里面有几种方式:nativeQuery  是是否开启MYsql语句的方式

    //第四种方法  SQL数据库语言
    @Query(nativeQuery=true,value="select * from t_user where username=?1 and password=?2")
    public User login2(String name,String password);

代码如上面所示。

这样就可以了。

 第五种方式:占位符查询   通过名称    对应指定参数

    @Query("from User where username=:username and password=:password")
    public User login3(@Param("username")String name,@Param("password")String password);

这种方式对使用SQL方式也适用,如下所示

    //第四种方法  SQL数据库语言
    @Query(nativeQuery=true,value="select * from t_user where username=:username and password=:password")
    public User login2(@Param("username")String name,@Param("password")String password);

6、登录业务的实现

  首先将不同的模块的配置文件添加到web.xml中。

  

    <!-- spring配置文件位置 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml,
                     classpath:applicationContext.xml,
                     classpath:applicationContext-domain.xml</param-value>
    </context-param>

  鼠标放到登录上面会显示一个手的图标,说明这是一个超链接

                            <a href="${pageContext.request.contextPath}/page_common_index.action" id="loginform:j_id19" name="loginform:j_id19">
                        <span
                            id="loginform:loginBtn" class="btn btn-login"
                            style="margin-top:-36px;">登录</span>
                        </a>

  现在将超链接改为一个点击事件

  

                        <a href="javascript:void(0)" id="loginform:j_id19"
                            name="loginform:j_id19" onclick="go()"> <span
                            id="loginform:loginBtn" class="btn btn-login"
                            style="margin-top: -36px;">登录</span>
                        </a>

添加go事件;

  

//     <!-- 声明式事务   提交表单 -->
    function go() {
        $("#loginform").submit();
    }
                <form id="loginform" name="loginform" method="post" class="niceform"
                    action="${pageContext.request.contextPath}/user/userAction_login">

提交表单到   ${pageContext.request.contextPath}/user/userAction_login">

  在Struts.xml中

  

客户端验证码

 编写BaseAction

package com.zero.bos.web.action.base;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.struts2.ServletActionContext;
import org.springframework.beans.factory.annotation.Autowired;


import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.util.ValueStack;
import com.zero.bos.service.facade.FacadeService;

@SuppressWarnings("all")
public class BaseAction<T> extends ActionSupport implements ModelDriven<T> {
    protected T model; // new T();

    public T getModel() {
        // TODO Auto-generated method stub
        return model;
    }

    // 父类中 注入 门面业务层
    @Autowired
    protected FacadeService serviceFacade;

    // 目的 获取子类参数化类型
    // 父类构造方法中 使用 参数化泛型+反射 获取子类具体泛型对应类型 newInstance 创建实例
    public BaseAction() {
        // 对model进行实例化, 通过子类 类声明的泛型
        Type superclass = this.getClass().getGenericSuperclass();
        // 转化为参数化类型
        ParameterizedType parameterizedType = (ParameterizedType) superclass;
        // 获取一个泛型参数
        Class<T> modelClass = (Class<T>) parameterizedType.getActualTypeArguments()[0];
        try {
            model = modelClass.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    // 父类封装通用方法 比如值栈操作 分页操作 session 操作 request操作
    // 1: 值栈操作 获取 值栈
    public ValueStack getValueStack() {
        return ActionContext.getContext().getValueStack();
    }

    // 压入栈顶
    public void push(Object obj) {
        getValueStack().push(obj);
    }

    // 压入栈顶map结构<>
    public void set(String key, Object obj) {
        getValueStack().set(key, obj);
    }

    // 2: session 操作
    public HttpSession getSession() {
        return ServletActionContext.getRequest().getSession();
    }

    public void setSessionAttribute(String key, Object obj) {
        getSession().setAttribute(key, obj);
    }

    public void removeSessionAttribute(String key) {
        getSession().removeAttribute(key);
    }

    public Object getSessionAttribute(String key) {
        return getSession().getAttribute(key);
    }

    // 3: request
    public HttpServletRequest getRequest() {
        return ServletActionContext.getRequest();

    }

    public String getParameter(String key) {
        return getRequest().getParameter(key);
    }

    // 分页操作 接受页面 和 每页显示记录
    protected int pageNum;// 页码
    protected int pageSize;// 每页显示记录数
    //struts2属性注入 将请求数据  自动注入
    public void setPageNum(int pageNum) {
        this.pageNum = pageNum;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

}
View Code

UserAction

  

package com.zero.bos.web.action.user;

import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.zero.bos.domain.user.User;
import com.zero.bos.service.facade.FacadeService;
import com.zero.bos.web.action.base.BaseAction;

@Controller("userAction")
@Scope("prototype")
@Namespace("/user") // 根据页码的/user而来,不能乱写
@ParentPackage("bos") // 要进行扩展struts.xml中的
public class UserAction extends BaseAction<User> {
    //login_error错误了就重新登录,转发到login页面
    @Action(value = "userAction_login", results = {
            @Result(name="login_error",location="/login.jsp"),
            @Result(name="login_ok",type="redirect",location="/index.jsp")
    
            }) // 页码的user/userAction_login
    public String login() {
        // 验证码校验       一次性验证码  用户名和密码校验
        //1、验证码的校验  ,这里User是不包含的 验证码检验的   checkcode,但是我们封装在了BaseAction,这里就可以直接调用了
        String input_checkcode=getParameter("checkcode");
        //    session.setAttribute("key", capstr);  从validatecode.jsp中拿到验证码
        String session_code=(String)getSessionAttribute("key");
        //进行比对,用户输入的和拿到的比对。这里可以跳过表单校验,不走post而走get就跳过了表单校验(1)用户没输
        //不管正确与否都移除验证码,但是session_code变量里面已经有了。
        removeSessionAttribute("key");
        if(StringUtils.isNotBlank(input_checkcode)) {
            //客户提交的验证码不为null
            if(input_checkcode.equalsIgnoreCase(session_code)) {
                //验证码一样,需要门面类去调dao
                User existUser=serviceFacade.getUserService().login(model.getUsername(), model.getPassword());
                if(existUser==null) {
                    //数据库没查到
                    this.addActionError(this.getText("login.usernameOrPassword.error"));
                    return "login_error";
                }else {
                    //将用户信息保存到session中
                    setSessionAttribute("exitUser", existUser);
                    return "login_ok";
                }
            }else {
                //错误信息,2:判断用户名和密码是否一致    一次性验证码,不管用户输入是否正确都要移除验证码。不太可能是空值。因为页面加载就会有session_code。
                this.addActionError(this.getText("login.checkcode.error"));
                return "login_error";
            }
        }else {
            //用户提交的验证码为null,然客户重新登录.国际化信息
            this.addActionError(this.getText("login.nocheckcode.error"));
            return "login_error";
        }
//        return "";
    }
}
View Code

this.addActionError(this.getText("login.nocheckcode.error"));

 国际化信息

login.usernameOrPassword.error=u7528u6237u540Du6216u8005u5BC6u7801u9519u8BEF
login.checkcode.error=u9A8Cu8BC1u7801u9519u8BEF
login.nocheckcode.error=u8BF7u8F93u5165u9A8Cu8BC1u7801

  如果登录成功返回“login_ok”

   

    @Action(value = "userAction_login", results = {
            @Result(name="login_error",location="/login.jsp"),
            @Result(name="login_ok",type="redirect",location="/index.jsp")
    

  直接跳转到index.jsp

  如果登录错误就到login.jsp页面。

  在validatecode.jsp

  session.setAttribute("key", capstr);

   将验证码放入到session中。

  在login.jsp中添加

  在顶部添加

  

<%@taglib prefix="s" uri="/struts-tags" %>

  <font color="red"><s:actionerror/></font>

   这里就会有错误信息

   后端代码就先从login.jsp拿到输入的验证码以及session中的实际的验证码进行对比。

  如果一直再进行输入的账户和密码是否在数据库中存在。

  进行多个判断:验证码是否正确;验证码是否为null,账户密码是否为正确的。

  

坚持就是胜利
原文地址:https://www.cnblogs.com/xiaotieblog/p/8648542.html