• 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,账户密码是否为正确的。

      

    坚持就是胜利
  • 相关阅读:
    [一起面试AI]NO.9 如何判断函数凸或非凸
    [一起面试AI]NO.8 在机器学习中,常用的损失函数有哪些?
    [一起面试AI]NO.5过拟合、欠拟合与正则化是什么?
    [一起面试AI]NO.4特征工程主要包括什么?
    [一起面试AI]NO.3分类问题常用的性能度量指标有哪些
    MySQL中自增ID修改起始值
    折半查找算法(Python版)
    彻底解决安卓7.0及以上版本抓包https失败
    Charles抓包2-Charles抓取https请求
    Charles抓包1-Charles安装汉化(附正版注册码)
  • 原文地址:https://www.cnblogs.com/xiaotieblog/p/8648542.html
Copyright © 2020-2023  润新知