jsp基础知识03-2

13年前
       
提交表单的时候能否提交中文,提交中文有乱码出现
方法1:可以在ActionServlet中的service方法中加上:request.setCharaterEncoding("utf-8");
方法2:过滤器

过滤器
 过滤器链
 过滤器应该怎么用呢>
 首先我们先创建一个类CharacterEncodingFilter让他继承javax.servlet.Filter
 实现其主要的方法
CharacterEncodingFilter类
 
package org.whatisjava.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class CharacterEncodingFilter implements Filter {
 public void destroy() {
  //做一些收尾工作
  
 }
 public void doFilter(ServletRequest request, ServletResponse response,
   FilterChain chain) throws IOException, ServletException {
  //注意这里是ServletRequest不是HttpServletRequest,这是sun公司的一个做的扩展的东西
  //过渡设计的产物,在应用的时候可以直接转换成
  HttpServletRequest req=(HttpServletRequest)request;
  HttpServletResponse resp=(HttpServletResponse)response;
  req.setCharacterEncoding("utf-8");
  //FilterChain意思是过滤器链
  //将请求和响应传给后面的组件
  
  chain.doFilter(request, response);
  //类似于方法调用,执行完上面这句之后,接着会执行下面代码
  
  //记住还要声明一下,让tomcat知道这个过滤器是拦在谁前面的;
  //怎么声明呢?在web.xml文件中声明filter,filter-mapping
  //最典型的例子,如论坛注册时,名字正规性,
  //必须调用该方法才能往下传
  //比如安全日志
  //存在多个filter时,看filter-mapping在web.xml文件中的先后顺序
  
  
 }
 public void init(FilterConfig config) throws ServletException {
  //类的对象在创建的时候使用
  //相当于初始化状态
 }
}
 
 
修改web.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 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-app_2_4.xsd">
 <filter>
  <filter-name>CharacterEncodingFilter</filter-name>
  <filter-class>org.whatisjava.filter.CharacterEncodingFilter</filter-class>
 </filter>
 <filter>
  <filter-name>LoggingFilter</filter-name>
  <filter-class>org.whatisjava.filter.LoggingFilter</filter-class>
 </filter>
 
 
 <filter-mapping>
  <filter-name>LoggingFilter</filter-name>
  <url-pattern>*.action</url-pattern>
 </filter-mapping>
 <filter-mapping>
  <filter-name>CharacterEncodingFilter</filter-name>
  <url-pattern>*.action</url-pattern>
 </filter-mapping>
 
 
 <servlet>
  <servlet-name>action</servlet-name>
  <servlet-class>
   org.smartstruts.action.ActionServlet
  </servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet>
  <servlet-name>ImageServlet</servlet-name>
  <servlet-class>
   org.whatisjava.servlet.ImageServlet
  </servlet-class>
 </servlet>
 <servlet-mapping>
  <servlet-name>action</servlet-name>
  <url-pattern>*.action</url-pattern>
 </servlet-mapping>
 <servlet-mapping>
  <servlet-name>ImageServlet</servlet-name>
  <url-pattern>/image</url-pattern>
 </servlet-mapping>
</web-app>
 
 
LoggingFilter类
 
package org.whatisjava.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoggingFilter implements Filter {
 public void destroy() {
  // TODO Auto-generated method stub
 }
 public void doFilter(ServletRequest request, ServletResponse response,
   FilterChain chain) throws IOException, ServletException {
  // TODO Auto-generated method stub
  HttpServletRequest req=(HttpServletRequest)request;
  HttpServletResponse resp=(HttpServletResponse)response;
  
  String clientIp=req.getRemoteAddr();
  int clientPort=req.getRemotePort();
  String uri=req.getRequestURI();
  long time=System.currentTimeMillis();
  
  //req.getServerName();
  //req.getServerPort();
  
  chain.doFilter(request, response);
  
  time=System.currentTimeMillis()-time;
  System.out.println(clientIp+"****"+uri+"***"+time);
  
  
  
  
 }
 public void init(FilterConfig arg0) throws ServletException {
  // TODO Auto-generated method stub
 }
}
 
 
总结:
 可变对象   引用
 不可变对象  string ,Integer
 session.setAttribute();如果是可变对象,则只需要set一遍就行
 如果是不可变对象,则需要重复set
 
对struts-config文件再进行一些小修改:
smartstruts-config.xml
<global-forwards>
  <forward name="" path="" redirect=""/>
</global-forwards>

四、标记库
在一个项目里面可能存在多个重复的信息,假设这个信息需要变更时
 怎么能快速修改呢?
 
 可以把它们放到一个属性文件里面〉
  user=User Name
  user_error=user and passowrd is error.
package test;
import java.util.Enumeration;
import java.util.ResourceBundle;
public class TestResource {
 public static void main(String [] args) throws Exception{
 ResourceBundle rb=ResourceBundle.getBundle("res");
 
 //ResourceBundle是JDK中专门用来读取属性文件的键值对的
 //"res"为扩展名
 
 String value=rb.getString("user");
 //getString取的是键,返回的是值
 System.out.println(value); 
 
 Enumeration en=rb.getKeys();
 //Enumeriation
 //Iterator迭代器已经将Enumeriation
 //属性文件不能识别中文
 //那么如何将属性值弄成中文呢?
 
 //通过native2ascii来进行转换
 
 while (en.hasMoreElements()){
  en.nextElement();
  //System.out.println(en.toString()); 
  //System.out.println(en);
  System.out.println(value);
 }
 //System.out.println(value);
 }
}
这样也有利于国际化
 
标记库,怎么做?
  1、首先设计一个标记库
   <hello  num="100" value="..."/>===>功能描述,输出value里面的内容num次;
  2、写一个类
   HelloTag extend SimpleTagSupport
   定义
    num
    value
   重写父类的doTag(){}方法
package org.smartstruts.taglib.bean;
import java.io.IOException;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;
public class HelloTag extends SimpleTagSupport {
 private int num;
 private String value;
 public HelloTag(){
  System.out.println("HelloTag...");
 }
 
 public int getNum() {
  return num;
 }
 public void setNum(int num) {
  System.out.println("setNum"+num);
  this.num = num;
 }
 public String getValue() {
  return value;
 }
 public void setValue(String value) {
  System.out.println("setValue"+value);
  this.value = value;
 }
 @Override
 public void doTag() throws JspException, IOException {
  // 必须要重写父类的方法
  System.out.println("Tag...");
  JspContext jspCtx=this.getJspContext();
  //getJspCcontext方法是simpleTagSupport的方法
  
  PageContext ctx=(PageContext)jspCtx;
  
  //jsp引擎把jsp页面转换成一个servlet(上面声明一些内建对象)
  //大多数内建对象都是servlet的api
  //PageContext是专门为创建的对象
  //PageContext的一种能力:往setXxxx,可以设置数据或者提取数据
  //还封装了对其他内建对象的引用,out,session,request,pageContext
  JspWriter out=ctx.getOut();
  for (int i=1;i<num;i++){
   System.out.println(value+" ");
  }
 
  
  super.doTag();
 }
 
 
}
 
   但是由于jsp引擎工作,可以使得我们jsp页面可以调用doTag,可以获取一个重要的PageContext对象
  PageContext除了有setAttribute,getAttribute,还可以获取其它的内建对象,也就可以做任何关于web方面的事情
    比如html,session,request等。
  3、在web-inf目录下新建一个文件hello.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 web-jsptaglibrary_2_0.xsd"
    version="2.0">
 
  <display-name>Test</display-name>
  <tlib-version>1.1</tlib-version>
  <short-name>test</short-name>
 
  <tag>
    <name>hello</name>
    <tag-class>org.smartstruts.taglib.bean.HelloTag</tag-class>
    <body-content>empty</body-content>
    <!--body-content>这里可以写两种:JSP/empty</body-content>-->
    <attribute>
        <name>num</name>
        <required>true</required><!--用户是否必须得填写这个属性-->
        <rtexprvalue>false</rtexprvalue>
    </attribute>   
    <attribute>
        <name>value</name>
        <required>true</required>
        <rtexprvalue>false</rtexprvalue>
    </attribute>
  </tag>
</taglib>

 最好的是把全局的资源配置文件放到servlet的application里面
 
 MessageResources
 

*********************************************************************
1、config.xml文件
 添加属性
  <message-resources  parameter="res">
  指定参数文件的路径,不包含扩展名properties
2、rule.xml文件跟着变更:  
 <pattern value="message-resources">
   <object-create-rule
    classname="org.whatisjava.controller.MessageResources" />
   <set-next-rule methodname="setMessageResources" />
   <set-properties-rule />
  </pattern>
3、做一个类:MessageResources
 其属性为:parameter,提供get,set方法
4、StrutsConfig文件变更:增加MessageResources属性,get,set方法
5、ActionServlet初始化的时候也把res资源文件初始化好,并把他放到大家能访问的地方
 
  
 private void initResources(){
  //首先要创建一个对象能存放读入的res资源文件内容
  Map messages=new HashMap();
  //String resName=config.getMessageResources().getParameter();
  MessageResources mr=config.getMessageResources();
  if (mr!=null){
   
  String resName=mr.getParameter();  
  ResourceBundle rb=ResourceBundle.getBundle(resName);
  
  Enumeration en=rb.getKeys();
  //Enumeriation
  //Iterator迭代器已经将Enumeriation
  //属性文件不能识别中文
  //那么如何将属性值弄成中文呢?
  
  //通过native2ascii来进行转换
  
  while (en.hasMoreElements()){
   String key=(String)en.nextElement();
   String value=rb.getString(key);
   //System.out.println(en.toString()); 
   //System.out.println(en);
   messages.put(key,value);
  
  }
  
  ServletContext ctx=this.getServletContext();
  ctx.setAttribute(Constants.MESSAGES_KEY, messages);
  //MESSAGES_KEY是我们自己写的一个常量
  
  }
  
 }
6、创建一个对象类Messages
 package org.smartruts.resources;
import java.util.HashMap;
import java.util.Map;
public class Messages {
 private Map<String,String> map=new HashMap<String,String>();
 
}
//首先要创建一个对象能存放读入的res资源文件内容、
7、写一个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 web-jsptaglibrary_2_0.xsd"
    version="2.0">
 
  <display-name>Smart Struts TagLib</display-name>
  <tlib-version>1.1</tlib-version>
  <short-name>bean</short-name>
 
  <tag>
    <name>message</name>
    <tag-class>org.smartstruts.taglib.bean.MessageTag</tag-class>
    <body-content>empty</body-content>
    <!--body-content>JSP</body-content>-->
    <attribute>
        <name>key</name>
        <required>true</required>
        <rtexprvalue>false</rtexprvalue>
    </attribute>   
  </tag>
</taglib>
8、创建一个MessageTag文件
package org.smartstruts.taglib.bean;
import java.io.IOException;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import org.smartstruts.Constants;
public class MessageTag extends SimpleTagSupport {
 //<message key=""/>
 private String key;
 
 public String getKey() {
  return key;
 }

 public void setKey(String key) {
  this.key = key;
 }
 @Override
 public void doTag() throws JspException, IOException {
 
  JspContext jspCtx=this.getJspContext();
  PageContext ctx=(PageContext)jspCtx;
  //以上两句是必不可少的
  //通过getServletContxt获得所有的内建对象
  ServletContext servletCtx=ctx.getServletContext();
  //从serlvetcontext中拿出key的值
  Map map=(Map)servletCtx.getAttribute(Constants.MESSAGES_KEY);
  
  if (map!=null){
  String value=(String)map.get(key);
  if (value!=null){
   ctx.getOut().write(value);
   //输出到指定的位置即可
   
  }
  }
  super.doTag();
 }
 
 
 
}
9、在页面中用标签库拿出数据
 通过资源文件就可以了。
 
 但是以前验证码错误信息是怎么来实现国际化呢?可以从application中把数据拿到

 Action类修改添加setMessage
 
 
 package org.smartstruts.action;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.smartstruts.Constants;
public abstract class Action {
 private HttpServlet servlet;//为什么要加上这个呢??
 //1v1 to 1v2
 public static final String SUCCESS="success";
 public static final String FAIL="fail";
 
 
 public abstract String execute(ActionForm form,HttpServletRequest request,
   HttpServletResponse response) throws Exception;
 
 protected void setMessage(HttpServletRequest request,String name,String key){
  //protected子类才能用的方法
  //此方法接收3个参数
  ServletContext ctx=this.getServlet().getServletContext();
  Map map=(Map)ctx.getAttribute(Constants.MESSAGES_KEY);
  //根据这个key到资源文件中找到value值
  //找到这个value后,然后往request里面写入了一个信息,name,value
  if (map!=null){
   String value=(String)map.get(key);
   if (value!=null){
    request.setAttribute(name, value);
    
   }
  }
  
  
 }
 public HttpServlet getServlet() {
  return servlet;
 }
 public void setServlet(HttpServlet servlet) {
  this.servlet = servlet;
 }
}
 
10、验证类
TestAction extends Action
this.setMessage(request,"error_msg","user");

 
**************************************************************************