• day12 EL 表达式和国际化开发


    Author:相忠良
    Email: ugoood@163.com
    起始于:May 12, 2018
    最后更新日期:May 16, 2018

    声明:本笔记依据传智播客方立勋老师 Java Web 的授课视频内容记录而成,中间加入了自己的理解。本笔记目的是强化自己学习所用。若有疏漏或不当之处,请在评论区指出。谢谢。
    涉及的图片,文档写完后,一次性更新。

    day12 EL 表达式和国际化开发

    建工程day12。

    1. EL(Expression Language) 表达式简介

    作用:

    • 获取数据
    • 执行运算
    • 获取web开发常用对象
    • 调用java方法

    1.1 执行运算

    看下面例子即可。

    2.jsp 示例代码:

    <%
      request.setAttribute("username","aaa");
      request.setAttribute("password","123");
    %>
    
    ${username=='aaa' && password=='123'}  <%--网页中输出true--%>
    
    <br />-------------empty 运算符----------------<br />
    <%
      request.setAttribute("list", null); // 为 null
      // request.setAttribute("list", new ArrayList()); //为 "空"
    %>
    ${empty(list)} <%--很好用!!--%>
    <%--上面2中情况都能判断,且返回true,empty通常配合<c:if> jstl标签使用,单独使用则毫无意义--%>
    
    <br />-------------el 支持二元运算符----------------<br />
    ${user!=null ? user.name:''} <%--很好用!!--%>
    
    <br />--------------二元运算符(数据回显)--------------<br />
    
    <%
      request.setAttribute("gender", "female");
    %>
    
    <%-- 点点会自动放在“女”上 --%>
    <input type="radio" name="gender" value="male"
      ${gender=='male'?'checked':''}>男
    <input type="radio" name="gender" value="female"
      ${gender=='female'?'checked':''}>女
    
    <%
      request.setAttribute("likes", new String[]{"dance", "sing"});
    %>
    <%-- 此处涉及 el 函数,后面再弄 --%>
    <input type="checkbox" name="likes" value="">唱歌
    <input type="checkbox" name="likes" value="">跳舞
    <input type="checkbox" name="likes" value="">足球
    <input type="checkbox" name="likes" value="">篮球
    

    1.2 获取web开发常用对象(el 中定义了11个隐式对象)

    1
    2

    3.jsp 示例代码:

    <head>
      <title>隐式对象</title>
    </head>
    
    <body>
      ${pageContext}<br /> <%-- pageContext 是 el 的隐式对象 --%>
    
      <br />------------使用 el 表达式访问指定的域------------<br />
      <%
        pageContext.setAttribute("aa", "123");
    
      %>
      ${aa} <br /> <%--从4个域里找 --%>
      ${pageScope.aa} <br /> <%--从指定域里找         拿到pageContext 的 map 集合 --%>
    
      ${sessionScope.user != null} <br /> <%--应该在session中检测用户是否登录,而不是在4个域里检测--%>
    
    </body>
    

    param 隐式对象(经常被使用):

    <br />---------获取保存了所有请求参数的 Map 对象---------<br/>
    ${param.name}
    

    上述代码也在 3.jsp 文件中。当我们在浏览器输入http://localhost:8080/day12/3.jsp?name=aaa来访问3.jsp时,${param.name}将获得参数name的值并返回该值的字符串形式。

    param 隐式对象经常用到数据回显,有下图所示的场景:
    3

    上图中,用户提交的表单在servlet出校验失败后,需跳回到表单页面,${param.username}可直接将用户所填的用户名拿到并显示。即使表单一般是 post 请求,但也有与之对应的 Request Map 用来存储参数。

    paramValues 隐式对象,可获取多个值,如下:

    <br />---------获取参数的多个值---------<br/>
    ${paramValues.name[0]}
    ${paramValues.name[1]}
    

    浏览器输入http://localhost:8080/day12/3.jsp?name=aaa&name=bbb查看结果。

    header 隐式对象获取请求头的 Map 对象:

    <br />---------获取请求头的 Map 对象---------<br/>
    ${header.Host} <br />
    ${header.Cookie} <br />
    ${header['Accept-Language']} <br />
    

    headerValues 隐式对象获取同名头的多个值,与 paramValues 类似。

    cookie 隐式对象
    ${cookie.JSESSIONID}获取的是cookie对象,经查servlet api,发现该对象有针对 name 和 value 的 setter,getter方法。故该对象有 name 属性和 value 属性。

    <br />---------获取cookie---------<br/>
    ${cookie.JSESSIONID.name} <br />
    ${cookie.JSESSIONID.value}
    

    initParam 隐式对象
    该对象保存了该 web 应用的初始化参数的 map 对象。

    如,在 web.xml(<context-param>配置整个web应用的初始化参数) 文件中添加:

    <context-param>
      <param-name>xx</param-name>
      <param-value>yyy</param-value>
    </context-param>
    

    在jsp文件中,我们可用 initParam 隐式对象获取上面配置的初始化参数,如下:

    <br />---------获取整个web应用的初始化参数---------<br/>
    ${initParam.xx} <br />
    

    浏览器中输入http://localhost:8080/day12/3.jsp?name=aaa&name=bbb查看结果。

    1.3 使用 EL 调用 Java 方法

    用 el 调用 java 方法有两个条件:

    1. el 只能调用静态方法;
    2. java类的静态方法需在TLD文件中描述。
      还包含1步,就是需在 jsp 文件中用 taglib 指令导入标签库。

    TLD文件需放置到 WEB-INF 中或该目录下除了 classes 和 lib 目录之外的任意子目录中。
    关于TLD文件的编写,如下图:
    4

    完整例子:
    先弄个普通java类,并编写一个静态方法,如下 ELDemo.java:

    package demo;
    public class ELDemo {
    	public static String show(String str){
    		return str;
    	}
    }
    

    再在 WEB-INF 目录下建个 my.tld 文件(找个别的tld文件,抄头尾),如下:
    修改uri, name, function-class, function-signature即可。

    <?xml version="1.0" encoding="UTF-8"?>
    
    <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
    	version="2.0">
    	<description>A tag library exercising SimpleTag handlers.</description>
    	<tlib-version>1.0</tlib-version>
    	<short-name>SimpleTagLibrary</short-name>
    	<uri>/my</uri>
    
    	<function>
    		<description>el调java类示例</description>
    		<name>show</name>
    		<function-class>demo.ELDemo</function-class>
    		<function-signature>java.lang.String show( java.lang.String )</function-signature>
    	</function>
    </taglib>
    

    建立 4.jsp,并在文件里用 taglib 指令导入标签库,如下:

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%@ taglib uri="/my" prefix="my" %>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <title>el 调 java 静态方法的示例</title>
      </head>
    
      <body>
        ${my:show("Hello!!!") }
      </body>
    </html>
    

    浏览器中输入http://localhost:8080/day12/4.jsp查看结果。

    1.4 sun 公司 el 函数库 - 处理字符串

    这么多函数记是记不住的。只记一点:处理字符串,就找 fn.tld 查。

    sun公司提供的el函数库,在jstl的 META-INF 文件夹内,找 fn.tld 文件,可查询到。

    jsp 页面中,用指令<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>导入sun公司自带 el 函数库。

    el 函数库:

    • fn:toLowerCase
    • fn:toUpperCase
    • fn:trim 删除首位空格
    • fn:length函数返回一个 集合或数组 大小,或返回一个 字符串中的字符个数,返回int类型
    • 还有好多,都在下面例子里

    例子 5.jsp:

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <title>sun 公司 el 函数库 - 处理字符串</title>
      </head>
    
      <body>
        <br />---------- fn:toLowerCase -----------<br />
        ${fn:toLowerCase("AAAA")}
    
        <br />---------- fn:length -----------<br />
    
        <% request.setAttribute("arr", new String[5]); %>
        ${fn:length(arr)}
    
        <%
        	List list = new ArrayList();
        	list.add("aa");
        	list.add("bb");
        	request.setAttribute("list", list);
        %>
    
       	<c:forEach var="i" begin="0" end="${fn:length(list)}">
       		${list[i]}
       	</c:forEach>
    
       	<br />---------- fn:split 字符串分割 -----------<br />
       	${fn:split("www.baidu.com",".")[1] }
    
       	<br />---------- fn:join 字符串连接 -----------<br />
        ${fn:join(fn:split("www,baidu,com",","),".")}
    
        <br />---------- fn:indexOf 搜索字符串出现的位置 -----------<br />
        ${fn:indexOf("www.baidu.com","du")}
    
        <br />---------- fn:contains 是否包含某串 -----------<br />
        ${fn:contains("aaabbbccc","bc")}
    
        <br />---------- 重要的回显例子 -----------<br />
        <%
    		request.setAttribute("likes", new String[]{"dance", "sing"});
    	%>
    	<input type="checkbox" name="likes" value="sing" ${fn:contains(fn:join(likes,","),"sing")?'checked':''}>唱歌
    	<input type="checkbox" name="likes" value="dance" ${fn:contains(fn:join(likes,","),"dance")?'checked':''}>跳舞
    	<input type="checkbox" name="likes" value="basketball" ${fn:contains(fn:join(likes,","),"basketball")?'checked':''}>篮球
    	<input type="checkbox" name="likes" value="football" ${fn:contains(fn:join(likes,","),"football")?'checked':''}>足球
    
    	<br />---------- fn:startsWith 检测以啥开头 -----------<br />
    	<br />---------- fn:replace 替换 -----------<br />
    	<br />---------- fn:substring 截取子串 -----------<br />
    	<br />---------- fn:substringAfter 截 某串第一次出现之后的子串  对应的是fn:substringBefore-----------<br />
    	${fn:substringAfter("www.baidu.com",".")} <%-- 返回 baidu.com --%>
    
    	<br />---------- fn:escapeXml 转义-----------<br />
    	${fn:escapeXml("<a href=''>点点</a>")}
    
      </body>
    </html>
    

    用户登录回显案例,如下:

    6.jsp:

    <%@ page language="java" import="java.util.*, demo.User" pageEncoding="UTF-8"%>
    <%@ taglib uri="/my" prefix="my"%>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <title>用户登录回显</title>
      </head>
    
      <body>
    
      	<%
      		User user = new User();
      		user.setUsername("张三");
      		session.setAttribute("user", user);
      	%>
    
        ${user!=null?my:add("欢迎您:",user.username):''}
    
      </body>
    </html>
    

    javabean 文件,demo.User:

    package demo;
    
    public class User {
    	private String username;
    
    	public String getUsername() {
    		return username;
    	}
    
    	public void setUsername(String username) {
    		this.username = username;
    	}
    }
    

    包含静态方法的类,用于自定义 el 函数的类,demo.MyEL:

    package demo;
    
    public class MyEL {
    	public static String add(String str1, String str2) {
    		return str1 + str2;
    	}
    }
    

    自定义 el 函数 add 的注册文件,WEB-INF/my.tld 文件:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
    	version="2.0">
    	<description>A tag library exercising SimpleTag handlers.</description>
    	<tlib-version>1.0</tlib-version>
    	<short-name>SimpleTagLibrary</short-name>
    	<uri>/my</uri>
    
    	<function>
    		<description>el调java类示例</description>
    		<name>show</name>
    		<function-class>demo.ELDemo</function-class>
    		<function-signature>java.lang.String show( java.lang.String )</function-signature>
    	</function>
    
    	<function>
    		<description>连接2个字符串</description>
    		<name>add</name>
    		<function-class>demo.MyEL</function-class>
    		<function-signature>java.lang.String add( java.lang.String, java.lang.String )</function-signature>
    	</function>
    </taglib>
    

    如此,my:add 这个 el 自定义函数(字符串连接功能)就可在6.jsp中正常使用,并实现用户登录回显功能。

    2. 国际化开发

    就是外国人来访问,看到外语页面,中国人来访问,看到中文页面。学国际化开发,是为做框架做准备的。
    国际化又称 i18n: internationalization。
    5

    6

    7

    8

    实验:

    在day02项目中的src目录中建立cn.wk.resource资源包。并在包下建立三个资源文件,名字如下:

    • MessageResource_en.properties 英文资源;
    • MessageResource_zh.properties 中文资源;
    • MessageResource.properties 默认资源,注意命名。

    三个文件内分别填入(我很懒,写在一个代码片段里了):

    username=username
    password=password
    
    username=u7528u6237u540D
    password=u5BC6u7801
    
    username=username
    password=password
    

    9

    下面代码将对上面的资源文件做操作,如下:

    cn.wk.i18n.Demo1 文件:

    package cn.wk.i18n;
    
    import java.util.Locale;
    import java.util.ResourceBundle;
    
    public class Demo1 {
    
    	public static void main(String[] args) {
    		// 资源包的 base name  "cn.wk.resource.MessageResource"
    		ResourceBundle bundler = ResourceBundle.getBundle(
    				"cn.wk.resource.MessageResource", Locale.CHINESE);
    		String username = bundler.getString("username");
    		String password = bundler.getString("password");
    
    		System.out.println(username);
    		System.out.println(password);
    	}
    }
    

    页面静态资源国际化的例子 login.jsp:
    做本例前,需将资源包中的3个资源文件,添加submit=submitsubmit=提交这样的东西。

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <title>页面静态数据国际化</title>
      </head>
    
      <body>
    
      	<a href="/day12/login.jsp?language=zh">中文</a>
      	<a href="/day12/login.jsp?language=en">English</a>
    
      	<%
      		String language = request.getParameter("language");
      		if(language==null || language.equals("")){
      			language = "zh";
      		}
    
      		Locale locale = new Locale(language);  		
      		ResourceBundle bundle = ResourceBundle.getBundle("cn.wk.resource.MessageResource", locale);
      	%>
    
        <form action="">
        	<%=bundle.getString("username")%>:<input type="text" name="username"><br />
        	<%=bundle.getString("password")%>:<input type="text" name="password"><br />
        	<input type="submit" value=<%=bundle.getString("submit") %>>    	
        </form>
    
      </body>
    </html>
    

    10

    11

    12

    13

    例子1: 使用 DateFormat 格式化输出 日期 时间

    package demo;
    
    import java.text.DateFormat;
    import java.util.Date;
    import java.util.Locale;
    
    public class Demo2 {
    	/**
    	 * 使用 DateFormat 格式化输出 日期 时间
    	 * */
    	public static void main(String[] args) {
    		Date date = new Date();
    		DateFormat df = DateFormat.getDateInstance(DateFormat.FULL,
    				Locale.CHINA);
    		String str = df.format(date); // 2018年5月16日 星期三
    		System.out.println(str);
    
    		df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL,
    				Locale.CHINA);
    		str = df.format(date); // 2018年5月16日 星期三 下午09时33分01秒 CST
    		System.out.println(str);
    
    		// 默认的 DateFormat 格式化输出器
    		df = DateFormat.getInstance();
    		System.out.println(df.format(date)); // 18-5-16 下午9:34
    	}
    }
    

    例子2: 使用 DateFormat 反向把一个字符串格式化成一个日期对象

    package demo;
    
    import java.text.DateFormat;
    import java.text.ParseException;
    import java.util.Date;
    import java.util.Locale;
    
    public class Demo3 {
    	/**
    	 * 使用 DateFormat 反向把一个字符串格式化成一个日期对象
    	 * @throws ParseException
    	 * */
    
    	public static void main(String[] args) throws ParseException {
    
    		String str = "2018年5月16日 星期三 下午09时33分01秒 CST";
    
    		// 根据字符串日期 定 short medium long full 和 Locale
    		DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL,
    				DateFormat.FULL, Locale.CHINA);
    		Date date = df.parse(str);
    		System.out.println(date); // Wed May 16 21:33:01 CST 2018
    	}
    }
    

    14

    15

    例子3:

    package demo;
    
    import java.text.NumberFormat;
    import java.text.ParseException;
    import java.util.Locale;
    
    public class Demo4 {
    
    	// NumberfFormat 数字,货币转换
    	public static void main(String[] args) throws ParseException {
    		// 数字转货币
    		int price = 18;  // $18.00 ¥18.00 18,00 €
    		NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.FRANCE);
    		System.out.println(nf.format(price));
    
    		// 货币转数字
    		String s = "¥18.00";
    		nf = NumberFormat.getCurrencyInstance(Locale.CHINA);
    		double num = nf.parse(s).doubleValue();
    		System.out.println(num);
    
    		// 百分比
    		double d = 0.1;
    		nf = NumberFormat.getPercentInstance();
    		System.out.println(nf.format(d)); // 10%
    	}
    }
    

    3. MessageFormat 字符串批量国际化

    16

    17

    18

    19

    例子, 注意字符串中格式控制的这种东西{0, time, short}

    package demo;
    
    import java.text.MessageFormat;
    import java.util.Date;
    import java.util.Locale;
    
    public class Demo5 {
    	public static void main(String[] args) {
    
    		String pattern = "At {0, time, short} on {0, date}, a hurricance destroyed {1} houses and caused {2, number, currency} of damage.";
    		MessageFormat format = new MessageFormat(pattern, Locale.CHINA);
    		Object params[] = { new Date(), 99, 100000 };
    		String message = format.format(params);
    		System.out.println(message);
    	}
    }
    
  • 相关阅读:
    CSS尺寸单位 % px em rem 详解
    【MySQL】mysql在Windows下使用mysqldump命令备份数据库
    CSS教程:vlink,alink,link和a:link
    正则表达式入门教程
    【MySQL】MySQL支持的数据类型
    iOS应用程序状态图
    Java开发
    Java开发
    iOS开发点滴
    Android开发点滴
  • 原文地址:https://www.cnblogs.com/ZhongliangXiang/p/9048598.html
Copyright © 2020-2023  润新知