对 Servlet 的改进--------Struts2 引入
通过上一篇博客: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 引入的更多相关文章
- struts2和servlet同时用(访问servlet时被struts2过滤器拦截问题的解决)
在同一个项目中间,如果既用到servlet有用了struts2的框架,运行项目时可能无法正常使用servlet,原因是在配置struts2的核心控制器时<url-pattern>/*< ...
- Struts2 引入
引入: 说:如果一个路径想访问一个类,需求怎么做? 第一种方法,用servlet 第二种方法,用过滤器 第三种方法如下图:把路径和方法都存到map里面,用反射可以执行类下的方法 第三中方法 ...
- 对 Servlet 的改进
通过上一篇博客:Servlet 的详解 http://www.cnblogs.com/ysocean/p/6912191.html,我们大致知道了 Servlet 的基本用法.但是稍微分析一下 Ser ...
- 控制层技术:Servlet+reflection、Struts2、Spring MVC三者之间的比较学习
Servlet Struts2 Spring MVC 处理用户提交的数据 基于MVC设计模式的Web应用程序 是一个框架 是MVC框架 导入servlet包,配置web.xml文件 web.xml & ...
- JavaScript组合设模式--改进上述引入的例子
对于组合设计模式: (1)组合模式中把对象分为两种(组合对象,和叶子对象) (2)组合对象和叶子对象实现:同一批操作 (3)对组合对象执行的操作可以向下传递到叶子节点进行操作 (4)这样就会弱化类与类 ...
- struts2权威指南学习笔记:struts2引入自定义库
问题: 在jsp页面中添加了s:property标签,然而在页面始终未展示 解决: 经过搜索学习,发现只要添加语句 1 <%@ taglib prefix="s" uri=& ...
- 在Eclipse中写web工程 发现import javax.servlet.http.HttpSession无法引入
解决方法 得加入tomcat的jar包,右击项目->build path-add libraries->server Runtime->选择要导入的tomcat 就可以了,如果没有选 ...
- struts2中访问servlet API
Struts2中的Action没有与任何Servlet API耦合,,但对于WEB应用的控制器而言,不访问Servlet API几乎是不可能的,例如需要跟踪HTTP Session状态等.Struts ...
- 引入工程报包导入异常:import javax.servlet.annotation.WebFilter;
引入工程报包导入异常:import javax.servlet.annotation.WebFilter; (2013-02-21 16:38:00) 分类: java 今天上午导入了一个项目,用 ...
随机推荐
- 24(java_io from keyboard)
public class ReadFromKB{ public static void main(String args[]) { try { byte bArray[]=new byte[128]; ...
- Mysql Innodb体系结构
Innodb体系结构 Innodb存储引擎主要包括内存池以及后台线程. 内存池:多个内存块组成一个内存池,主要维护进程/线程的内部数据.缓存磁盘数据,修改文件前先修改内存.redo log 后台线程: ...
- 【局域网聊天客户端篇】基于socket与Qt
前言 暑假把linux下的高级编程和网络编程学习了一遍,学习很重要,但是也得有个练手的地方,所以必须做做项目来认识下自己所学习的知识. 能够找到小伙伴一起做项目也是一件很快乐的事情的,很幸运的有两个小 ...
- js中将yyyy-MM-dd格式的日期转换
1.转换为yyyy年MM月dd日 var str = "2017-02-16"; var reg =/(\d{4})\-(\d{2})\-(\d{2})/; var date = ...
- SIP DB33标准笔记 监控图像获取
实时监控图像的获取: a) 实时监控图像的获取过程应包括获取实时流.释放实时流.应使用 RFC 3261 中定义的方法INVITE 获取一个摄像机的实时监控视频流. 取消没有完成的连接应采用 CANC ...
- Sencha+cordova 构造 华丽手机程序,并讲讲,在商用项目中经常用到的cordova插件(一)
采用 Sencha Architect 3 ,编辑设计,我只想说一个结论,jq能搞的 Sencha touch也能做到(只是 设计思路 更面向对象,学习知识量大点而已 ,不理解 MVC 就不用选了), ...
- 使用Perl提取Excel中的IO_MUX
使用Perl提取Excel中的IO_MUX 关键问题 提取数据 格式化输出 循环嵌套 数据结构构建 坐标映射,逆向提取关键字 描述 在IC集成中,我们使用Excel表格规划设计的IC引脚功能映射需要转 ...
- 使用SSH框架查出的实体集合用AJAX形式刷新到页面JOSONArray报异常
所报异常:net.sf.json.JSONException: java.lang.reflect.InvocationTargetException 问题根源:数据库中查出的日期是java.sql. ...
- .net应用程序中添加chm帮助文档打开显示此程序无法显示网页问题
在做.net大作业时添加了chm帮助文档结果在打开时显示“此程序无法显示网页问题”,但是把帮助文档拷到别的路径下却显示正常, 经过从网上查找,终于找到了答案: (1).chm文件的路径中不能含有“#” ...
- 【代码学习】PHP文件的上传和下载
===================== 文件上传和下载 ===================== 一.php.ini的配置信息 file_uploads = On /Off 是否允许文件上 ...