首页 > 代码库 > struts2(三)之国际化、拦截器

struts2(三)之国际化、拦截器

一、国际化

  1.1、国际化的定义

  软件的国际化:软件开发时,要使它能同时应对世界不同地区和国家的访问,并针对不同地区和国家的访问,提供相应的、符合来访者阅读习惯的页面或数据。

  1.2、什么需要国际化

  程序:需要国际化

  数据:不需要国际化

  比如:软用户注册的表单,有用户名,密码这5个汉字,在zh_CN语言环境,显示的就是用户名和密码。但是在en_US语言环境,显示的就应该是username和password。这就是程序。

      我们在填写数据的时候,美女和123这样的数据是不需要的

  1.3、固定文本的国际化

      固定文本就是一些消息提示、错误提示、菜单、导航栏等等

    1.3.1、创建一个消息资源包    

    一个资源包由多个文件组成,这些文件名都有命名规范:主要文件名_语言代码_国家代码.properties。 语言代码:由iso规定的。国家代码:有iso规定的
    当文件只有主要文件名.properties时,表明它是默认资源包。浏览器会根据不同的语言环境找对应语言环境的资源包,当没有时,找默认的。
    每个资源包的内容都由相同的key和对应语言环境的value组成。

    比如:message_zh_CN.properties    message_en_US.properties  

    技术分享技术分享

 

    1.3.2、读取资源包的内容

    技术分享技术分享

    1.3.3、在jsp中使用国际化

    login.jsp

技术分享
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%
    Locale locale = request.getLocale();
    ResourceBundle bundle = ResourceBundle.getBundle("com.jxlg.resource.message", locale);
%>
<html>
  <head>
      <%=bundle.getString("jsp.login.title") %></br>
  </head>
  <body>
      <%=bundle.getString("jsp.login.username") %>:<input type="text" name="username" /></br>
      <%=bundle.getString("jsp.login.password") %>:<input type="password" name="password" /></br>
    <input type="submit" value=http://www.mamicode.com/"<%=bundle.getString("jsp.login.submit")%>:" />

</body>
</html>
longin.jsp

  技术分享技术分享

 当浏览器的语言环境是用英文的时候                          当浏览器的语言环境是中文的时候

  技术分享            技术分享

  1.3.4、使用jstl中的fmt标签

  技术分享

二、Struts中的国际化

  2.1、Struts使用国际化的要求   

    首先,我们要知道,在Struts2中,所有的消息提示都是基于国际化的。
    其次,要想在Struts2中使用国际化,动作类必须继承ActionSupport类。

  2.2、Struts使用国际化

    2.2.1、配置资源包

      A.配置全局资源包

      技术分享

      B.配置包范围的资源包

        资源包名称命名规范:package_语言代码_国家代码.properties(固定的)。以此种命名方式的资源包能被该包及其子包中的动作类访问。         

        优先级:高于全局消息资源包 

      C.局部消息资源包(只为动作类使用)    

    资源包名称命名规范:动作类名称_语言代码_国家代码.properties。以此种命名方式的资源包,只为动作类服务。
        优先级最高(就近原则)。

     技术分享

      Struts资源包的搜索顺序

      技术分享

  2.3、读取资源包的内容

    2.3.1、动作类中的读取方式(开发几乎不用)

    技术分享

  2.3.2、在页面中读取资源包内容

    直接访问jsp  

    技术分享

  结果    技术分享

 

   注意:当资源包没有中没有对应的的key值,则把key的内容显示到页面上

    通过动作类访问

    在struts.xml中的配置

    技术分享

    这是在访问demoi18n.jsp时结果是:

    技术分享

  2.4、自由指定读取资源包

    技术分享

三、Struts中的拦截器(非常重要)  

  3.1、拦截器的重要性  

  Struts2中的很多功能都是由拦截器完成的。比如:servletConfig,staticParam,params,modelDriven等等。
  是AOP编程思想的一种应用形式。

  3.2、拦截器的执行时机

  技术分享

  3.3、自定义拦截器

    拦截器的类试图

    技术分享

  3.4、编写拦截器步骤

      1.编写一个类,继承AbstractInterceptor类或者实现Interceptor接口。重写intercept方法。

      技术分享

      2.配置拦截器:注意拦截器必须先声明后使用

      技术分享

      3.测试拦截器的执行顺序

      访问:技术分享

      技术分享

  3.5、多个拦截器的执行顺序

    struts.xml中的配置

    技术分享

    技术分享

    执行结果:

      技术分享

  3.6、intercept返回值

    返回的是逻辑结果视图

四、拦截器的应用

  1.struts.xml中的配置

  技术分享

  2.Demo1Action.java动作类

  技术分享

  3.checkLoginInterceptor.java拦截器

  技术分享

  4.页面

  技术分享

 

  技术分享

 

  技术分享

  5.测试

  因为我们用来测试的,所以我们在动作类中直接就给user赋值了,相当于就是登录了。

  技术分享

  技术分享

技术分享

 

  案例中的问题

    1.问题:由于我们写了自己的拦截器,默认的拦截器就不起作用了。

     解决办法:把默认的拦截器加到配置文件中

技术分享
<package name="p2" extends="struts-default">
        <interceptors>声明拦截器
            <interceptor name="checkLoginInterceptor" class="com.itheima.web.interceptor.CheckLoginInterceptor" />
        </interceptors>
        <global-results>全局结果视图
            <result name="input">/login.jsp</result>数据回显的结果视图
        </global-results>
        用户登录时,不需要检查登录的拦截器工作
        <action name="login" class="com.itheima.web.action.Demo2Action" method="login">
            <result type="redirectAction">showMain</result>
        </action>
        前往主页的动作名称,需要检查登录的拦截器工作
        <action name="showMain" class="com.itheima.web.action.Demo2Action" >
            <interceptor-ref name="checkLoginInterceptor"></interceptor-ref>
            <result>/main.jsp</result>
        </action>
        前往另一个页面的动作名称,需要检查登录的拦截器工作
        <action name="showOther" class="com.itheima.web.action.Demo2Action" >
            <interceptor-ref name="checkLoginInterceptor"></interceptor-ref>
            <result>/otherpage.jsp</result>
        </action>
    </package>
struts.xml

    2.问题:上面1中还是存在问题。当有多个拦截器时,需要改写的内容很多

      解决:抽取公共包,把全局配置放入公共包中

技术分享
<package name="p2" extends="struts-default">
        <interceptors>
            <interceptor name="checkLoginInterceptor" class="com.itheima.web.interceptor.CheckLoginInterceptor" />
            定义一个拦截器栈,把我们自定义的拦截器和默认的拦截器栈放到一起.
            <interceptor-stack name="myDefaultStack">
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="checkLoginInterceptor"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <global-results>
            <result name="input">/login.jsp</result>
        </global-results>
        <action name="login" class="com.itheima.web.action.Demo2Action" method="login">
            <result type="redirectAction">showMain</result>
        </action>
        <action name="showMain" class="com.itheima.web.action.Demo2Action" >
            直接引入我们自己定义的拦截器栈,里面已经包含了默认的拦截器栈
            <interceptor-ref name="myDefaultStack"></interceptor-ref>
            <result>/main.jsp</result>
        </action>
        <action name="showOther" class="com.itheima.web.action.Demo2Action" >
            直接引入我们自己定义的拦截器栈,里面已经包含了默认的拦截器栈
            <interceptor-ref name="myDefaultStack"></interceptor-ref>
            <result>/otherpage.jsp</result>
        </action>
    </package>
struts.xml

    3.问题:还要在每个动作方法中引入拦截器,能不能不用呢

     解决:我们在设置【开发模式】时,覆盖掉了一个default.properties中的常量,能不能把struts-default.xml中的默认拦截器栈的设置给覆盖掉呢?答案是可以的。

    技术分享

技术分享
<package name="p2" extends="struts-default">
        <interceptors>
            <interceptor name="checkLoginInterceptor" class="com.itheima.web.interceptor.CheckLoginInterceptor" />
            <interceptor-stack name="myDefaultStack">
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="checkLoginInterceptor"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        覆盖了struts-default.xml中定义的默认拦截器栈。由myDefaultStack把defaultStack给替换了
        <default-interceptor-ref name="myDefaultStack"></default-interceptor-ref>
        <global-results>
            <result name="input">/login.jsp</result>
        </global-results>
        <action name="login" class="com.itheima.web.action.Demo2Action" method="login">
            <result type="redirectAction">showMain</result>
        </action>
        <action name="showMain" class="com.itheima.web.action.Demo2Action" >
            <result>/main.jsp</result>
        </action>
        <action name="showOther" class="com.itheima.web.action.Demo2Action" >
            <result>/otherpage.jsp</result>
        </action>
    </package>
struts.xml

    4.问题:当使用默认的拦截器栈,这时候三个动作都会被检查登录拦截。

      解决:需要通过AbstractInterceptor类的子类入手,通过查看发现,该类还有一个子类是抽象的:           

        在AbstractInterceptor的子类中,还有一个抽象类MethodFilterInterceptor,它里面提供了两个属性。
        excludeMethods:哪些方法不需要拦截
        includeMethods:哪些方法需要拦截

      技术分享

 

    技术分享

    重新写拦截器类,这次我们继承MethodFilterInterceptor

技术分享
package com.itheima.web.interceptor;

import javax.servlet.http.HttpSession;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
/**
 * 检查登录的拦截器,最终版本
 * @author zhy
 *
 */
public class CheckLoginInterceptor1 extends MethodFilterInterceptor {

    public String doIntercept(ActionInvocation invocation) throws Exception {
        //1.获取HttpSession
        HttpSession session = ServletActionContext.getRequest().getSession();
        //2.获取session域中的登录标记
        Object obj = session.getAttribute("user");
        //3.判断是否有登录标记
        if(obj == null){
            //用户没有登录
            return "input";
        }
        //4.用户登录了,放行
        String rtValue =http://www.mamicode.com/ invocation.invoke();
        return rtValue;
    }

}
CheckLoginInterceptor1

 

    并且在struts的配置文件中,配置需要拦截哪些方法,和需要放过哪些方法。

技术分享
<package name="p2" extends="struts-default">
        <interceptors>
            <interceptor name="checkLoginInterceptor1" class="com.itheima.web.interceptor.CheckLoginInterceptor1" />
            <interceptor-stack name="myDefaultStack">
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="checkLoginInterceptor1">
                    给自定义拦截器注入参数,告知他哪些方法不需要拦截
                    <param name="excludeMethods">login</param>
                </interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <default-interceptor-ref name="myDefaultStack"></default-interceptor-ref>
        <global-results>
            <result name="input">/login.jsp</result>
        </global-results>
        <action name="login" class="com.itheima.web.action.Demo2Action" method="login">
            <result type="redirectAction">showMain</result>
        </action>
        <action name="showMain" class="com.itheima.web.action.Demo2Action" >
            <result>/main.jsp</result>
        </action>
        <action name="showOther" class="com.itheima.web.action.Demo2Action" >
            <result>/otherpage.jsp</result>
        </action>
    </package>
struts.xml

    5.问题:我们在声明时配置了哪些方法需要拦截,哪些方法不需要拦截。但是在没有写动作类和动作方法之前,不确定方法名叫什么。

      解决:我们需要在使用拦截器的时候给它注入参数。告诉拦截器哪些需要拦截,哪些不需要

技术分享
package name="p2" extends="struts-default">
        <interceptors>
            <interceptor name="checkLoginInterceptor1" class="com.jxlg.web.interceptor.CheckLoginInterceptor1" />
            <interceptor-stack name="myDefaultStack">
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="checkLoginInterceptor1"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <default-interceptor-ref name="myDefaultStack"></default-interceptor-ref>
        <global-results>
            <result name="input">/login.jsp</result>
        </global-results>
        
        <action name="login" class="com.jxlg.web.action.Demo2Action" method="login">
            <interceptor-ref name="myDefaultStack">
                <!-- 在引用自定义拦截器栈的时候,给指定的拦截器注入参数。方式就是:拦截器名称.属性名称 -->
                <param name="checkLoginInterceptor1.excludeMethods">login</param>
            </interceptor-ref>
            <result type="redirectAction">showMain</result>
        </action>
        <action name="showMain" class="com.jxlg.web.action.Demo2Action" >
            <result>/main.jsp</result>
        </action>        
        <action name="showOther" class="com.jxlg.web.action.Demo2Action" >
            <result>/otherpage.jsp</result>
        </action>
    </package>
struts.xml

  开发中就使用这种形式

技术分享

 

  拦截器类视图

  技术分享

 

 

    

 

    

  

 

 

    

 

  

 

  

 

 

 

技术分享

struts2(三)之国际化、拦截器