Realization of the back end of tmall's Homepage Based on servlet+filter + reflection simulation

Keywords: Java JSP xml Session

In order to deepen the principle of web, this project does not use the framework, mainly describes the ideas from request to page presentation. For details, please refer to the specific project at the end of the article

Why use filter? Direct servlet implementation is not enough

Because tmall and other projects need many servlets to handle specific types of business, such as adding, deleting, modifying and querying the background management page, order page, and each operation needs to write a servlet. Using filter + reflection can solve this redundancy problem.

2. From browser input path to filter

For example, the home page address of our local tmall project is http://127.0.0.1:8080/tmall/forehome. Tmall here is the project name. We set filter in web.xml to intercept all requests, and / *, which is set by URL pattern. All requests will be mapped to the Java class tmall.filter.ForeServletFilter.

    <filter>
        <filter-name>ForeServletFilter</filter-name>
        <filter-class>tmall.filter.ForeServletFilter</filter-      class>
    </filter>
    <filter-mapping>
        <filter-name>ForeServletFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

In the doFilter method of filter, judge the request. If it starts with / for, jump to the servlet corresponding to the fore ground and do the specific logical data processing.

@WebFilter(filterName = "ForeServletFilter")
public class ForeServletFilter implements Filter {
    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        //Get path from project name
        String uri = request.getRequestURI();
        //Get project name path
        String contextPath = request.getContextPath();
        //Get path suffix
        String path = StringUtils.remove(uri, contextPath);
        if(path.startsWith("/fore")&&!path.startsWith("/foreServlet")) {
            //You need to take out the method name and put it in the session
            String method = StringUtils.substringAfterLast(path, "fore");
            request.setAttribute("method", method);
            //Jump to foreServlet
            request.getRequestDispatcher("/foreServlet").forward(request, response);
            return;
        }
        chain.doFilter(request, response);

    }

    @Override
    public void init(FilterConfig config) throws ServletException {

    }

}

3. Jump from filter to servlet

web.xml sets servlet mapping, and then jumps to the Java class ForeServlet.

    <servlet>
        <servlet-name>ForeServlet</servlet-name>
        <servlet-class>tmall.servlet.ForeServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>ForeServlet</servlet-name>
        <url-pattern>/foreServlet</url-pattern>
    </servlet-mapping>

Here, we only write the specific method instead of the service method, and let it inherit the service method of its parent class BaseForeServlet. The specific methods here include the methods mentioned above for adding, deleting, modifying and querying various background management pages and order pages. Here is an example of the home page to define a home() method:

public class ForeServlet extends BaseForeServlet {
    public String home(HttpServletRequest request, HttpServletResponse response, Page page) {
        List<Category> cs = categoryDAO.list(page.getStart(), page.getCount());
        //Fill data
        request.setAttribute("cs", cs);
        new ProductDAO().fill(cs);
        new ProductDAO().fillByRow(cs);
        return "home.jsp";
    }
}

IV. use reflection to call specific methods

So how do I call the home() method of this subclass servlet?
Here we use the service method of BaseForeServlet to first intercept the method name in the path, and then use the home() method of the reflection execution subclass to fill in the data.

@WebServlet(name = "BaseForeServlet")
public abstract class BaseForeServlet extends HttpServlet {
    
    protected CategoryDAO categoryDAO = new CategoryDAO();
    protected OrderDAO orderDAO = new OrderDAO();
    protected OrderItemDAO orderItemDAO = new OrderItemDAO();
    protected ProductDAO productDAO = new ProductDAO();
    protected ProductImageDAO productImageDAO = new ProductImageDAO();
    protected PropertyDAO propertyDAO = new PropertyDAO();
    protected PropertyValueDAO propertyValueDAO = new PropertyValueDAO();
    protected ReviewDAO reviewDAO = new ReviewDAO();
    protected UserDAO userDAO = new UserDAO();
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = (String)req.getAttribute("method");
        Method md = null;
        Page page = new Page(1, 5);
        try {
            md = this.getClass().getMethod(method, javax.servlet.http.HttpServletRequest.class,
                    javax.servlet.http.HttpServletResponse.class, Page.class);
            String redirect = md.invoke(this, req, resp, page).toString();
            if (redirect.startsWith("@")) {
                resp.sendRedirect(redirect);
            }else if (redirect.startsWith("%")) {
                resp.sendRedirect(redirect);
            }else {
                req.getRequestDispatcher(redirect).forward(req, resp);
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

V. page presentation

The foreServlet returns home.jsp to the parent class, which judges the path prefix and then jumps to the corresponding page.

String redirect = md.invoke(this, req, resp, page).toString();
            if (redirect.startsWith("@")) {
                resp.sendRedirect(redirect);
            }else if (redirect.startsWith("%")) {
                resp.sendRedirect(redirect);
            }else {
                req.getRequestDispatcher(redirect).forward(req, resp);
            }

Four, summary

We also implied the design pattern of MVC in this project. The Model is data such as Dao and Bean, the View is jsp page, and the Control is servlet. Because of the limited space, many contents are not displayed. For specific items, please refer to the project of a God on the Internet: Tmall J2EE project

Posted by Shuriken1 on Tue, 10 Dec 2019 02:18:41 -0800