表示层能有什么疑惑?很简单,我们暂时忘记所有的框架,就写一个注册的servlet来看看。

index.jsp

<form id="form1" name="form1" method="post" action="loginServlet">
<table width="357" border="0" align="center">
    <tr>
      <td width="128">用户名:</td>
      <td width="219"><label>
        <input name="user" type="text" id="user" value="dlf" />
      </label></td>
    </tr>
    <tr>
      <td>生日:</td>
      <td>
        <input name="birthday" type="text" id="pwd" value="2012-05-04" />
      </td>
    </tr>
    <tr>
      <td>
        <input type="submit" name="Submit" value="登录" />
      </td>
    </tr>
</table>
</form>

User.java

public Class User{
    private String user;
    private Date birthday;
    public User(){}
    .....//省略get/set
}

RegisterServlet.java

package example;
public class RegisterServlet extends HttpServlet {
public void destroy() {
   super.destroy(); // Just puts "destroy" string in log

   // Put your code here

}
public void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {

   request.setCharacterEncoding("utf-8");      //设置格式
   response.setContentType("text/html");

   PrintWriter out = response.getWriter();     //获得参数
   String name = new String (request.getParameter("user").getBytes("ISO8859_1"), "UTF-8");
   String birthday= new String(request.getParameter("birthday").getBytes("ISO8859_1"), "UTF-8");

   Date date=null;                //参数类型转换
   try{
    date=new SimpleDateFormat("yyyy-MM-dd").parse(birthday);
   }catch(ParseException e){
    e.printStackTrace();
   }  

   User user = new User();                      // 相当于MVC模型图中 第二步create
   user.setName(name);                // 相当于MVC模型图中 第四步extract
   user.setBirthday(date);            // bean中的数据来自于视图

   UserService us=new UserService();            //核心业务逻辑
   us.register(user);
                        //返回处理结果
                        // 相当于MVC模型图中 第三步forward
     request.getRequestDispatcher("/success.jsp").forward(request,response);

}
    public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        doPost(request,response);
    }
}

web.xml

<servlet>
    <servlet-name>register</servlet-name>        <!--这里是servlet的名字-->
    <servlet-class>example.RegisterServlet</servlet-class>    <!-- 这里写servlet类在的包路径-->
  </servlet>
  <servlet-mapping>                 <!-- 这里是地址映射-->
    <servlet-name>register</servlet-name><!--这个和上面的同名-->
    <url-pattern>/loginServlet</url-pattern><!--这里写servlet映射地址-->
  </servlet-mapping>

我们对照之前的MVC元素

Model(数据模型)----User.java

View(对外交互)-----registration.jsp

Control(程序执行与控制)-----RegistrationServlet.java

URL Mapping(请求转化)----web.xml

上面的代码有问题吗?

没有问题(除了取参数那部分)

上面的代码好吗?

不好。

哪里不好?

不好的地方主要在以下两点:

1 出于程序可读性和可维护性的考虑,程序还需要重构。

2 业务扩展也存在问题。

上面说的问题很宏观也很泛,下面具体说几个问题。



1 当浏览器发送一个Http请求,Web容器是如何接收这个请求并指定相应的java类来执行业务逻辑并返回处理结果呢?

这其实就是一个URL Mapping的问题。

对这个感兴趣的朋友 可以阅读 下面的一篇文章

how tomcat works 读书笔记 十一 StandWrapper 上

里面的参数由web.xml而来。

其实如何查找对应的java类,说白了就是servlet容器会分析请求的url并且和web.xml里面的servlet-mapping元素下的uri-pattern对照,如果找到一致的,就按照servlet-name查找到相应的java类。

至于这个根据uri生成java对象,在tomcat中使用的是digerter库。相关内容见:

How tomcat works 读书笔记十五 Digester库 上

很简单吧。但是这里也有一个问题,如果一个web.xml里面就写3-5个servlet,我们看着也方便;可问题是,如果一个系统里程序执行与控制部分由几十个几百个,都放在web.xml里面,那就是一场灾难了。

解决这个问题的策略是建立一套由uri到java类的规则匹配引擎。



2 在web请求中,数据是如何顺利地流转与浏览器与java世界中的。我们能否做到自动匹配?

在浏览器中,我们看到的信息都是字符串(弱类型),但是在java中,有string,int,boolean等等不同的数据类型(java是强类型)。在上面的servlet中,我们看到了birthday这个属性的转换。看上去也不复杂,不过如何属性不是一个是100个呢?属性的类型也不再是基本类型呢?

解决这个问题的策略是使用表达式引擎



3 servlet的多线程问题。

这是一个比较大的问题,详细说明见

tomcat中的线程问题

http://blog.csdn.net/dlf123321/article/details/42222303

4 Control层作为mvc的核心控制器,如何能在最大程度上支持功能点上的扩展。

这个问题很大。

这其实就是一个不断分层细化的问题。

上面的那句话肯定让大家很是不懂。我来仔细说说。

想想我们之前讨论分层的时候,为什么要分层?因为分层后,把相同的逻辑功能点放到了一起不管是可读性还是扩展性都有了保证。

那就上面的servlet而言能不能再次进行功能细分呢?

首先我们看看在那个servlet中代码在逻辑层面上都干了什么。

1 获得参数

2 类型转换

3 执行核心业务逻辑

4 返回处理结果

其实一个servlet(程序执行与控制模块)干的事情无外乎就是上面四步。那么我们能不能把它们四个再分割呢?

就像一个汽车工厂,最开始的时候,从原料(钢铁)的获得,材料的切割,焊接,喷色到最后的销售都是一个人负责的(在上面的例子中,就是说上面的四点都是在一个servlet中干的),这好不好?不好。为什么?

如果本来车子是喷蓝色油漆,我现在想改成喷白色漆。在一个人干所以事情的架构下回很麻烦,那怎么办?

做一条"流水线",一个人负责采购原料,一个人负责原料切割,一个人负责喷漆......

我现在想要改变喷漆的颜色,直接找那一个人就OK。

我们回到代码上,问题的难点在于,要构建一条"流水线"是很麻烦的,特别是这个流水线不仅能生产汽车,还能生产飞机,还能生产大炮。总而言之,这个"流水线"应该是一套规则,而不是实体。怎么做?我们自己来做流水线不现实的,所以看看前辈们的最佳实践,看看他们使用的框架是怎么构建"流水线"的。



5 View层的表现形式是多种多样的,随着Web开发技术的不断发展,MVC如何在框架级别提供一种完全透明的方式来应对不同的视图表现形式。

在之前的servlet中,我们是使用硬编码的形式来控制视图的流转。对上面这个问题的解决,其实也是第二个问题的答案。构建流水线。



6 MVC模式虽然很直观的为我们规定了表示层的各种元素,但是如何通过某种机制吧这些元素有机的整合在一起,从而形成一个整体呢。

这个问题太大,我在目前没有办法理解,只能截图了。

参考资料

http://blog.csdn.net/dlf123321/article/details/42222303

Struts2技术内幕 读书笔记三 表示层的困惑的更多相关文章

  1. Struts2技术内幕 读书笔记一 框架的本质

    本读书笔记系列,主要针对陆舟所著<<Struts2技术内幕 深入解析Strtus2架构设计与实现原理>>一书.笔记中所用的图片若无特殊说明,就都取自书中,特此声明. 什么是框架 ...

  2. 深入理解linux网络技术内幕读书笔记(三)--用户空间与内核的接口

    Table of Contents 1 概论 1.1 procfs (/proc 文件系统) 1.1.1 编程接口 1.2 sysctl (/proc/sys目录) 1.2.1 编程接口 1.3 sy ...

  3. Struts2技术内幕 读书笔记二 web开发的基本模式

    最佳实践 在讨论基本模式之前,我们先说说一个词:最佳实践 任何程序的编写都得遵循一个特定的规范.这种规范有约定俗称的例如:包名全小写,类名每个单词第一个字母大写等等等等;另外还有一些需要我们严格遵守的 ...

  4. Kafka技术内幕 读书笔记之(三) 生产者——消费者:高级API和低级API——基础知识

    1. 使用消费组实现消息队列的两种模式 分布式的消息系统Kafka支持多个生产者和多个消费者,生产者可以将消息发布到集群中不同节点的不同分区上:消费者也可以消费集群中多个节点的多个分区上的消息 . 写 ...

  5. webkit技术内幕读书笔记 (二、三)

    可视区和网页 通常网页比屏幕的可视区面积要大,因此当网页内容在可视区中放不下时,一般浏览器会提供滚动条. 从URL到构建完DOM树的过程 当用户输入网页URL的时候,WebKit调用其资源加载器加载该 ...

  6. Kafka技术内幕 读书笔记之(三) 消费者:高级API和低级API——消费者消费消息和提交分区偏移量

    消费者拉取钱程拉取每个分区的数据,会将分区的消息集包装成一个数据块( FetchedDataChunk )放入分区信息的队列中 . 而每个队列都对应一个消息流( KafkaStream ),消费者客户 ...

  7. MySQL技术内幕读书笔记(三)——文件

    目录 文件 参数文件 日志文件 套接字文件 pid文件 表结构定义文件 INNODB存储引擎文件 文件 ​ 有以下类型文件 参数文件:告诉MYSQL实例启动时在哪里找到数据库文件,并且制定某些初始化参 ...

  8. MySQL技术内幕读书笔记(八)——事务

    事务的实现 ​ 事务隔离性由锁来实现.原子性.一致性.持久性通过数据库的redo log和undo log来完成.redo log称为重做日志,用来保证事务的原子性和持久性.undo log用来保证事 ...

  9. MySQL技术内幕读书笔记(七)——锁

    锁 ​ 锁是数据库系统区分与文件系统的一个关键特性.为了保证数据一致性,必须有锁的介入.数据库系统使用锁是为了支持对共享资源进行并发访问,提供数据的完整性和一致性. lock与latch ​ 使用命令 ...

随机推荐

  1. PHP Ajax JavaScript Json 实现天气信息获取

    使用第三方服务 间接方式 思路 使用到的服务 实现代码 前端完整代码 总结 要在自己的网站上添加一个天气预报功能,是一个很普通的需求,实现起来也不是很难.今天来介绍几个简单的方法. 使用第三方服务 有 ...

  2. ubuntu蓝牙音响配对成功但在声音设置中无法设置 解决

    ubuntu蓝牙音响配对成功但在声音设置中无法设置 解决 首先,连接蓝牙 但是,在声音设置中如下: 都没有发现设备??? 打开终端输入: ~$ pactl load-module module-blu ...

  3. FORM内置系统变量

    常用 和输入焦点有关: SYSTEM.CURSOR_ITEM:返回系统当前正在操作的项名. SYSTEM.CURSOR_RECORD:返回系统当前正在操作的记录行号. SYSTEM.CURSOR_BL ...

  4. SQL语句常见问题的总结(持续更新)

    语言问题 修改语言注册表\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432\ORACLE\KEY_DevSuitHome1中的NLS_LANG修改为AMERICAN_AMERIC ...

  5. Asp.net 在刷新或提交页面后保持滚动条的位置

    网页内容在较长时,每次回传刷新页面或提交网页时都会定位到最顶端,非常不利于用户交互. 将Page.MaintainScrollPositionOnPostBack属性值设置为true即可实现刷新后保持 ...

  6. Struts 1之DispatchAction

    DispatchAction是struts 1 的内置通用分发器 import org.apache.struts.actions.DispatchAction; public class UserA ...

  7. Swift中类似C++和ruby中的final机制

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 我们知道在C++和ruby语言的错误处理中有一种final机制 ...

  8. FFmpeg源代码简单分析:avformat_alloc_output_context2()

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  9. 详解EBS接口开发之采购接收&退货处理之关键API--(补充)

    PROCEDURE process_rcv_online(p_api_version IN NUMBER, p_init_msg_list IN VARCHAR2 DEFAULT fnd_api.g_ ...

  10. 【Unity Shaders】法线纹理(Normal Mapping)的实现细节

    写在前面 写这篇的目的是为了总结我长期以来的混乱.虽然题目是"法线纹理的实现细节",但其实我想讲的是如何在shader中编程正确使用法线进行光照计算.这里面最让人头大的就是各种矩阵 ...