工具类积累(二)—— 一个Servlet处理多个URL请求

Posted on 2016-04-04 14:58  Iltxy  阅读(531)  评论(0)    收藏  举报

  今天帮同学看传智写聊天室源码时,在了解了该聊天室大致的结构之后,总结出了一个很不错的工具类!更准确的说是一段写得很优秀的源码!也解答了我长时间以来的疑惑!源代码如下:

 1 package cn.itcast.utils;
 2 import java.io.IOException;
 3 import java.lang.reflect.Method;
 4 
 5 import javax.servlet.ServletException;
 6 import javax.servlet.http.HttpServlet;
 7 import javax.servlet.http.HttpServletRequest;
 8 import javax.servlet.http.HttpServletResponse;
 9 
10 public class BaseServlet extends HttpServlet {
11     /*
12      * 它会根据请求中的method参数,来决定调用本类的哪个方法
13      */
14     protected void service(HttpServletRequest req, HttpServletResponse res)
15             throws ServletException, IOException {
16         req.setCharacterEncoding("UTF-8");
17         res.setContentType("text/html;charset=utf-8");
18         // 例如:http://localhost:8080/demo1/xxx?method=login
19         String methodName = req.getParameter("method");// 它是一个方法名称
20         // 当没用指定要调用的方法时,那么默认请求的是execute()方法。
21         if(methodName == null || methodName.isEmpty()) {
22             methodName = "execute";
23         }
24         Class c = this.getClass();
25         try {
26             // 通过方法名称获取方法的反射对象
27             Method m = c.getMethod(methodName, HttpServletRequest.class,
28                     HttpServletResponse.class);
29             // 反射方法目标方法,也就是说,如果methodName为add,那么就调用add方法。
30             String result = (String) m.invoke(this, req, res);
31             // 通过返回值完成请求转发
32             if(result != null && !result.isEmpty()) {
33                 req.getRequestDispatcher(result).forward(req, res);
34             }
35         } catch (Exception e) {
36             throw new ServletException(e);
37         }
38     }
39 }
转发类
  1 package cn.itcast.action;
  2 import java.io.IOException;
  3 import java.util.Date;
  4 import java.util.Map;
  5 
  6 import javax.servlet.ServletContext;
  7 import javax.servlet.http.HttpServletRequest;
  8 import javax.servlet.http.HttpServletResponse;
  9 import javax.servlet.http.HttpSession;
 10 import org.apache.commons.beanutils.BeanUtils;
 11 import cn.itcast.service.UserService;
 12 import cn.itcast.utils.BaseServlet;
 13 import cn.itcast.vo.User;
 14 public class UserServlet extends BaseServlet {
 15     /**
 16      * 检查session是否过期
 17      * @throws IOException 
 18      */
 19     public String check(HttpServletRequest req,HttpServletResponse resp) throws IOException{
 20         // 从session中获得用户的信息
 21         User existUser = (User) req.getSession().getAttribute("existUser");
 22         // 判断session中的用户是否过期
 23         if(existUser == null){
 24             // 登录的信息已经过期了!
 25             resp.getWriter().println("1");
 26         }else{
 27             // 登录的信息没有过期
 28             resp.getWriter().println("2");
 29         }
 30         return null;
 31     }
 32     
 33     /**
 34      *  退出聊天室
 35      * @throws IOException 
 36      */
 37     public String exit(HttpServletRequest request,HttpServletResponse response) throws IOException{
 38         // 获得session对象
 39         HttpSession session = request.getSession();
 40         // 将session销毁.
 41         session.invalidate();
 42         // 页面转向.
 43         response.sendRedirect(request.getContextPath()+"/index.jsp");
 44         return null;
 45     }
 46     
 47     /**
 48      * 发送聊天内容
 49      * @throws IOException 
 50      */
 51     public String sendMessage(HttpServletRequest req,HttpServletResponse resp) throws IOException{
 52         // 1.接收数据 。
 53         System.out.println("sendMessage invoke....");
 54         String from = req.getParameter("from"); // 发言人
 55         String face = req.getParameter("face"); // 表情
 56         String to = req.getParameter("to"); // 接收者
 57         String color = req.getParameter("color"); // 字体颜色
 58         String content = req.getParameter("content"); // 发言内容
 59         // 发言时间 正常情况下使用SimpleDateFormat
 60         String sendTime = new Date().toLocaleString(); // 发言时间
 61         // 获得ServletContext对象.
 62         ServletContext application = getServletContext();
 63         //  从ServletContext中获取消息
 64         String sourceMessage = (String) application.getAttribute("message");
 65         // 拼接发言的内容:xx 对 yy 说 xxx
 66         sourceMessage += "<font color='blue'><strong>" + from
 67                 + "</strong></font><font color='#CC0000'>" + face
 68                 + "</font>对<font color='green'>[" + to + "]</font>说:"
 69                 + "<font color='" + color + "'>" + content + "</font>("
 70                 + sendTime + ")<br>";
 71         // 将消息存入到application的范围
 72         application.setAttribute("message", sourceMessage);
 73         return getMessage(req, resp);
 74     }
 75     
 76     /**
 77      * 获取消息的方法
 78      * @throws IOException 
 79      */
 80     public String getMessage(HttpServletRequest req,HttpServletResponse resp) throws IOException{
 81         String message = (String) getServletContext().getAttribute("message");
 82         if(message != null){
 83             resp.getWriter().println(message);
 84         }
 85         return null;
 86     }
 87     /**
 88      * 踢人的功能
 89      * @throws IOException 
 90      */
 91     public String kick(HttpServletRequest req,HttpServletResponse resp) throws IOException{
 92         // 1.接收参数
 93         int id = Integer.parseInt(req.getParameter("id"));
 94         // 2.踢人:从userMap中将用户对应的session销毁.
 95         // 获得userMap集合(在线列表)
 96         Map<User, HttpSession> userMap = (Map<User, HttpSession>) getServletContext()
 97                 .getAttribute("userMap");
 98         // 获得这个用户对应的session.如何知道是哪个用户呢? id已经传递过来.去数据库中查询.
 99         // 重写user的equals 和 hashCode 方法 那么只要用户的id相同就认为是同一个用户.
100         User user = new User();
101         user.setId(id);
102         // 从map集合中获得用户的对应的session 
103         HttpSession session = userMap.get(user);
104         // 销毁session
105         session.invalidate();
106         // 重定向到页面
107         resp.sendRedirect(req.getContextPath()+"/main.jsp");
108         return null;
109     }
110     
111     /**
112      * 登录的功能
113      */
114     public String login(HttpServletRequest req,HttpServletResponse resp){
115         // 接收数据
116         Map<String, String[]> map = req.getParameterMap();
117         User user = new User();
118         // 封装数据
119         try {
120             BeanUtils.populate(user, map);
121             // 调用Service层处理数据 
122             UserService us = new UserService();
123             User existUser = us.login(user);
124             if (existUser == null) {
125                 // 用户登录失败
126                 req.setAttribute("msg", "用户名或密码错误!");
127                 return "/index.jsp";
128             } else {
129                 // 用户登录成功
130                 // 第一个BUG的解决:第二个用户登录后将之前的session销毁!
131                 req.getSession().invalidate();
132                 
133                 // 第二个BUG的解决:判断用户是否已经在Map集合中,存在:已经在列表中.销毁其session.
134                 // 获得到ServletCOntext中存的Map集合.
135                 Map<User, HttpSession> userMap = (Map<User, HttpSession>) getServletContext()
136                         .getAttribute("userMap");
137                 // 判断用户是否已经在map集合中'
138                 if(userMap.containsKey(existUser)){
139                     // 说用map中有这个用户.
140                     HttpSession session = userMap.get(existUser);
141                     // 将这个session销毁.
142                     session.invalidate();
143                 }
144                 // 使用监听器:HttpSessionBandingListener作用在JavaBean上的监听器.
145                 req.getSession().setAttribute("existUser", existUser);
146                 ServletContext application = getServletContext();
147                 String sourceMessage = "";
148                 if (null != application.getAttribute("message")) {
149                     sourceMessage = application.getAttribute("message")
150                             .toString();
151                 }
152                 sourceMessage += "系统公告:<font color='gray'>"
153                         + existUser.getUsername() + "走进了聊天室!</font><br>";
154                 application.setAttribute("message", sourceMessage);
155 
156                 resp.sendRedirect(req.getContextPath() + "/main.jsp");
157                 return null;
158             }
159         } catch (Exception e) {
160             e.printStackTrace();
161         } 
162         return null;
163     }
164 }
业务处理类
  这两个类结构写的蛮清楚的!一旦有请求过来,比如说:http:8080//localhost/项目名/User/method=login!当到达UserServlet时就会执行service方法。接下来所做的工作就是得到该类的类加载器,并根据方法名(为null时默认调用execute方法)调用对应的方法!这样就实现了UserServlet类处理多个Action请求的目的!说到这里,衷心觉得这段代码写得蛮好的!工具类积累(二)—— 一个Servlet处理多个URL请求 - 薛定谔的猫 - 薛定谔的猫
  想到这里,我突然想到了Struts2!它的模式似乎也是这样!在一个类中处理多个请求!看了上面一段代码!突然就形成了一个想法,或者说猜测吧!(没看源码,也没得到验证)现在我就基于上面的代码思路来简单的分析一些Struts的实现机制!
  首先,当前台一个请求到达的时候,就会经过Struts的核心过滤器--->
  过滤器就可以得到request和response对象-->
  根据request得到请求URL(假设是http:8080//localhost/项目名/namespace/methodName)-->
  解析该URL字符串,并且得到namespace和methodName-->
  根据配置文件struts.xml解析得到对应的类和方法名-->
  通过反射来调用对应的方法-->
  最后,根据返回的结果,将jsp显示!
  当然,上面的分析的确是太简陋,太简单了,实际项目中肯定是复杂得多了(过滤器、拦截器、监听器等等)!上面的分析肯定是基于最简单的情景而分析的。相信在思路上还是讲得通的。因为Struts框架的底层肯定还是Servlet!
  好了,今天的博客就写到这里了!不得不感叹,优秀的代码还是要读一些的!因为思路总是相通的!优秀的代码之所有优秀,那是因为优秀的代码集众家之所长!是人类智慧的结晶!
  思路分享给大家,希望有所启迪!

 

博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3