• 调查管理系统 -(5)Struts2配置&用户注册/登录/校验


    1、设计BaseAction

    由于几乎每个Action都要继承ActionSupport类并且实现ModelDriven接口,因此最好设计一个BaseAction类,让其继承ActionSupport并实现ModelDriven接口,便于其它Action的复用。当然,设计BaseAction的作用不仅在于此,其还将会有很多的用处,拭目以待吧。

    具体实现如下: 

     1 package com.atguigu.surveypark.struts2.action;
     2 import com.opensymphony.xwork2.ActionSupport;
     3 import com.opensymphony.xwork2.ModelDriven;
     4 import com.opensymphony.xwork2.Preparable;
     5 /**
     6  * 抽象action,专门用于继承
     7  */
     8 public abstract class BaseAction<T> extends ActionSupport implements ModelDriven<T>, Preparable {
     9     public void prepare() throws Exception {}
    10     public abstract T getModel() ;
    11 }

    在这里BaseAction除了实现了ModelDriven接口以外,还实现了Preparable接口。因为实现了Preparable接口后,在拦截器栈中的prepare拦截器(即预处理拦截器)会起作用,这样就可以在Action中实现其prepare()方法自定义以prepare或prepareDo开头加上Action中方法名的方法,在Action相应的方法调用前为我们执行一些预处理工作。

    2、定义注册Action即RegAction:

    在RegAction中主要定义了两个方法toRegPage()和doReg()(即到达注册页面和进行用户注册),具体实现如下:

     1 package com.atguigu.surveypark.struts2.action;
     2 import javax.annotation.Resource;
     3 import org.apache.struts2.interceptor.validation.SkipValidation;
     4 import org.springframework.context.annotation.Scope;
     5 import org.springframework.stereotype.Controller;
     6 import com.atguigu.surveypark.model.User;
     7 import com.atguigu.surveypark.service.UserService;
     8 import com.atguigu.surveypark.util.DataUtil;
     9 import com.atguigu.surveypark.util.ValidateUtil;
    10 /**
    11  * 注册action
    12  */
    13 @Controller
    14 @Scope("prototype")
    15 public class RegAction extends BaseAction<User> {
    16     private User model = new User();
    17     private String confirmPassword ; //确认密码字段
    18     //注入userService
    19     @Resource
    20     private UserService userService ;
    21     public String getConfirmPassword() {
    22         return confirmPassword;
    23     }
    24     public void setConfirmPassword(String confirmPassword) {
    25         this.confirmPassword = confirmPassword;
    26     }
    27     public User getModel() {
    28         return model;
    29     }
    30     //到达注册页面
    31     @SkipValidation
    32     public String toRegPage(){
    33         return "regPage" ;
    34     }
    35     //进行用户注册
    36     public String doReg(){
    37         //密码加密
    38         model.setPassword(DataUtil.md5(model.getPassword()));
    39         userService.saveEntity(model);
    40         return SUCCESS ;
    41     }
    42     //校验
    43     public void validate() {
    44         //1.非空
    45         if(!ValidateUtil.isValid(model.getEmail())){
    46             addFieldError("email", "email是必填项!");
    47         }
    48         if(!ValidateUtil.isValid(model.getPassword())){
    49             addFieldError("password", "password是必填项!");
    50         }
    51         if(!ValidateUtil.isValid(model.getNickName())){
    52             addFieldError("nickName", "nickName是必填项!");
    53         }
    54         if(hasErrors()){
    55             return ;
    56         }
    57         //2.密码一致性
    58         if(!model.getPassword().equals(confirmPassword)){
    59             addFieldError("password", "密码不一致!");
    60             return  ;
    61         }
    62         //3.email占用
    63         if(userService.isRegisted(model.getEmail())){
    64             addFieldError("email", "email已占用!");
    65         }
    66     }
    67 }
    View Code

    在RegAction中我们实现了BaseAction中的getModel()方法,这样ModelDriven拦截器能够将返回的模型model对象(这里即为user对象)压入到ValueStack的栈顶。

    此外,在RegAction中还覆写了validate()方法对用户注册进行校验。由于validate()方法只需要在请求doReg()方法调用时进行校验,因此为toRegPage()方法添加了@SkipValidation注解,这样在调用toRegPage()方法时,Struts2的validate拦截器就不会执行validate()方法去对请求进行校验。

    还注意到,在对用户输入的Email、密码等字段是否为空进行校验时,封装了一个工具类方法ValidateUtil.isValid()。由于对字符串是否为空、集合是否为空等校验工作经常会用到,因此我们可以将常用的方法抽取出来放到工具类中,以实现代码的重用。(当然我们也可以借助于其它类似于Apache提供的commons-lang.jar等工具包来完成这些基本工作。)

     3、定义登录Action即LoginAction:

    在LoginAction中主要定义了两个方法toLoginPage()和doLogin()(即到达登录页面和进行登录),具体实现如下:

     1 package com.atguigu.surveypark.struts2.action;
     2 import java.util.Map;
     3 import javax.annotation.Resource;
     4 import org.apache.struts2.interceptor.SessionAware;
     5 import org.springframework.context.annotation.Scope;
     6 import org.springframework.stereotype.Controller;
     7 import com.atguigu.surveypark.model.User;
     8 import com.atguigu.surveypark.service.UserService;
     9 import com.atguigu.surveypark.util.DataUtil;
    10 /**
    11  * 登陆action
    12  */
    13 @Controller
    14 @Scope("prototype")
    15 public class LoginAction extends BaseAction<User> implements SessionAware {
    16     @Resource
    17     private UserService userService ;
    18     //接受session的map
    19     private Map<String,Object> sessionMap ;
    20     //到达登陆页面
    21     public String toLoginPage(){
    22         return "loginPage" ;
    23     }
    24     //进行登陆处理
    25     public String doLogin(){
    26         return "success";
    27     }
    28     //校验登陆信息
    29     public void validateDoLogin(){
    30         User user = userService.validateLoginInfo(model.getEmail(),DataUtil.md5(model.getPassword()));
    31         if(user == null){
    32             addActionError("email/password错误");
    33         }
    34         else{
    35             sessionMap.put("user", user);
    36         }
    37     }
    38     //注入session的map
    39     public void setSession(Map<String, Object> arg0) {
    40         this.sessionMap = arg0 ;
    41     }
    42 }
    View Code

    在LoginAction中我们实现了SessionAware接口,并在Action中声明了一个sessionMap变量,这样在请求Action方法时servletConfig拦截器就会为Action注入session的Map对象。(我认为这里也可以使用ActionContext来获取session,因为无论哪种方法都会是我们的代码与Struts2框架有一定的耦合。另外,佟刚老师曾讲过对于使用ActionContext或实现XxxAware接口的建议是:若一个 Action 类中有多个 action 方法, 且多个方法都需要使用域对象的 Map 或 parameters, 则建议使用Aware接口的方式。这里也只有doLogin()方法用到了sessionMap。)

    此外,在LoginAction中也需要对用户登录进行校验(只需对doLogin()方法的调用进行校验),在这里定义的是一个validateDoLogin()方法,而并没有在toLoginPage()方法上添加@SkipValidation注解。这时因为,Struts2的验证框架为我们提供了另外一种过滤需要校验的方法的手段,即我们只需要为需要校验的方法编写一个以validate或validateDo开头并加上需要校验的方法的方法名的方法即可(如这里需要对doLogin()方法进行校验,我们只需定义一个validateDoLogin()方法或validateDoDoLogin()方法,这样Struts2就只是在请求doLogin()方法时进行校验,而不会对其它方法的调用进行校验。)。

    还有重要的一点是,在LoginAction方法中并没有实现BaseAction的getModel()方法。这时由于在每个Action中都需要获取model对象,因此,我们利用反射技术对BaseAction进行改造,将model对象的实例化工作放到BaseAction的构造方法中来完成,这样在实例化具体的Action时,其构造方法在调用父类BaseAction的构造方法时会完成model的实例化工作,这样同样提供了代码的重用性。改造后的BaseAction的实现如下:

     1 package com.atguigu.surveypark.struts2.action;
     2 import java.lang.reflect.ParameterizedType;
     3 import com.opensymphony.xwork2.ActionSupport;
     4 import com.opensymphony.xwork2.ModelDriven;
     5 import com.opensymphony.xwork2.Preparable;
     6 /**
     7  * 抽象action,专门用于继承
     8  */
     9 public abstract class BaseAction<T> extends ActionSupport implements ModelDriven<T>, Preparable {
    10     public T model ;
    11     public BaseAction(){
    12         try {
    13             ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
    14             Class clazz = (Class) type.getActualTypeArguments()[0];
    15             model = (T) clazz.newInstance();
    16         } catch (Exception e) {
    17             e.printStackTrace();
    18         }
    19     }
    20     public void prepare() throws Exception {    }
    21     public T getModel(){
    22         return model ;
    23     }
    24 }
    View Code

    这里的工作类似于BaseDaoImpl与BaseServiceImpl,主要都是获取到泛型的具体类型,然后对其进行实例化操作。

    同时,BaseAction、BaseDaoImpl、BaseServiceImpl我们都定义为了一个抽象类,关于将基类定义为抽象类的好处参:不是抽象类的基类不是好基类

    4、推荐做法及知识点:

    1)推荐做法:不要直接与JSP页面进行交互,而要让每个请求都经过Action,这样便于权限或安全问题的控制。

    2) Spring的自动检测注解@Controller、@Service、@Repository本质上并没有什么区别,只是从语义(字面)上来区分了每个对象属于哪一层。

    3)SSH整合后,Action类是由Spring负责创建的,但是其生命周期并不由Spring管理。因为Spring容器只管理单例的bean,而不管理原型的bean(Action是原型的bean)。

    4)SSH整合后,Action类是由Spring负责创建的,我们在Action类上添加@Controller注解后,其默认的实例化对象的名称为ActionName的首字母小写后,因此在配置文件struts.xml中action元素的class属性的值应该写为ActionName的首字母小写后的值,而不再是全类名。

    <action name="LoginAction_*" class="loginAction" method="{1}"> <!--这里配置class为LoginAction对象的名称-->
        <result name="loginPage">/index.jsp</result>
        <result name="input">/index.jsp</result>
        <result name="success">/index.jsp</result>
    </action>

    5、总结:

    1)Struts2框架提供给了两种过滤校验的方法

    Ⅰ、在不要进行校验的方法上添加@SkipValidation注解;

    Ⅱ、为需要校验的方法编写特定的的方法,该方法必须以validate或validateDo开头,后面加上需要校验的方法的名称(首字母要大写)。

    2)文中红色字体部分。

  • 相关阅读:
    hdu 4825 Xor Sum (01 Trie)
    hdu 5877 Weak Pair (Treap)
    bzoj 1861: [Zjoi2006]Book 书架 (splay)
    bzoj 1503: [NOI2004]郁闷的出纳员 (splay)
    hihocoder#1333 : 平衡树·Splay2 (区间操作)
    「BZOJ1251」序列终结者 (splay 区间操作)
    二进制运算符的相关运算
    Bzoj 1085: [SCOI2005]骑士精神 (dfs)
    Bzoj 1083: [SCOI2005]繁忙的都市 (最小生成树)
    Bzoj 1088: [SCOI2005]扫雷Mine (DP)
  • 原文地址:https://www.cnblogs.com/KnightKitt/p/3957085.html
Copyright © 2020-2023  润新知