一、国际化
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="<%=bundle.getString("jsp.login.submit")%>:" /> </body> </html>
当浏览器的语言环境是用英文的时候 当浏览器的语言环境是中文的时候
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>
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>
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>
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 = invocation.invoke(); return rtValue; } }
并且在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>
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>
开发中就使用这种形式
拦截器类视图