jsp知识1

13年前
一、JSP model
JSP Model one :Jsp+javaBean:jsp页面直接调用java的类,java类把业务的操作封装起来   非主流的
JSP Model two: MVC在WEB项目中的具体应用

 JSP+JavaBean
  JSP model one   
   就是JSP页面直接调用java类,java类把业务的操作封装起来
 JSP+JavaBean已经慢慢不再用了。
  最主流的模式是MVC
   Struts
    要想用好Struts,要想理解JSP的原理
我们先写一个山寨版本的Struts
 只有这样我们才能理解什么是框架,我们要努力学习
二、MVC?
 我们主要是指导MVC在WEB项目中的具体应用。
  JSP  MODEL TWO
  在软件工程中,基本上不会随便升级模式的。因为升级模式,程序可能重构,程序员要重新学习
JSP model one:每一个JSP页面之间可能存在错综复杂的关系
 |
 |     升级过程中,JSP重构
 |
 |
JSP MODEL TWO
MVC
M层:JavaBean   ----model很难理解,记住就行;主要是对业务数据的访问
 1、包含dao
 2、包含domain中的类
C层:控制层(器)一般情况下用servlet来实现----没页面只有代码;
 1、接受提交,处理请求(GET,POST)
 2、调用M
 3、选择JSP去显示结果
V层:model two里面的jsp   view层,只能干两件事:1、显示结果;2、通过表单提交数据

三、举例子说明JSP model one,two:显示用户列表
 1、JSP MODEL ONE:jsp+javaBean
    user_list.jsp
    UserDao   访问数据
    User类   负责封装业务数据
    具体怎么功能:user_list.jsp与UserDao进行交互
    
    jsp: 1、接收请求 2、调用dao 3、显示结果
    
 2、jsp model two
    user_list.jsp
    ****servlet(为什么是servlet不是一个普通类呢?因为要接收请求,类不能接收请求)--控制器
    UserDao
    User
    
    servlet:1、接收请求 2、调用 dao  3、把数据传给jsp
    jsp:显示结果
    
   浏览器-----〉servlet---->dao------>servlet---->jsp------>显示结果
    重点在servlet---->jsp
     这里我们学习下转化技术(就是为了MVC才学习转发技术)
四、转发技术
 重定向  浏览器------jsp(servlet)---->浏览器----〉另外一个servlet或者jsp ---〉浏览器     两个请求
 转发     浏览器-------Servlet(做完一段事情后)---->jsp(接着做事,响应)----〉浏览器        一个请求
 jsp页面可以放到jsp下面
 tomcat 文件不允许浏览器访问web-inf下面的文件。web-inf下面的文件都不能通过浏览器直接访问.但是别的组件会通过转发的方式来访问
五:request和Session共享数据      
一个请求内部的不同组件之间共享数据用request
  request.setAttribute(arg0,arg1);
  request.getAtrribute(arg0,arg1);
多个请求之间共享数据用session,但是数据一直会存在session里面,用完最好直接清除。
    比如验证码
      1、一个生成验证码
      2、用户填写的验证码到服务器上与session中的验证码进行对比
六、
前端控制器:如果写多个servlet的话,servlet之间的关系就像JSP时的关系一样错综复杂。
   所以不管写多少功能,要求servlet只有一个,但是通过
修改web.xml文件,把前端控制器叫ActionServlet;其url-pattern地址为*.action
 <servlet>
     <servlet-name>action</servlet-name>
      <servlet-class>org.whatisjava.controller.ActionServlet</servlet-class>
   </servlet>
  <servlet-mapping>
     <servlet-name>action</servlet-name>
     <url-pattern>*.action</url-pattern>
  </servlet-mapping> 
******************************************************************************************
假设访问的地址为listUser.action时,就是看用户列表;假设访问的地址为:addUser时就是添加用户
******************************************************************************************
package org.whatisjava.controller;
import java.io.IOException;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.whatisjava.dao.UserDao;
public class ActionServlet extends HttpServlet {

 public void service(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {
  System.out.println("ActionServlet....");
  String uri=request.getRequestURI();
  //request.getRequestURI();//根据请求的url返回uri    ri(Returned Value)
  //For example: First line of HTTP request   Returned Value
  //POST   /some/path.html HTTP/1.1    /some/path.html 
  //GET   http://foo.bar/a.html HTTP/1.0  /a.html 
  //HEAD    /xyz?a=b HTTP/1.1     /xyz 
  //String path=uri.substring(uri.lastIndexOf("/"),uri.indexOf("."));
  //以上语句存在错误,使用下面语句通过
  String path=uri.substring(uri.lastIndexOf("/"),uri.lastIndexOf("."));
  //substring(int beginIndex,int endIndex);
  //从路径中取出文件名;
  
  //System.out.println(path);
  if("/listUser".equals(path)){
   UserDao dao=new UserDao();
   List list=(List) dao.findAllUser();
   
   request.setAttribute("user_list", list);
   RequestDispatcher rd=request.getRequestDispatcher("WEB-INF/jsp/user_list.jsp");
   rd.forward(request, response);
   
   
  }else if("/addUser".equals(path)){
   //添加用户
  
   
  }
  
  
 }
}
 //按照这种模式来做的话,这个serlvet将成了超级类
 
 
ActionServlet
ActionServlet(){
 if ()
 {
 }else if(){
 
 }
 
 }

我们怎么解决上面这个问题呢?
再做一个类叫Action;

package org.whatisjava.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public abstract class Action {
 public abstract String execute(HttpServletRequest request,HttpServletResponse response);
 //抽象类没有实例,用的是其子类;意思是让其子类长的一样
 //抽象方法不会有实现
 
}
 
<?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">
  <servlet>
    <servlet-name>ActionServlet</servlet-name>
    <servlet-class>org.whatisjava.controller.ActionServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>ActionServlet</servlet-name>
    <url-pattern>*.action</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>
 
*************************
ActionServlet
**********************
package org.whatisjava.controller;
import java.io.IOException;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.whatisjava.dao.UserDao;
public class ActionServlet extends HttpServlet {

 public void service(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {
  System.out.println("ActionServlet....");
  String uri=request.getRequestURI();
  //request.getRequestURI();//根据请求的url返回uri    ri(Returned Value)
  //For example: First line of HTTP request   Returned Value
  //POST   /some/path.html HTTP/1.1    /some/path.html 
  //GET   http://foo.bar/a.html HTTP/1.0  /a.html 
  //HEAD    /xyz?a=b HTTP/1.1     /xyz 
  String path=uri.substring(uri.lastIndexOf("/"),uri.indexOf("."));
  //substring(int beginIndex,int endIndex);
  //从路径中取出文件名;
  
  //System.out.println(path);
//  //*************************************
//  if("/listUser".equals(path)){
//   Action action=new ListUserAction();
//   
//   String forward=action.execute(request, response);
//   
//   RequestDispatcher rd=request.getRequestDispatcher(forward);
//   rd.forward(request, response);
//   
//   
//  }else if("/addUser".equals(path)){
//   //添加用户
//   //按照这种模式来做的话,这个serlvet将成了超级类
//   
//   Action action=new AddUserAction();
//   
//   String forward=action.execute(request, response);
//   
//   RequestDispatcher rd=request.getRequestDispatcher(forward);
//   rd.forward(request, response);
//   
//  }
//  //*********
   Action action=null;
  if ("user_list".equals(path)){
   
   action=new ListUserAction();
  }else if("addUser".equals(path)){
   
   action=new AddUserAction();
  }
  //假设这个地方再增加一个功能比如deleteUser,还是需要修改程序?
  //怎么才能避免需要添加功能时不修改Action呢?
  //最好的是把其放到配置文件里面
  
  //根据配置文件决定new哪个类......
  //采用反射
  //String className;
  //Class.forName(className).newInstance();
  
  String forward=action.execute(request, response);
  
  RequestDispatcher rd=request.getRequestDispatcher(forward);
  rd.forward(request, response);
  
  
 }
}

**********************
ListUserAction
************************
package org.whatisjava.controller;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.whatisjava.dao.UserDao;
public class ListUserAction extends Action {
 //
 public String execute(HttpServletRequest request,
   HttpServletResponse response) {
  UserDao dao=new UserDao();
  List list=(List) dao.findAllUser();
  
  request.setAttribute("user_list",list);
  
  return "/WEB-INF/jsp/user_list.jsp";
 }
}

如何去解析一个特定格式的xml配置文件

1、首先要定义一个配置文件格式:
 <action-mappings> <!--根元素-->
  <action path="/listUser" type="ListUserServlet"/>
  <!--表示一个元素;一个路径和类型的对应-->
  <action path="/addUser" type="AddUserServlet"/>
 </action-mappings>
 //一个action元素就表示了一个路径和一个类型的对应
 //说明书:
  以后所有的程序员按照以上格式来写配置文件
  程序首先要读这个配置文件,根据path的请求信息.action前面的那个值来确定new哪个类
  然后通过反射的方式来new这个类。
  
2、通过组件commons-digester来解析配置文件
 两种技术SAX    DOM这两种模式都是比较底层的技术
 组件commons-digester专门用来解析配置文件(struts也是用这个组件来解析配置文件的)
 配置文件一般都是在启动的时候读配置文件,把其内容缓存到内存中
 digester组件的功能作用就是把xml的元素转换成对象放到内存中。---这样做,就是先要在内存中做一组类
 和配置文件是对应的,这样就可以把xml的内容放到对象中了。
 根据上面的xml配置文件就相当于要做两个类
 ActionMappings----代表根元素ActionMappings
 ActionMapping----代表action元素

创建两个类
ActionMapping类
package org.whatisjava.controller;
public class ActionMapping {
 private String path;
 private String type;
 public ActionMapping(){
  
 }
 public String getPath() {
  return path;
 }
 public void setPath(String path) {
  this.path = path;
 }
 public String getType() {
  return type;
 }
 public void setType(String type) {
  this.type = type;
 }
 
 
}
ActionMappings类
package org.whatisjava.controller;
import java.util.HashMap;
import java.util.Map;
public class ActionMappings {
 //private Collection<ActionMapping> actions;
 //根据path找actionmapping,主要是用于查询;
 
 //到底是用ArrayLIST,还是HashMap中呢?
 //HashMap是根据HashCode做索引的
 private Map<String,ActionMapping> actions=new HashMap<String,ActionMapping>();
 
 //Map是键值对
 
 
 //提供一个方法能让外界访问,能把数据放到map里面
 public void addActionMapping(ActionMapping mapping){
  actions.put(mapping.getPath(), mapping);
  //key为mapping的path作为键;
  //mapping自身为value
  
 }
 
 
 public ActionMapping findActionMapping(String path){
  
  return (ActionMapping)actions.get(path);
  
 }
}
 
假设已经有一个组件已经可以把xml配置文件的信息一下子帮我们灌输到ActionMappings里面,在ActionServlet里面应该怎么做?

package org.whatisjava.controller;
import java.io.IOException;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.whatisjava.action.AddUserAction;
import org.whatisjava.action.ListUserAction;
import org.whatisjava.dao.UserDao;
public class ActionServlet extends HttpServlet {
 private ActionMappings mappings=null;
 
 public void init(){
  //构造完了之后会调用以下init();
  //初始化mappings(读取配置文件信息到mapings对象中)
  
 
 }
 
 
 
 public void service(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {
  System.out.println("ActionServlet....");
  String uri=request.getRequestURI();
  //request.getRequestURI();//根据请求的url返回uri    ri(Returned Value)
  //For example: First line of HTTP request   Returned Value
  //POST   /some/path.html HTTP/1.1    /some/path.html 
  //GET   http://foo.bar/a.html HTTP/1.0  /a.html 
  //HEAD    /xyz?a=b HTTP/1.1     /xyz 
  String path=uri.substring(uri.lastIndexOf("/"),uri.indexOf("."));
  //substring(int beginIndex,int endIndex);
  //从路径中取出文件名;
  
  //System.out.println(path);
//  //*************************************
//  if("/listUser".equals(path)){
//   Action action=new ListUserAction();
//   
//   String forward=action.execute(request, response);
//   
//   RequestDispatcher rd=request.getRequestDispatcher(forward);
//   rd.forward(request, response);
//   
//   
//  }else if("/addUser".equals(path)){
//   //添加用户
//   //按照这种模式来做的话,这个serlvet将成了超级类
//   
//   Action action=new AddUserAction();
//   
//   String forward=action.execute(request, response);
//   
//   RequestDispatcher rd=request.getRequestDispatcher(forward);
//   rd.forward(request, response);
//   
//  }
//  //*********
//   Action action=null;
//  if ("user_list".equals(path)){
//   
//   action=new ListUserAction();
//  }else if("addUser".equals(path)){
//   
//   action=new AddUserAction();
//  }
  //假设这个地方再增加一个功能比如deleteUser,还是需要修改程序?
  //怎么才能避免需要添加功能时不修改Action呢?
  //最好的是把其放到配置文件里面
  
  //根据配置文件决定new哪个类......
  //采用反射
  //String className;
  //Class.forName(className).newInstance();
  if (path==null) throw new ServletException("....."); 
  
  ActionMapping mapping=mappings.findActionMapping(path);
  
  if (mapping==null) throw new ServletException("...."); 
  
  
  try{  
  String className=mapping.getType();
  Class clazz=Class.forName(className);
  Action action=(Action) clazz.newInstance();
  
  String forward=action.execute(request, response);
  if (forward!=null){ 
  RequestDispatcher rd=request.getRequestDispatcher(forward);
  rd.forward(request, response);
  }
  }catch(Exception e){
   throw new ServletException("...");
   
  }
 }
}
 

导入commons-digest组件;将该包放到lib目录下。用这个小组件还需要配置一个rule.xml文件
rule.xml文件
<?xml version='1.0' encoding='UTF-8'?>
<!--
 这个xml文件是由commons-digester定义用于告诉digester组件
  自定义的配置文件和配置对象之间的关系,commons-digester组件了解了这
 个关系后就可以将配置文件中的信息转换为配置对象
-->
<digester-rules>
 <pattern value="action-mappings">
  <pattern value="action">
   <!--每碰到一个action元素,就创建指定类的对象-->
   <object-create-rule classname="org.whatisjava.controller.ActionMapping" />
   <!--
    对象创建后,调用指定的方法,
    将其加入它上一级元素所对应的对象
   -->
   <set-next-rule methodname="addActionMapping" />
   <!--
    将action元素的各个属性按照相同的名称
    赋值给刚刚创建的ActionMapping对象
   -->
   <set-properties-rule />
   
  </pattern>
 </pattern>
</digester-rules>
 
 
 
&&&&&&&&&&&&&&&&&*****************************
接下来要完成2个问题:
 a、框架的转发和重定向问题
 b、action返回的是好多地址
框架变更:
 
修改下config.xml文件
<action-mappings>
 <action path="/registerForm" type="org.whatisjava.action.RegisterFormAction">
  <forward name="123" path="/1.jsp" redirect="true"/>
  <forward name="456" path="/2.jsp" redirect="false"/>
 //这两个forward是定义在action里面的。一个forward包含name,path,redirect3个信息
   //redirect只能选择true或者false
   //action返回的地址不是真正的地址,而是forward中指定name 123,或456,
   //如果返回123,path=1.jsp,
</action>
 
</action-mappings>