• Struts2 第一讲 -- Struts2开发前奏


      我们在学习Struts之前,先来复习一下Servlet,众所周知ServletJavaWeb的三大组件。我们发送一个请求,这个请求交给Servlet处理,Servlet将处理的结果返还给浏览器。每个Servlet对应一个URL-pattern。那么有没有这么一种情况呢?我们访问多个URL-pattern,这些URL-pattern具有共同的功能,那就是转发到其它页面,但是又不想写那么多ServletServlet虽然是单例的,但是能少一个对象,对于JVM也是一种优化不是吗,那么有什么办法可以做到呢?如下图

     

      熟悉Servlet的前辈,可能一看就会知道只是不可能的,一个Servlet只能对应一个URLPattern,那么怎么实现这个功能呢?下面我们通过项目来实现一下:

    • 创建Web项目struts2_1
    • 创建test.jsp页面,在页面中建立三个URL请求链接
    <body>
    <h3>入门路径:</h3><br>
    <a href="${pageContext.request.contextPath }/UserServlet">userWorld</a><br>
    <a href="${pageContext.request.contextPath }/HelloServlet">helloWorld</a><br>
    <a href="${pageContext.request.contextPath }/CustomerServlet">addWorld</a><br>
    
    </body>
    • 我们首先通过传统的Servlet来实现:

    UserServlet

        public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            response.setContentType("text/html;charset=utf-8");
            PrintWriter pw = response.getWriter();
            System.out.println("欢迎访问UserServlet");
            //pw.println("访问一次,我就得写一个Servlet!!!");请求转发会将response携带的数据丢失
            request.getRequestDispatcher("/success.jsp").forward(request, response);
            pw.flush();
            pw.close();
        }
    Web.xml 
     <servlet>
          <servlet-name>UserServlet</servlet-name>
          <servlet-class>cn.web.UserServlet</servlet-class>
      </servlet>
      <servlet-mapping>
          <servlet-name>UserServlet</servlet-name>
          <url-pattern>/UserServlet</url-pattern>
      </servlet-mapping>
    @WebServlet("/HelloServlet")
    public class HelloServlet extends HttpServlet {
        
        public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            response.setContentType("text/html;charset=utf-8");
            PrintWriter pw = response.getWriter();
            System.out.println("欢迎访问HelloServlet");
            pw.println("访问一次,我就得写一个Servlet!!!!");
            request.getRequestDispatcher("/error.jsp").forward(request, response);
            pw.flush();
            pw.close();
        }
    @WebServlet("/CustomerServlet")
    public class CustomerServlet extends HttpServlet {
        
        public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            response.setContentType("text/html;charset=utf-8");
            PrintWriter pw = response.getWriter();
            System.out.println("欢迎访问CustomerServlet");
            pw.println("访问一次,我就得写一个Servlet!!!!!");
            request.getRequestDispatcher("/add.jsp").forward(request, response);
            pw.flush();
            pw.close();
        }
    Success.jsp
      <body>
            xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
      </body>
    Error.jsp
      <body>
           错误页面
      </body>
    Add.jsp
      <body>
           添加
      </body>

      我们在浏览器访问test.jsp,然后可以访问到这些Servlet,但是我们也注意到了,每一个URLpattern对应一个Servlet,这么多请求造成了我们写了很多Servlet,并且需要很多web.xml中的配置(Servlet3.0以后支持注解)。 那么能否实现在web容器中只配置一次,就可以实现以上3URL都可以跳转到指定的页面呢?

      结论:可以使用过滤器实现:我们在过滤器中过滤所有的请求,进行判断,如果是test.jsp那么放行,否则就全部过滤操作。实际上根据上图我们知道这样一个对应关系,那就是一个请求对应一个Servlet,然后一个Servlet对应一个页面,那么我们创建两个Map集合,一个放请求和类的对应,一个放返回值和页面的对应.

    • 创建一个Action接口,作为请求对应的类,它有三个实现类对应三个Servlet
    package cn.filter;
    
    public interface Action {
        public String excute();
    }
    package cn.filter;
    
    public class HelloAction implements Action{
    
        @Override
        public String excute() {
            System.out.println("访问HelloAction!");
            return "error";
        }
    }
    package cn.filter;
    
    public class UserAction implements Action {
    
        @Override
        public String excute() {
            System.out.println("访问UserAction!");
            return "success";//对应请求转发的页面名称
        }
    }
    package cn.filter;
    
    public class CustomerAction implements Action {
    
        @Override
        public String excute() {
            System.out.println("访问CustomerAction!");
            return "add";
        }
    }
    • 创建Filter,然后对过滤进行操作

    package cn.filter;
    
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    
    import javax.servlet.DispatcherType;
    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.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebFilter(
            dispatcherTypes = {DispatcherType.REQUEST }
                        , 
            urlPatterns = { 
                    "/TestFilter", 
                    "/*"
            })
    public class TestFilter implements Filter {
        //使页面的访问路径对应Action类
        Map<String, String> actionMap = new HashMap<>();
        //使对应的action返回值对应相应的jsp页面
        Map<String, String> returnMap = new HashMap<>();
        //web容器启动时执行
        public void init(FilterConfig fConfig) throws ServletException {
            actionMap.put("/UserServlet", "cn.filter.UserAction");
            actionMap.put("/HelloServlet", "cn.filter.HelloAction");
            actionMap.put("/CustomerServlet", "cn.filter.CustomerAction");
            returnMap.put("success", "/success.jsp");
            returnMap.put("add", "/add.jsp");
            returnMap.put("error", "/error.jsp");
        }
        
        public void destroy() {
            // TODO Auto-generated method stub
        }
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
            HttpServletRequest request= (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) resp;
            //获取请求Servlet路径
            String path = request.getServletPath();
            if(path != null && path.equals("/test.jsp")){
                chain.doFilter(request, response);
                return;
            }//如果是test.jsp那么放行
            //如果不是test.jsp页面,那就进行过滤操作
            //获取访问的action路径
            String actionClass = actionMap.get(path);
            try {
                //通过反射获取Action类的对象
                Action action = (Action) Class.forName(actionClass).newInstance();
                //获取返回的页面名称
                String returnValue = action.excute();
                //利用Action类的返回值,获取所对应的页面
                String page = returnMap.get(returnValue);
                //转发到相应页面
                request.getRequestDispatcher(page).forward(request, response);
            } catch (InstantiationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
    }

      我们使用浏览器进行测试,发现,这次我们的请求没有经过Servlet,而是通过Action类处理了(对比前后两次控制台打印输出可以看出),通过过滤器,我们简单避免了web.xml中的反复配置.上面其实就是一个简单的Struts2实现:

  • 相关阅读:
    go 接收发送文件
    【0031】反转整数/判断回文
    【003】链表或字符串的【反转】【左旋转】
    【002】链表或字符串模拟加法/加一/乘法
    【01】数组中只出现一次的数字
    【面试题050】树中两个结点的最低公共祖先
    【面试题049】把字符串转换成整数
    【面试题048】不能继承的类
    【面试题047】不用加减乘除做加法
    【面试题046】求1+2+...+n
  • 原文地址:https://www.cnblogs.com/lin-jing/p/8315175.html
Copyright © 2020-2023  润新知