• Struts2基础-4-2 -struts拦截器实现权限控制案例+ 模型驱动处理请求参数 + Action方法动态调用


    1.新建项目,添加jar包到WEB-INF目录下的lib文件夹,并添加到builde path里面

    整体目录结构如下

    2.新建web.xml,添加struts2核心过滤器,和默认首页

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
     5     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
     6     <welcome-file-list>
     7         <welcome-file>main.jsp</welcome-file>
     8     </welcome-file-list>
     9 
    10     <filter>
    11         <filter-name>StrutsPrepareAndExecuteFilter</filter-name>
    12         <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    13     </filter>
    14 
    15     <filter-mapping>
    16         <filter-name>StrutsPrepareAndExecuteFilter</filter-name>
    17         <url-pattern>/*</url-pattern>
    18     </filter-mapping>
    19 
    20 </web-app>

     3. 新建一个User Javabean ,编写loginAction

    在   cn.test.domain  包下建User类

     1 package cn.test.domain;
     2 
     3 public class User {
     4     private String username;
     5     private String password;
     6 
     7     public String getUsername() {
     8         return username;
     9     }
    10 
    11     public void setUsername(String username) {
    12         this.username = username;
    13     }
    14 
    15     public String getPassword() {
    16         return password;
    17     }
    18 
    19     public void setPassword(String password) {
    20         this.password = password;
    21     }
    22 
    23     @Override
    24     public String toString() {
    25         return "User [password=" + password + ", username=" + username + "]";
    26     }
    27 
    28 }

    在  cn.test.action  包下 建 LoginActoin,模拟用户登陆,判断登陆用户是否为指定用户,不是,就返回逻辑视图名" input ",跳转到login.jsp 去让用户登陆

     1 package cn.test.action;
     2 
     3 import cn.test.domain.User;
     4 
     5 import com.opensymphony.xwork2.ActionContext;
     6 import com.opensymphony.xwork2.ActionSupport;
     7 import com.opensymphony.xwork2.ModelDriven;
     8 
     9 public class LoginActoin extends ActionSupport implements ModelDriven<User>{
    10 
    11     private static final long serialVersionUID = 1L;
    12     private User user = new User();  //必须要有该Javabean的实例
    13     @Override
    14     public User getModel() {
    15         return user;
    16     }
    17     @Override
    18     public String execute() throws Exception {
    19         // 获取ActionContext
    20         ActionContext context = ActionContext.getContext();
    21         if("admin".equals(user.getUsername())&& "123".equals(user.getPassword())){
    22             //把用户存储在session中
    23             context.getSession().put("user", user);
    24             return SUCCESS;
    25         }else {
    26             context.put("msg", "用户名密码不正确");
    27             return INPUT;
    28         }
    29         
    30     }
    31     
    32 
    33 }

    注:这里使用了struts2的模型驱动来获取请求参数值

      在 Struts2中, Action处理请求参数还有另外一种方式,叫做模型驱动( Modeldriven)。过实现 Modeldriven接口来接收请求参数, Action类必须实现 Modeldriven接口,引入JavaBea的实例 ,并且重写 get Model()方法,这个方法返回的就是 Action所使用的数据模型对象。

      模型驱动方式通过 Javabean模型进行数据传递。只要是普通的 Javabean,就可以充当模型部分。采用这种方式, Javabean所封装的属性与表单的属性一一对应, Javabean将成为数据传递的载体。使用模型驱动方式, Action类通过get*()的方法来获取模型,其中  *  代表具体的模型对象,代码如上LoginActoin 中背景颜色部分所示。

      使用模型驱动时,其登录页面 userlogin.jsp也要做相应调整。使用ModelDriver的方式,一个Action只能对应一个Model,因此不需要添加 user前缀,页面上的username对应到这个Model的username属性。属性驱动的方法和模刑驱动的方法各有优缺点,实际开发中,应根据不同情况来选择使用。

    4.在 cn.test.action 包下创建  BookAction ,写增删改查四个方法

     1 package cn.test.action;
     2 
     3 import com.opensymphony.xwork2.ActionSupport;
     4 
     5 public class BookAction extends ActionSupport {
     6 
     7     private static final long serialVersionUID = 1L;
     8     public String add(){
     9         System.out.println("book add");
    10         return SUCCESS;
    11     }
    12     public String del(){
    13         System.out.println("book del");
    14         return SUCCESS;
    15     }
    16     public String update(){
    17         System.out.println("book update");
    18         return SUCCESS;
    19     }
    20     public String find(){
    21         System.out.println("book find");
    22         return SUCCESS;
    23     }
    24 
    25 }

    5.在 cn.test.interceptor 包下创建自定义拦截器类PrivilegeInterceptor ,根据session中有无指定用户,进行权限控制

     1 package cn.test.interceptor;
     2 
     3 import com.opensymphony.xwork2.Action;
     4 import com.opensymphony.xwork2.ActionContext;
     5 import com.opensymphony.xwork2.ActionInvocation;
     6 import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
     7 
     8 /**
     9  * 自定义拦截器类,获取session中有无登陆用户,完成页面跳转的权限控制
    10  * 
    11  * @author Administrator
    12  * 
    13  */
    14 public class PrivilegeInterceptor extends AbstractInterceptor {
    15 
    16     private static final long serialVersionUID = 1L;
    17 
    18     @Override
    19     public String intercept(ActionInvocation invocation) throws Exception {
    20         // 获取actionContext
    21         ActionContext actionContext = invocation.getInvocationContext();
    22         // 获取session中的用户
    23         Object user = actionContext.getSession().get("user");
    24         if (null != user) {
    25             return invocation.invoke(); // 继续向下执行
    26         } else {
    27             actionContext.put("msg", "对不起,您还未登陆!");
    28             return Action.LOGIN; // 返回逻辑视图名"login",由对应的result配置,跳转到登陆页面
    29         }
    30     }
    31 
    32 }

    6.在webcontent目录下创建4个视图页面:主页main.jsp  ,登陆页login.jsp ,操作成功页success.jsp , 404错误页error.jsp

    (1)main.jsp  定义增删改查4个链接,请求路径中action的命名按照  book_* 的方式命名,方便struts里面配置Action的动态调用

     1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
     2 <%
     3 String path = request.getContextPath();
     4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
     5 %>
     6 
     7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
     8 <html>
     9   <head>
    10     <base href="<%=basePath%>">
    11     <title>main.jsp</title>
    12   </head>
    13   
    14   <body>
    15    <a href="<%=basePath%>book_add">bookAdd</a> <br>
    16    <a href="<%=basePath%>book_del">bookDel</a> <br>
    17    <a href="<%=basePath%>book_update">bookUpdate</a> <br>
    18    <a href="<%=basePath%>book_find">bookFind</a> <br>
    19   </body>
    20 </html>

    (2),登陆页login.jsp 

     1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
     2 <%
     3     String path = request.getContextPath();
     4     String basePath = request.getScheme() + "://"
     5             + request.getServerName() + ":" + request.getServerPort()
     6             + path + "/";
     7 %>
     8 
     9 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    10 <html>
    11     <head>
    12         <base href="<%=basePath%>">
    13         <title>登陆</title>
    14     </head>
    15     <body>
    16         ${requestScope.msg }
    17         <br>
    18         <form action="<%=basePath%>login.action" method="post">
    19             <table>
    20                 <tr>
    21                     <td><label style="text-align:right;">用户名:</label></td>
    22                     <td><input type="text" name="username"/></td>
    23                 </tr>
    24                 <tr>
    25                     <td><label style="text-align:right;">密码:</label></td>
    26                     <td><input type="password" name="password"/></td>
    27                 </tr>
    28                 <tr >
    29                     <td colspan="2" align="right"><input type="submit" value="登陆"/></td>
    30                 </tr>
    31             </table>
    32         </form>
    33     </body>
    34 </html>

    (3)操作成功页success.jsp 

     1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
     2 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
     3 <html>
     4   <head>
     5     <title>success.jsp</title>
     6    </head>
     7   
     8   <body>
     9   用户${user.username }操作成功!
    10    </body>
    11 </html>

    (4)   404错误页error.jsp

     1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
     2 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
     3 <html>
     4   <head>
     5     <title>error page</title>
     6    </head>
     7   
     8   <body>
     9                您访问的页面不存在<br>
    10   </body>
    11 </html>

    7.配置struts。xml,声明自定义拦截器,拦截器栈以及对book操作的action,和处理404错误的action

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <!DOCTYPE struts PUBLIC
     3     "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
     4     "http://struts.apache.org/dtds/struts-2.3.dtd">
     5 <struts>
     6     
     7     <package name="intercepter" namespace="/" extends="struts-default">
     8         <!-- 声明拦截器 -->
     9         <interceptors>
    10             <interceptor name="privilege" class="cn.test.interceptor.PrivilegeInterceptor"></interceptor> <!--自定义拦截器-->
    11             <!-- 自定义拦截器栈,放入自定义的拦截器和struts的默认拦截器 -->
    12             <interceptor-stack name="myStack">
    13                 <interceptor-ref name="privilege"></interceptor-ref>
    14                 <interceptor-ref name="defaultStack"></interceptor-ref>
    15             </interceptor-stack>
    16         </interceptors>
    17         
    18         <!-- 默认的 Action配置要放在拦截器配置的后面 -->
    19         <default-action-ref name="defaultAction"></default-action-ref>
    20         
    21         <!-- 用户登陆操作   action里面不写方法名,默认之心execute()方法!!!-->
    22         <action name="login" class="cn.test.action.LoginActoin" >
    23             <result>/main.jsp</result>
    24             <result name="input">/login.jsp</result>
    25         </action>
    26         <!-- book操作action -->
    27         <action name="book_*" class="cn.test.action.BookAction" method="{1}">
    28             <result name="success">/success.jsp</result>
    29             <result name="login">/login.jsp</result>
    30             <!-- 在action中使用自定义拦截器,对book操作的actoin进行权限控制 
    31             放在哪个action,就对那个action进行权限控制的拦截-->
    32             <interceptor-ref name="myStack"></interceptor-ref>
    33         </action>
    34         
    35         <!-- 注意,package元素里面的子元素是有顺序要求的,如果写错位置,启动时会报错,一般把action写在最后面 -->
    36         <action name="defaultAction">
    37             <result>/error.jsp</result>
    38         </action>
    39     </package>
    40 
    41 </struts>

    book操作action类中只返回了一个success作为result 的name属性值, 下面action中配置的    <result name="login">/login.jsp</result> ,这个result是拦截器用的,当拦截器检测到用户没有登陆时,就返回“login”这个逻辑视图名;

    关于动态调用,action 的method={1},表示 method属性值取 action的name属性的值里边的第一个*的值。如果请求里是book_add 那么method 就是add,则执行Action中的add方法。

    <!-- book操作action -->
            <action name="book_*" class="cn.test.action.BookAction" method="{1}">
                <result name="success">/success.jsp</result>
                <result name="login">/login.jsp</result>
                <interceptor-ref name="myStack"></interceptor-ref>   <!--调用拦截器栈 -->
            </action>

    8. 部署并测试

    (1)访问http://localhost:8080/strutsstu4-2/  自动跳转到main.jsp 

    (2)随便点击一个链接,比如update ,提示还未登陆,红框里面的提示消息是 PrivilegeInterceptor 拦截器类中返回的 ,说明拦截器工作了。

    (3)输入错误用户名密码测试,提示用户名密码不正确,同时,页面跳转到了登陆页,可以看到浏览器中的地址成了login.action,

      

    (4)输入admin 123登陆     

       

     可以在main.jsp中加入 当前登陆用户:${username } <br/> ,效果会看的更明显

    点击bookFind,可以看到浏览器地址发生变化,请求book_find这个action 

    (5) 请求一个不存在的actoin: 

    遇到的问题:添加默认的 Action配置时,给放在了拦截器配置的前面,导致启动时报错,提示信息如下:

    Caused by: 元素类型为 "package" 的内容必须匹配 "(result-types?,interceptors?,default-interceptor-ref?,default-action-ref?,default-class-ref?,global-results?,global-exception-mappings?,action*)"。 - file:/D:/Tomcat/apache-tomcat-6.0.30/webapps/strutsstu4-2/WEB-INF/classes/struts.xml:42:12

     其实括号里面的红字部分就已经提示了package中各个元素要遵从的顺序,可以看到,default-action-ref是在default-interceptor-ref?的后面,也就是说默认Action应该配置在拦截器后面

    示例代码下载地址  https://github.com/liuch0228/Struts2SSH.git

  • 相关阅读:
    关于Entity Framework中的Attached报错的完美解决方案
    关于C# Winform DataGridView 设置DefaultCellStyle无效的原因与解决方案
    实现winform DataGridView控件判断滚动条是否滚动到当前已加载的数据行底部
    关于Entity Framework自动关联查询与自动关联更新导航属性对应的实体注意事项说明
    阅读《LEARNING HARD C#学习笔记》知识点总结与摘要系列文章索引
    阅读《LEARNING HARD C#学习笔记》知识点总结与摘要五
    C# Winform 通过FlowLayoutPanel及自定义的编辑控件,实现快速构建C/S版的编辑表单页面
    NPOI导入导出EXCEL通用类,供参考,可直接使用在WinForm项目中
    阅读《LEARNING HARD C#学习笔记》知识点总结与摘要四
    C#实现通用数据过滤窗体
  • 原文地址:https://www.cnblogs.com/enjoyjava/p/8997959.html
Copyright © 2020-2023  润新知