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实现:

posted @ 2018-01-19 05:41  十月十四  阅读(171)  评论(0编辑  收藏  举报