zoukankan      html  css  js  c++  java
  • servlet中的过滤器 国际化

    1. 过滤器

    基本概念

    过滤器是需要在xml中配置的。

    为什么需用到过滤器?

    项目开发中,经常会涉及到重复代码的实现!

    注册 ----à Servlet 1. 设置编码】 ----à  JSP

    修改 ----àServlet 1. 设置编码】 ---à  JSP

    其他,

    如判断用户是否登陆,只有登陆才能有操作权限!

    涉及到重复判断: 获取session,取出session数据,判断是否为空,为空说明没有登陆,不能操作; 只有登陆后,才能操作!

    如何解决:

    1. 抽取重复代码,封装
    2. 每个用到重复代码的地方,手动的调用!

    过滤器,设计执行流程:

    1. 用户访问服务器
    2. 过滤器: Servlet请求进行拦截
    3. 先进入过滤器, 过滤器处理
    4. 过滤器处理完后, 在放行, 此时,请求到达Servlet/JSP
    5. Servlet处理
    6. Servlet处理完后,再回到过滤器, 最后在由tomcat服务器相应用户;

    (过滤器就像回家的门!)

    过滤器,HelloWorld案例

    Javax.servlet.*;

    |-- interface  Filter  及过滤器

    开发步骤:

    1. 写一个普通java类,实现Filter接口
    2. 配置过滤器

    过滤器相关Api

    |-- interface  Filter 过滤器核心接口

    Void  init(filterConfig);    初始化方法,在服务器启动时候执行

    Void  doFilter(request,response,filterChain);   过滤器拦截的业务处理方法

    Void destroy();    销毁过滤器实例时候调用

    |-- interface  FilterConfig   获取初始化参数信息

    String

    getInitParameter(java.lang.String name) 

    Enumeration

    getInitParameterNames()

    |-- interface  FilterChain     过滤器链参数;一个个过滤器形成一个执行链;

    void doFilter(ServletRequest request, ServletResponse response)  ;  执行下一个过滤器或放行

    /**

     * 过滤器,测试

     * @author Jie.Yuan

     *

     */

    public class HelloFilter implements Filter{

    // 创建实例

    public HelloFilter(){

    System.out.println("1. 创建过滤器实例");

    }

    @Override

    public void init(FilterConfig filterConfig) throws ServletException {

    System.out.println("2. 执行过滤器初始化方法");

    // 获取过滤器在web.xml中配置的初始化参数

    String encoding = filterConfig.getInitParameter("encoding");

    System.out.println(encoding);

    // 获取过滤器在web.xml中配置的初始化参数 的名称

    Enumeration<String> enums =  filterConfig.getInitParameterNames();

    while (enums.hasMoreElements()){

    // 获取所有参数名称:encodingpath

    String name = enums.nextElement();

    // 获取名称对应的值

    String value = filterConfig.getInitParameter(name);

    System.out.println(name + " " + value);

    }

    }

    // 过滤器业务处理方法: 在请求到达servlet之前先进入此方法处理公用的业务逻辑操作

    @Override

    public void doFilter(ServletRequest request, ServletResponse response,

    FilterChain chain) throws IOException, ServletException {

    System.out.println("3. 执行过滤器业务处理方法");

    // 放行 (去到Servlet)

    // 如果有下一个过滤器,进入下一个过滤器,否则就执行访问servlet

    chain.doFilter(request, response);

    System.out.println("5. Servlet处理完成,又回到过滤器");

    }

    @Override

    public void destroy() {

    System.out.println("6. 销毁过滤器实例");

    }

    }

    <!-- 过滤器配置 -->

    <filter>

    <!-- 配置初始化参数 -->

    <init-param>

    <param-name>encoding</param-name>

    <param-value>UTF-8</param-value>

    </init-param>

    <init-param>

    <param-name>path</param-name>

    <param-value>c:/...</param-value>

    </init-param>

    <!-- 内部名称 -->

    <filter-name>hello_filter</filter-name>

    <!-- 过滤器类的全名 -->

    <filter-class>cn.itcast.a_filter_hello.HelloFilter</filter-class>

    </filter>

    <filter-mapping>

    <!-- filter内部名称 -->

    <filter-name>hello_filter</filter-name>

    <!-- 拦截所有资源 -->

    <url-pattern>/*</url-pattern>

    </filter-mapping>

    对指定的请求拦截

    /*   表示拦截所有的请求

    <filter-mapping>

    <filter-name>hello_filter2</filter-name>

    <url-pattern>/*</url-pattern>

    </filter-mapping>

    默认拦截的类型:(直接访问或者重定向),但是不会拦截forward

    <dispatcher>REQUEST</dispatcher>

    拦截转发:

      <dispatcher>FORWARD</dispatcher>

    拦截包含的页面(RequestDispatcher.include(/page.jsp);    page.jsp也执行拦截)

      <dispatcher>INCLUDE</dispatcher>

    拦截声明式异常信息:

      <dispatcher>ERROR</dispatcher>

    <!-- 配置第二个过滤器 -->

    <!-- 演示: 拦截指定的请求 -->

    <filter>

    <filter-name>hello_filter2</filter-name>

    <filter-class>cn.itcast.a_filter_hello.HelloFilter2</filter-class>

    </filter>

    <filter-mapping>

    <filter-name>hello_filter2</filter-name>

    <!-- 1. 拦截所有

    <url-pattern>/*</url-pattern>

     -->

     <!-- 2. 拦截指定的jsp 

     <url-pattern>/index.jsp</url-pattern>

     <url-pattern>/list.jsp</url-pattern>

     -->

     <!-- 拦截所有的jsp

     <url-pattern>*.jsp</url-pattern>

      -->

      <!-- 3. 根据servlet的内部名称拦截

      <servlet-name>IndexServlet</servlet-name>

       -->

      <!-- 拦截指定的servlet 

      <url-pattern>/index</url-pattern>

      -->

      

      <!-- 4. 指定拦截指定的类型 -->

      <url-pattern>/*</url-pattern>

      <dispatcher>REQUEST</dispatcher>

      <dispatcher>FORWARD</dispatcher>

    </filter-mapping>

    共性问题:

    1. 过滤器:方法参数没有自动命名,说明没有关联源码

    --à 关联tomcatservlet源代码

    2. 连接池: 多刷新几次,报错!

    -à 连接没关

    QueryRunner qr = new QueryRunner();

    qr.update(con,sql);

    // 这里con一定要关闭

        -à 注意:dataSource 确定一个项目创建一次

    QueryRunner qr = new QueryRunner(dataSource);

    à 修改连接池参数配置

    3 .  编码

    // 设置POST提交的请求的编码

    request.setCharacterEncoding("UTF-8");

    // 设置相应体的编码

    response.setCharacterEncoding("UTF-8");

    // 设置页面打开时候时候的编码格式、 设置相应体的编码

    response.setContentType("text/html;charset=UTF-8");

    开发中:

    工作区间编码、项目编码、request/response、数据库编码一致!

    2.案例

    过滤器-编码统一处理

    几乎每一个Servlet都要涉及编码处理:处理请求数据中文问题!

    GET/POST

    每个servlet都要做这些操作,把公用的代码抽取-过滤器实现!

    代码实现思路:

    1. Login.jsp  登陆,输入“中文”
    2. LoginServlet.java   直接处理登陆请求
    3. EncodingFilter.java   过滤器处理请求数据编码:GET/POST

    过滤器:

    /**

     * 编码处理统一写到这里(servlet中不需要再处理编码)

     * @author Jie.Yuan

     *

     */

    public class EncodingFilter implements Filter {

    // 过滤器业务处理方法:处理的公用的业务逻辑操作

    @Override

    public void doFilter(ServletRequest req, ServletResponse res,

    FilterChain chain) throws IOException, ServletException {

    // 转型

    final HttpServletRequest request = (HttpServletRequest) req;    

    HttpServletResponse response = (HttpServletResponse) res;

    // 一、处理公用业务

    request.setCharacterEncoding("UTF-8"); // POST提交有效

    response.setContentType("text/html;charset=UTF-8");

    /*

     * 出现GET中文乱码,是因为在request.getParameter方法内部没有进行提交方式判断并处理。

     * String name = request.getParameter("userName");

     *

     * 解决:对指定接口的某一个方法进行功能扩展,可以使用代理!

     *      request对象(目标对象),创建代理对象!

     */

    HttpServletRequest proxy =  (HttpServletRequest) Proxy.newProxyInstance(

    request.getClass().getClassLoader(), // 指定当前使用的累加载器

    new Class[]{HttpServletRequest.class}, // 对目标对象实现的接口类型

    new InvocationHandler() { // 事件处理器

    @Override

    public Object invoke(Object proxy, Method method, Object[] args)

    throws Throwable {

    // 定义方法返回值

    Object returnValue = null;

    // 获取方法名

    String methodName = method.getName();

    // 判断:对getParameter方法进行GET提交中文处理

    if ("getParameter".equals(methodName)) {

    // 获取请求数据值【 <input type="text" name="userName">

    String value = request.getParameter(args[0].toString()); // 调用目标对象的方法

    // 获取提交方式

    String methodSubmit = request.getMethod(); // 直接调用目标对象的方法

    // 判断如果是GET提交,需要对数据进行处理  (POST提交已经处理过了)

    if ("GET".equals(methodSubmit)) {

    if (value != null && !"".equals(value.trim())){

    // 处理GET中文

    value = new String(value.getBytes("ISO8859-1"),"UTF-8");

    }

    }

    return value;

    }

    else {

    // 执行request对象的其他方法

    returnValue = method.invoke(request, args);

    }

    return returnValue;

    }

    });

    // 二、放行 (执行下一个过滤器或者servlet)

    chain.doFilter(proxy, response); // 传入代理对象

    }

    @Override

    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override

    public void destroy() {

    }

    }

    过滤器配置:

    <!-- 编码处理过滤器配置 -->

    <filter>

    <filter-name>encoding</filter-name>

    <filter-class>cn.itcast.a_loginFilter.EncodingFilter</filter-class>

    </filter>

    <filter-mapping>

    <filter-name>encoding</filter-name>

    <url-pattern>/*</url-pattern>

    </filter-mapping>

    Servlet

    public class LoginServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)

    throws ServletException, IOException {

    // 获取请求数据

    String name = request.getParameter("userName");

    System.out.println("用户:" + name);

    }

    1. 国际化

    假设我们正在开发一个支持多国语言的Web应用程序,要求系统能够根据客户端的系统的语言类型返回对应的界面:英文的操作系统返回英文界面,而中文的操作系统则返回中文界面——这便是典型的i18n国际化问题。

    Javaweb增强:过滤器、监听器、国际化、文件上传下载、javaMail

    国际化又简称为 i18ninternationalization

    国际化的人:

    人,英语,汉语;  可以说这个人是国际化的人;

    软件的国际化:

    软件

    中国: 显示中文,以及服务符合中国习惯的文本字符串!

     1999-09-09

    美国: 显示英文,以及服务符合他国习惯的文本字符串!

    这种软件,就叫国际化的软件!

    如何做到国际化的软件,要求:

    1. 软件中存储特定的字符串
    2. 知道浏览器当前使用哪种语言(Locale  

    Locale  本地化

    Java提供了一个本地化的对象!封装当前语言、国家、环境等特征!

    public class App {

    @Test

    //1. 本地化对象:Locale

    // 封装语言、国家信息的对象,有java.util提供

    public void testLocale() throws Exception {

    // 模拟中国语言等环境

    //Locale locale = Locale.CHINA;

    Locale locale = Locale.getDefault(); // 当前系统默认的语言环境

    System.out.println(locale.getCountry());    // CN  国家的简称

    System.out.println(locale.getDisplayCountry()); // 国家名称

    System.out.println(locale.getLanguage()); // zh 语言简称

    // 模拟美国国家

    Locale l_us = Locale.US;

    System.out.println(l_us.getCountry());

    System.out.println(l_us.getDisplayCountry());

    }

    }

    国际化

    静态数据国际化

    网站中显示的固定文本的国际化: “用户名”“密码“

    国际化的软件:

    1. 存储所有国家显示的文本的字符串

    a) 文件: properties

    b) 命名:  基础名_语言简称_国家简称.properties

    例如:msg_zh_CN.properties     存储所有中文

          Msg_en_US.properties    存储所有英文

    1. 程序中获取

    ResourceBundle类,可以读取国际化的资源文件!

    1、静态国际化 一般时菜单 一些变迁

     * 1)把需要国际化的文档存储到对应的properties文件中,名民航会泽: 基础名_语言缩写_国家缩写.properties. 一般msg_en_US.properties msg_zh_CN.properties

     * 2)使用ResourseBundle工具类 绑定,之后就可以直接读取

     * i.使用ResourceBundle.getBundle(String baseName, Locale locale)函数获取一个bundle示例

     * bsaeName 包名.基础名,不在src下面应当加上包名

     * locale 表示local实例

     * ii.通过bundle示例进一步获取属性值

     * bundle.getString ("key"); // 返回对饮键值对应的value

    @Test

    // i18n 国际化

    // 使用一个工具类 ResourseBundle 进行今天资源的绑定

    public void testI18n() throws Exception {

    Locale locale = Locale.US;

    ResourceBundle bundle = ResourceBundle.getBundle("cn.itcast.f_i18n.msg", locale);// 名字只需要写到基名称就可以了,后面的内容就不用写了。

    System.out.println(bundle.getString("hello"));

    System.out.println(bundle.getString("username"));

    System.out.println(bundle.getString("password"));

    }

    Msg_zh_CN.properties中的内容:

    Hello=你好

    Username=用户名

    Password=密码

     

     

     

     

    动态文本国际化

    中文:1987-09-19   1000

    英文: Sep/09 1987  $100

    数值,货币,时间,日期等数据由于可能在程序运行时动态产生,所以无法像文字一样简单地将它们从应用程序中分离出来,而是需要特殊处理。Java 中提供了解决这些问题的 API (位于 java.util 包和 java.text 包中)

    // 国际化 - 静态数据

    @Test

    public void testI18N() throws Exception {

    // 中文语言环境

    Locale locale = Locale.US;

    // 创建工具类对象ResourceBundle

    ResourceBundle bundle = ResourceBundle.getBundle("cn.itcast.f_i18n.msg", locale);

    // 根据key获取配置文件中的值

    System.out.println(bundle.getString("hello"));

    System.out.println(bundle.getString("username"));

    System.out.println(bundle.getString("pwd"));

    }

    // 国际化 - 动态文本 - 0. 概述

    @Test

    public void testI18N2() throws Exception {

    // 国际化货币

    NumberFormat.getCurrencyInstance();

    // 国际化数字

    NumberFormat.getNumberInstance();

    // 国际化百分比

    NumberFormat.getPercentInstance();  

    // 国际化日期

    //DateFormat.getDateTimeInstance(dateStyle, timeStyle, aLocale)

    }

    // 国际化 - 动态文本 - 1. 国际化货币

    @Test

    public void testI18N3() throws Exception {

    // 模拟语言环境

    Locale locale = Locale.CHINA;

    // 数据准备

    double number = 100;

    // 工具类

    NumberFormat nf = NumberFormat.getCurrencyInstance(locale);

    // 国际化货币

    String m = nf.format(number);

    // 测试

    System.out.println(m);

    }

    //面试题:  代码计算:  $100 * 10  

    @Test

    public void eg() throws Exception {

    String str = "$100";

    int num = 10;

    // 1. 分析str值是哪一国家的货币

    Locale us = Locale.US;

    // 2. 国际化工具类

    NumberFormat nf = NumberFormat.getCurrencyInstance(us);

    // 3. 解析str国币

    Number n = nf.parse(str);

    System.out.println(n.intValue() * num);

    }

    // 国际化 - 动态文本 - 2. 国际化数值

    @Test

    public void testI18N4() throws Exception {

    // 模拟语言环境

    Locale locale = Locale.CHINA;

    NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);

    String str = nf.format(1000000000);

    System.out.println(str);

    }

    // 国际化 - 动态文本 - 3. 国际化日期

    /*

     * 日期

     *   FULL   201534日 星期三

     *   LONG   201534

     *   FULL   201534日 星期三

     *    MEDIUM 2015-3-4

     *    SHORT  15-3-4

     *    

     * 时间

     *   FULL   下午043159CST

     *   LONG   下午043237

     *    MEDIUM 16:33:00

     *    SHORT  下午4:33

     *    

     *

     */

    @Test

    public void testI18N5() throws Exception {

    // 日期格式

    int dateStyle = DateFormat.SHORT;

    // 时间格式

    int timeStyle = DateFormat.SHORT;

    // 工具类

    DateFormat df =

    DateFormat.getDateTimeInstance(dateStyle, timeStyle, Locale.CHINA);

    String date = df.format(new Date());

    System.out.println(date);

    }

    // 面试2: 请将时间值:09-11-28 上午102539CST,反向解析成一个date对象。

    @Test

    public void eg2() throws Exception {

    String str = "09-11-28 上午102539CST";

    // 创建DateFormat工具类,国际化日期

    DateFormat df = DateFormat.getDateTimeInstance(

    DateFormat.SHORT, DateFormat.FULL, Locale.getDefault());

    Date d = df.parse(str);

    System.out.println(d);

    }

    Jsp页面国际化

    自己讲一段,jsp页面还是在web木下面msg_zh_CN.propertiesmsg_eg_US.properties还是在上面的src下面的某个包中,编译后,会被自动拷贝到服务器的web目录下。是这样.properties文件文件中还是一个一个的键值对。在jsp页面中直接使用,

    1、ResourceBundle bundle = ResourceBundle.getBundle("cn.itcast.f_i18n.msg",request.getLocale());这一句就是resourcebundle的使用,中间的参数就是写到msg具体的使用哪一个文件,交给服务器自己辨别。

    2、直接在jsp中嵌入java代码使用<%= bundle.getString(””)%>

    <html>

      <head>

       <%

       ResourceBundle bundle = ResourceBundle.getBundle("cn.itcast.f_i18n.msg",request.getLocale());

       %>

        <title><%=bundle.getString("title") %></title>

    <meta http-equiv="pragma" content="no-cache">

    <meta http-equiv="cache-control" content="no-cache">

    <meta http-equiv="expires" content="0">    

      </head>

      

      <body>

      <form name="frmLogin" action="${pageContext.request.contextPath }/admin?method=login" method="post">

       <table align="center" border="1">

       <tr>

       <td><%=bundle.getString("username") %></td>

       <td>

       <input type="text" name="userName">

       </td>

       </tr>

       <tr>

       <td><%=bundle.getString("pwd") %></td>

       <td>

       <input type="password" name="pwd">

       </td>

       </tr>

       <tr>

       <td>

       <input type="submit" value="<%=bundle.getString("submit") %>">

       </td>

       </tr>

       </table>

      </form>

      </body>

    </html>

    Jsp页面国际化  使用jstl标签

    JSTL标签:

    核心标签库

    国际化与格式化标签库

    数据库标签库(没用)

    函数库

    <fmt:setLocale value=""/>        设置本地化对象

       <fmt:setBundle basename=""/>     设置工具类

       <fmt:message></fmt:message>     显示国际化文本

    格式化数值

    <fmt:formatNumber pattern="#.##" value="100.99"></fmt:formatNumber>

    格式化日期:

    <fmt:formatDate pattern="yyyy-MM-dd" value="${date}"/>

     1 <html>
     2 
     3   <head>
     4 
     5    <!-- 一、设置本地化对象 -->
     6 
     7    <fmt:setLocale value="${pageContext.request.locale}"/>
     8 
     9    <!-- 二、设置工具类 -->
    10 
    11    <fmt:setBundle basename="cn.itcast.f_i18n.msg" var="bundle"/>
    12 
    13  
    14 
    15     <title><fmt:message key="title" bundle="${bundle}"></fmt:message></title>
    16 
    17 <meta http-equiv="pragma" content="no-cache">
    18 
    19 <meta http-equiv="cache-control" content="no-cache">
    20 
    21 <meta http-equiv="expires" content="0">    
    22 
    23   </head>
    24 
    25   
    26 
    27   <body>
    28 
    29   <form name="frmLogin" action="${pageContext.request.contextPath }/admin?method=login" method="post">
    30 
    31    <table align="center" border="1">
    32 
    33    <tr>
    34 
    35    <td><fmt:message key="username" bundle="${bundle}"></fmt:message></td>
    36 
    37    <td>
    38 
    39    <input type="text" name="userName">
    40 
    41    </td>
    42 
    43    </tr>
    44 
    45    <tr>
    46 
    47    <td><fmt:message key="pwd" bundle="${bundle}"></fmt:message></td>
    48 
    49    <td>
    50 
    51    <input type="password" name="pwd">
    52 
    53    </td>
    54 
    55    </tr>
    56 
    57    <tr>
    58 
    59    <td>
    60 
    61    <input type="submit" value="<fmt:message key="submit" bundle="${bundle}"/>">
    62 
    63    </td>
    64 
    65    </tr>
    66 
    67    </table>
    68 
    69   </form>
    70 
    71   </body>
    72 
    73 </html>
     
  • 相关阅读:
    【leetcode】Triangle (#120)
    【leetcode】Unique Binary Search Trees (#96)
    【leetcode】Maximum Subarray (53)
    【转】算法杂货铺——k均值聚类(K-means)
    EM算法总结
    人工智能聚类算法总结
    K-MEANS算法总结
    在线制作css动画——CSS animate
    IOS 固定定位底部input输入框,获取焦点时弹出的输入法键盘挡住input
    响应式、手机端、自适应 百分比实现div等宽等高的方法
  • 原文地址:https://www.cnblogs.com/OliverZhang/p/6076782.html
Copyright © 2011-2022 走看看