通过上一篇博客:Servlet 的详解 http://www.cnblogs.com/ysocean/p/6912191.html,我们大致知道了 Servlet 的基本用法。但是稍微分析一下 Servlet 的用法,我们还是发现其存在很多缺点:

  ①、一个请求对应一个 Servlet,即每一个请求我们都需要在 web.xml 文件中配置映射。如果项目大,请求很多,那么会造成 web.xml 很大,很难维护。

  ②、即便在好几个请求对应一个 Servlet,即在 service() 方法中,通过 if--else 语句来判断执行的代码块。那这样就会造成 service() 方法很拥挤。

  ③、一个项目只存在一个 web.xml 文件,如果一个项目是多人开发,那么整合代码开发过程中会有很多问题。不适合团队开发。

  ④、Servlet中doGet方法和doPost方法中的两个参数reqeust,response拥有严重的容器依赖性。

  ⑤、如果页面上表单中的元素比较复杂,则在Servlet的方法中获取表单元素的数据比较繁琐。

  ⑥、Servlet是单线程的,只要在Servlet中的声明一个实例变量,那么该变量在多线程访问时就会有线程安全问题。

  ⑦、在Servlet中处理异常,如果Servlet中有N个方法,则这N个方法必须都要try--catch。因为子类抛的异常不能大于父类。

那么接下来我们用一个例子来解决上面的问题。

  1、新建一个 Web 工程,名为 ServletIncreased。并在 web.xml 中配置一个过滤器 ServletFilter,这个过滤器会过滤所有以 .do 结尾的 URL 链接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="http://java.sun.com/xml/ns/javaee"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
  http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   id="WebApp_ID" version="3.0">
    
  <filter>
    <filter-name>ServletFilter</filter-name>
    <filter-class>com.ys.filter.ServletFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>ServletFilter</filter-name>
    <url-pattern>*.do</url-pattern>
  </filter-mapping>
   
</web-app>

  2、创建一个 UserServlet,里面有两个方法,insert()和update()方法,调用 insert() 方法会跳转到 insert.jsp 页面,调用 update() 方法会调转到 update.jsp 页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.ys.servlet;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class UserServlet {
    //用户插入方法
    public void insert(HttpServletRequest req,HttpServletResponse resp) throws Exception, IOException{
        req.getRequestDispatcher("insert.jsp").forward(req, resp);
    }
     
    //用户更新方法
    public void update(HttpServletRequest req,HttpServletResponse resp) throws Exception, IOException{
        req.getRequestDispatcher("update.jsp").forward(req, resp);
    }
     
}

  3、创建一个配置文件类,里面存放配置文件的关系,通过一个 Map 集合,保存 Servlet 的类名和全类名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.ys.config;
import java.util.HashMap;
import java.util.Map;
public class ServletNameConfig {
    //定义一个 Servlet 配置文件,Map<key,value>
    //key:表示 Servlet 的类名
    //value:表示 Servlet 类名的全称
    public static Map<String, String> servletMap = new HashMap<>();
     
    static {
        servletMap.put("UserServlet""com.ys.servlet.UserServlet");
    }
}

  4、回头看我们配置的过滤器,ServletFilter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.ys.filter;
import java.io.IOException;
import java.lang.reflect.Method;
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;
import com.ys.config.ServletNameConfig;
public class ServletFilter implements Filter{
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
         
        String reqURL = req.getRequestURI(); //  /ServletIncreased/UserServlet.do
        String[] strs = reqURL.split("/");
        //定义 Servlet 的全类名
        String servletAllName = null;
        if(strs[2] != null){
            //得到 请求路径的 servlet 类名
            String servletName = strs[2].substring(0, strs[2].indexOf("."));
            //根据获取的 Servlet 类名,由配置文件 ServletNameConfig 里面的map 得到 全类名
            servletAllName = ServletNameConfig.servletMap.get(servletName);
        }
        //获取请求方法名
        String methodName = req.getParameter("method");
        System.out.println(servletAllName+"---"+methodName);
        try {
            //通过反射调用执行方法
            Class obj = Class.forName(servletAllName);
            Method method = obj.getDeclaredMethod
                    (methodName, HttpServletRequest.class,HttpServletResponse.class);
            method.invoke(obj.newInstance(), req,resp);
        catch (Exception e) {
            e.printStackTrace();
        }      
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void destroy() {
    }
}

  整体的项目结构如下:

  

然后将整个项目发布到 tomcat 服务器运行,发布的方法可以如下:

  http://www.cnblogs.com/ysocean/p/6893446.html

然后我们在浏览器输入如下链接:http://localhost:8080/ServletIncreased/UserServlet.do?method=insert

  那么就会调用 UserServlet 的 insert 方法,进而跳转到 insert.jsp 页面

  

如果我们在浏览器输入如下链接:将 insert 改为 update

   http://localhost:8080/ServletIncreased/UserServlet.do?method=update

那么就会调用 UserServlet 的update 方法,进而调转到 update.jsp 页面

  

分析:这个改进主要是配置了一个过滤器,然后通过过滤器的 doFilter() 方法,我们可以通过请求路径获得请求URL,然后通过字符串的截取方法得到 Servlet 的名称。通过配置文件保存的 Servlet类名和全类名的对应关系得到全类名;然后利用反射的原理,通过 invoke() 方法来动态调用方法。这里我们并没有解决上面所有的问题,比如严重的容器依赖性我们这里还有。如果想真正解决,请看下一篇博客:Struts2 详解

对 Servlet 的改进的更多相关文章

  1. 对 Servlet 的改进--------Struts2 引入

    通过上一篇博客:Servlet 的详解 http://www.cnblogs.com/ysocean/p/6912191.html,我们大致知道了 Servlet 的基本用法.但是稍微分析一下 Ser ...

  2. Servlet(8)—GenericServlet和改进Servlet实例

    概念genericservlet是个抽象的父类,必须给出子类才能实例化它.它给出了设计servlet的一些骨架,定义了servlet生命周期,还有一些得到名字.配置.初始化参数的方法,其设计的是和应用 ...

  3. Servlet(9)—HttpServlet和改进Servlet实例

    HttpServlet:针对Http协议定义的一个Servlet基类,唯一的功能就是强制类型转换ServletRequest转换成HttpServletRequest,ServletResponse转 ...

  4. Servlet笔记6--Servlet程序改进

    第一步改进,GenericServlet: 我们目前所有放入Servlet类直接实现了javax.servlet.Servlet接口,但是这个接口中有很多方法是目前不需要的,我们可能只需要编写serv ...

  5. Servlet学习笔记(七)—— 自己定义过滤器的编写改进:自己定义实现FilterChain

    笔记六中实现了三种过滤器:字符编码过滤.登录权限过滤.敏感词过滤,可是有个缺陷就是,限定了过滤顺序,而不能实现先进行request过滤.最后response过滤,而且中间几项过滤的顺序不能动态改变.所 ...

  6. Java Servlet——改进的CGI

    一.关于Servlet 在上一篇随笔中,我们看到了CGI存在的不足,其每次请求都需加载和运行一个CGI程序.若使用Java编写CGI程序,需要为每个请求都启动一个系统进程以及JVM,其执行效率大大降低 ...

  7. java web学习总结(二十四) -------------------Servlet文件上传和下载的实现

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...

  8. servlet jsp jdbc bootstrarp mvc分层模式实现的第一个项目

    登录注册界面 这是一个注册和登录的界面 用到了前端页面中自带的一点H5的标签和属性---巩固下 邮箱格式 :type="email"  不能为空:  required=" ...

  9. Servlet与多线程与IO操作

    1.JVM内存模型相关概念 2.Java多线程并发深入理解 3.Servlet.设计模式.SpringMVC深入理解 4.Java基础遗漏点补充 数据库连接池:JDBC connection pool ...

随机推荐

  1. CImage访问像素及其像素操作总结

    MSDN的代码 COLORREF pixel; int maxY = imgOriginal.GetHeight(), maxX = imgOriginal.GetWidth(); byte r,g, ...

  2. Java——HashSet和TreeSet的区别

    HashSetHashSet有以下特点 不能保证元素的排列顺序,顺序有可能发生变化 不是同步的 集合元素可以是null,但只能放入一个null当向HashSet集合中存入一个元素时,HashSe ...

  3. arcgis jsapi接口入门系列(4):用代码在地图画点线面

    PS:用代码画点这样写是为了跟后面的用鼠标画点线面区分出来 画点 drawPointGraphic: function () { //点有多种样式:一般的点,显示文字,显示图片 //一般的点 let ...

  4. SP2-0734: 未知的命令开头 "imp scott/..." - 忽略了剩余的行。

    Oracle数据导入报错:SP2-0734: 未知的命令开头 "imp scott/..." - 忽略了剩余的行. 原因:进入sqlplus里是不能执行imp的(sqlplus不认 ...

  5. Java多态的应用

    //多态的应用 class Animal{     public void eat(){     } } class Dog extends Animal{     public void eat() ...

  6. MySQL优化汇总

    1)mysql优化汇总,转载自网络

  7. 洛谷 2299 Mzc和体委的争夺战

    题目背景 mzc与djn第四弹. 题目描述 mzc家很有钱(开玩笑),他家有n个男家丁(做过前三弹的都知道).但如此之多的男家丁吸引来了我们的体委(矮胖小伙),他要来与mzc争夺男家丁. mzc很生气 ...

  8. python 基础网络编程2

    python 基础网络编程2 前一篇讲了socketserver.py中BaseServer类, 下面介绍下TCPServer和UDPServer class TCPServer(BaseServer ...

  9. 11gR2新特性---Gpnp守护进程

    在这篇文章中,我们会对11gR2 新的守护进程(资源名称ora.gpnpd)进行介绍,其中包含的gpnp的功能,启动顺序和基本的诊断方法. gpnp全称为grid plug and play,该组件的 ...

  10. UVA 1220 Party at Hali-Bula (树形DP)

    求一棵数的最大独立集结点个数并判断方案是否唯一. dp[i][j]表示以i为根的子树的最大独立集,j的取值为选和不选. 决策: 当选择i时,就不能选择它的子结点. 当不选i时,它的子结点可选可不选. ...