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