通过上一篇博客: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 链接

<?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 页面

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 的类名和全类名

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

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 的改进--------Struts2 引入的更多相关文章

  1. struts2和servlet同时用(访问servlet时被struts2过滤器拦截问题的解决)

    在同一个项目中间,如果既用到servlet有用了struts2的框架,运行项目时可能无法正常使用servlet,原因是在配置struts2的核心控制器时<url-pattern>/*< ...

  2. Struts2 引入

    引入:   说:如果一个路径想访问一个类,需求怎么做? 第一种方法,用servlet 第二种方法,用过滤器 第三种方法如下图:把路径和方法都存到map里面,用反射可以执行类下的方法     第三中方法 ...

  3. 对 Servlet 的改进

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

  4. 控制层技术:Servlet+reflection、Struts2、Spring MVC三者之间的比较学习

    Servlet Struts2 Spring MVC 处理用户提交的数据 基于MVC设计模式的Web应用程序 是一个框架 是MVC框架 导入servlet包,配置web.xml文件 web.xml & ...

  5. JavaScript组合设模式--改进上述引入的例子

    对于组合设计模式: (1)组合模式中把对象分为两种(组合对象,和叶子对象) (2)组合对象和叶子对象实现:同一批操作 (3)对组合对象执行的操作可以向下传递到叶子节点进行操作 (4)这样就会弱化类与类 ...

  6. struts2权威指南学习笔记:struts2引入自定义库

    问题: 在jsp页面中添加了s:property标签,然而在页面始终未展示 解决: 经过搜索学习,发现只要添加语句 1 <%@ taglib prefix="s" uri=& ...

  7. 在Eclipse中写web工程 发现import javax.servlet.http.HttpSession无法引入

    解决方法 得加入tomcat的jar包,右击项目->build path-add libraries->server Runtime->选择要导入的tomcat 就可以了,如果没有选 ...

  8. struts2中访问servlet API

    Struts2中的Action没有与任何Servlet API耦合,,但对于WEB应用的控制器而言,不访问Servlet API几乎是不可能的,例如需要跟踪HTTP Session状态等.Struts ...

  9. 引入工程报包导入异常:import javax.servlet.annotation.WebFilter;

    引入工程报包导入异常:import javax.servlet.annotation.WebFilter; (2013-02-21 16:38:00)   分类: java 今天上午导入了一个项目,用 ...

随机推荐

  1. 微信小程序,前端大梦想(二)

    微信小程序的视图与渲染  今天我们从四个方面来了解小程序:   •组件的基本使用  •数据绑定  •渲染标签  •模板的使用     一.组件的基本使用:  微信小程序为我们的开发提供了丰富的UI组件 ...

  2. Xshell 使用技巧

    Xshell是Windows平台下的一款ssh客户端程序,支持标签卡方式打开会话.打开多个会话后,打开"View"菜单,选中"Compose Bar",在Xsh ...

  3. (一)一起学 Java Collections Framework 源码之 概述

    . . . . . 目录 (一)一起学 Java Collections Framework 源码之 概述 JDK 中很多类 LZ 已经使用了无数次,但认认真真从源码级研究过其原理的还只占少数,虽然从 ...

  4. 原生JS跨浏览器事件封装处理

    引子:用javascript给元素绑定事件,我们可以用addEventListener这个方法,然而这个方法有兼容问题,比如在IE浏览器上面就无效,在IE上面要用attachEvent这个方法 一.a ...

  5. salt-stack部署

    saltstack部署   环境准备 [root@server elasticsearch]# cat /etc/redhat-release CentOS release 6.6 (Final)[r ...

  6. 初遇stm32

    刚开始接触32,建一个工程都这么费劲,可能是keil安装时一些文件和库没有安装完整,真是坑啊. 回头可能还要从新安装,然后开始新的学习,争取十天之内入门32,在博客园这个强大的技术支持下, 想不入门都 ...

  7. 图片裁剪(cropper)后上传问题

    最近工作需要处理头像裁剪以及上传,研究了几天,写点心得,提醒自己记住踩过的坑,能帮助别人当然更好. 功能基本就是这样: 这里需要注意的是:拿到需求后,不要急于直接上手,花费半个小时,甚至更长时间缕清整 ...

  8. SQL*Plus快速入门

    连接数据库sqlplus hr@\"//mymachine.mydomain:port/MYDB\" --连接到MYDB数据库的一个HR数据集里sqlplus hr@MYDB -- ...

  9. hdu1054最小顶点覆盖

    最小定点覆盖是指这样一种情况: 图G的顶点覆盖是一个顶点集合V,使得G中的每一条边都接触V中的至少一个顶点.我们称集合V覆盖了G的边.最小顶点覆盖是用最少的顶点来覆盖所有的边.顶点覆盖数是最小顶点覆盖 ...

  10. iOS APP开发设置启动图片 Launch Image

    一.添加启动图片 点击Assets.xcassets进入图片管理,右击,弹出"New Launch Image"或点下面的+号创建Launch Image: 这里首先说明一下尺寸: ...