SpringMvc底层--自定义mvc

一.思路:<Springmvc的架构图>

 

<springmvc处理流程>

二,处理器实现接口controller

所有动作处理实现controller接口调用handlerRequest方法,来实现一个实体的所有增删改查的操作

/**
 *拦截器实现的接口
 */
public interface Controller {
    /**
     * 拦截器中处理请求uri
     * @param request
     * @param response
     * @return
     */
    public String handlerRequest(HttpServletRequest request,HttpServletResponse response);
}
假设一个实例实现这个接口<创建一个实例拦截器>

public class XXXController implements Controller {

    @Override
    public String handlerRequest(HttpServletRequest request,HttpServletResponse response) {
        String op = request.getParameter("op");
        //以add方法作为实例
        if("add".equals(op)){
            //TODO:从前端获取参数getParameter();
            ApplicationContext ac = WebApplicationContextUtils.findWebApplicationContext(request.getServletContext());

           //TODO:Service部分
            return "show.jsp";
        }
        return null;
    }

 

三,DispatcherServlet

1,接收用户请求解析给拦截器controller然后传给服务层(service层)
2,拦截器接收服务层处理的结果传给DispatcherServlet,解析uri地址<controller中的return ...>

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.解析地址: http://localhost:8080/testSpringmvc_copy/xxx.action
        String uri = request.getRequestURI();
        //2.取出xxx.action==>xxx
        String actionName = uri.substring( uri.lastIndexOf("/")+1);  //xxx.action
        String cotrollerName = actionName.substring(0,actionName.lastIndexOf("."));
        //3.根据请求的参数调对应的XxxController处理器
        Controller controller = null;
        if("Xxx".equals(cotrollerName)){
            controller = new XxxController();
        }
        //4.调用controller中的handlerRequest()方法处理
        String dispatcherUrl = null;
        if(controller!=null){
            dispatcherUrl = controller.handlerRequest(request, response); //获取handlerRequest()返回值
        }
        //5.获取返回值
        if(dispatcherUrl!=null){
            //6.跳转页面
            request.getRequestDispatcher(dispatcherUrl).forward(request, response);
        }else{
            request.getRequestDispatcher("404.jsp").forward(request, response);
        }

问题一:

写到这里,因为一个项目中不可能只有一个实体操作,也就是说有多少个实体对象就要创建多少个拦截器实例(Xxxcontroller),那么在这里的逻辑中每一次都要经过一次if...else if...语句的层层筛选,所以为了避免如此,思考是否可以利用Spring的IOC机制,就像配置实体类那样来配置controller然后由spring生成实例对象,然后我们直接取呢?

<!-- 配置controller -->
    <bean name="xxxController" class="com.yc.servlet.XxxController"></bean>

配置之后用注解的方式修改代码给值,然后修改上面的判断语句

ApplicationContext ac = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
Controller controller = (Controller) ac.getBean("xxxController");

测试之后发现可用,这样就有效的减少了不必要判断语句的书写

利用Spring的IOC机制,管理好处理器之后,问题又来了,配置之后到底使用多例还是单例呢?

           想想servlet----->多例----------->对于拦截器而言,就是处理来自DispatcherServlet的处理请求,然后返回处理后的结果给DispatcherServlet。所以使用多例。

问题二:在模型和视图中建立一种联系,是否可以用模型取得参数?是否一定就需要用转发?一定需要一个String的返回值类型吗?

四,建立模型,获取参数与跳转方式

1.以前J2ee部分取得参数,根据参数名取request.getParameter();  可以看成是一个Map类型     (参数名  , 参数值)

private Map<String,String> parameterMap = new HashMap<String,String>();
    public Map<String, String> getParameterMap() {
        return parameterMap;
    }
    public void setParameterMap(Map<String, String> parameterMap) {
        this.parameterMap = parameterMap;
    }

因为依赖于web,实际上还是用request来取得参数,但是包装到了Map中,然后通过模型建立的联系来操作

2.在模型与显示界面之间的request,session,application请求,重定向与转发跳转的模拟

public static final String WEBSCOPE_REQUEST="request";
    public static final String WEBSCOPE_SESSION ="session";
    public static final String WEBSCOPE_APPLICATION ="application";
    private String uri;        //跳转地址
    private boolean isDirect;   //如何跳转   true重定向   false转发
    private Object model;   //模型   用于在uri界面显示的模型
    private String webScope;   //模型保存的作用域

3.在拦截器controller接口中创建建立模型处理获取参数与跳转的方法

 /**
     * 处理器中处理参数获取与跳转
     * @param model
     * @return
     */
    public ModelAndView handlerRequest(Model model);

4.修改DispatcherServlet中跳转的代码

思路:得到请求的类型 ---》得到跳转的方式

获得请求的类型:

ModelAndView mv =null;
        if(controller!=null){
/*            dispatcherUrl = controller.handlerRequest(request, response); ////获取handlerRequest()返回值   return "...";
*/            Model model = new Model();
            mv = controller.handlerRequest(model);
        }
        if(mv==null){
            request.getRequestDispatcher("404.jsp").forward(request, response);
        }else{
            if(mv.getModel()!=null){
                switch(mv.getWebScope()){
                case ModelAndView.WEBSCOPE_REQUEST:
                    request.setAttribute(mv.getModelName(), mv.getModel());
                    break;
                case ModelAndView.WEBSCOPE_SESSION:
                    request.getSession().setAttribute(mv.getModelName(), mv.getModel());
                    break;
                case ModelAndView.WEBSCOPE_APPLICATION:
                    request.getServletContext().setAttribute(mv.getModelName(), mv.getModel());
                    break;
                }  
            }

 

获得跳转的方式:

if(mv.getUri()!=null){
                if(mv.isDirect()){
                    response.sendRedirect(mv.getUri());
                }else{
                    request.getRequestDispatcher(mv.getUri()).forward(request, response);
                }
            }

测试:

总结SpringMvc底层:   用户请求-->DispatcherServlet-->拦截器实例(实现拦截器接口) -->通过实现拦截器接口的方法把请求传给服务层(service层)-->调用Dao层方法-->回传参数给拦截器实例-->拦截器实例接收回传给DispatcherServlet-->解析调jsp页面

猜你喜欢

转载自blog.csdn.net/qq_42773863/article/details/81276281
今日推荐