SpringMVC

MVC架构

  • Model:数据模型,提供要展示的数据
  • View:负责模型展示,用户看到的页面
  • Controller:接受请求交给模型处理,并把结果返回为视图

运行流程

  1. SpinrgMVC的DispatcherServlet,它会接管、处理请求
  2. 其中有和流程有关的部件处理器映射器、处理器适配器的集合
  3. 根据请求会获得处理器合适的处理器映射器获得处理器
  4. 处理器就有对应处理该请求的Controller、拦截器信息
  5. 根据处理器获得适配器
  6. 适配器进行处理,使得Controller处理业务,返回信息
  7. 得到ModelAndView,进行渲染、合并转发

返回结果
在这里插入图片描述

相关类
DispatchServlet属性
  • HandlerMapping的List集合
  • HandlerAdapter的List集合
HandlerMapping

在这里插入图片描述

HandlerAdapter

在这里插入图片描述
以RequestMappingHandlerMapping为例

  1. 获得请求
  2. 遍历handlerMappings得到RequestMappingHandlerMapping,它包含了所有requestMappingController方法的映射(地址与方法的映射)
  3. RequestMappingHandlerMapping返回handler(包含Controller类信息、对应方法信息、拦截器信息)
  4. 根据handler得到对应的RequestMappingHandlerAdapter对象,包含了方法参数解析所需类等相关信息
  5. 执行adapter方法
  6. 底层参数、返回值处理,利用反射执行方法
  7. 得到结果

Controller原理(简单例子)

	<!--处理器映射器-->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

    <!--处理器适配器-->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

	 <!--BeanNameUrlHandlerMapping URL映射,这个请求交给 HelloController 处理-->
    <bean id="/hello" class="com.o11eH.controller.HelloController"/>
    
    <!--视图解析器,得到 modelAndView 拼接前后缀得到视图(页面)-->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
public class HelloController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
            throws Exception {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("msg", "Hello World!");

        //返回视图交给视图解析器
        return modelAndView;
    }
}

Controller使用

web项目配置文件
	<servlet>
        <!--dispatcherServlet拦截请求,并交给处理器映射器处理-->
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

        <init-param>
            <!--DispatcherServlet 绑定的配置文件-->
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:SpringMVC-config.xml</param-value>
        </init-param>

        <!--启动级别-->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>

        <!--/ 不匹配jsp,/* 则匹配 / 则接收拦截工程目录所有的请求-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
	<!--配置过滤器,设置编码解决中文乱码问题-->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

Spring基本配置

	<!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
    <context:component-scan base-package="com.o11eH.controller"/>

    <!-- 让Spring MVC不处理静态资源 -->
    <mvc:default-servlet-handler/>

    <!--
    支持mvc注解驱动
        在spring中一般采用@RequestMapping注解来完成映射关系
        要想使@RequestMapping注解生效
        必须向上下文中注册DefaultAnnotationHandlerMapping
        和一个AnnotationMethodHandlerAdapter实例
        这两个实例分别在类级别和方法级别处理。
        而annotation-driven配置帮助我们自动完成上述两个实例的注入。
     -->
    <mvc:annotation-driven/>

工作与上方原理部分相同

@Controller
public class HelloController {
    @RequestMapping("/hello")
    public String hello(Model model) {
        model.addAttribute("msg", "Hello World!");
        return "msg1";
    }
}

Restful

请求路径更简洁,不同的请求方式可以是相同的请求地址

@Controller
public class RestFulController {

    @RequestMapping("/add1")
    //传统方式设置参数访问
    public String add1(@RequestParam("n") int n1, @RequestParam("m") int n2, Model model) {
        int add = n1 + n2;
        model.addAttribute("msg", "相加结果为" + add);
        return "msg1";
    }

    @RequestMapping("/add2/{n1}/{n2}")
    public String add2(@PathVariable int n1, @PathVariable int n2, Model model) {
        int add = n1 + n2;
        model.addAttribute("msg", "相加结果为" + add);
        return "msg1";
    }

    @RequestMapping("/add3/{n1}/{n2}")
    public String add3(@PathVariable int n1, @PathVariable String n2, Model model) {
        String string = n1 + n2;
        model.addAttribute("msg", "数字和字符串拼接结果为" + string);
        return "msg1";
    }

    @RequestMapping(value = "/add4/{n1}/{n2}", method = RequestMethod.GET)
    public String add4(@PathVariable int n1, @PathVariable int n2, Model model) {
        int add = n1 + n2;
        model.addAttribute("msg", "Get请求相加结果为" + add);
        return "msg1";
    }

    @PostMapping(value = "/add4/{n1}/{n2}")
    public String add5(@PathVariable int n1, @PathVariable int n2, Model model) {
        int add = n1 + n2;
        model.addAttribute("msg", "Post请求,相加结果为" + add);
        return "msg1";
    }

    @RequestMapping(value = "/user")
    public String getUser(User user, Model model) {
        model.addAttribute("msg", user);
        return "msg1";
    }
Controller通过Servlet处理
    
	@RequestMapping("/servlet/test")
    //不需要视图解析器
    public void servletAPITest(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setAttribute("msg", "通过ServletAPI转发访问到这个页面");
        req.getRequestDispatcher("/WEB-INF/pages/msg1.jsp").forward(req, resp);
    }
}

Model重定向和转发

	@RequestMapping("/model/forward")
    public String forwardPage(Model model) {
        model.addAttribute("msg", "转发请求");
        return "msg1";//配置视图解析器后,不需要 “forward:”字符串
    }

    @RequestMapping("/model/redirect")
    public String redirectPage(Model model) {
        model.addAttribute("msg", "重定向");
        return "redirect:/index.jsp";
    }

spring配置拦截器

	<!--拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--
            /** 包含路径及子路径
            /A/* 拦截A/A1、A/A2,A/A1/A2不会被拦截
            -->
            <mvc:mapping path="/**"/>

            <bean class="com.o11eH.interceptor.WebInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
控制用户的访问
public class WebInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("拦截器处理处理前");
        System.out.println("URL:" + request.getRequestURI());

        if (request.getRequestURI().contains("login") || request.getSession().getAttribute("userName") != null) {
            return true;
        }
        request.getRequestDispatcher("/index.jsp").forward(request, response);
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        System.out.println("具体功能处理后");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("视图渲染后,清理");
    }

文件上传

	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--请求的编码格式,必须和jSP的pageEncoding属性一致-->
        <property name="defaultEncoding" value="utf-8"/>
        <property name="maxUploadSize" value="5242880"/>
        <property name="maxInMemorySize" value="51200"/>
    </bean>
@Controller
public class FileController {
    @RequestMapping("/upload")
    public String upload(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws
            IOException {
        String path = request.getSession().getServletContext().getRealPath("/Uploaded File");
        File filePath = new File(path);
        filePath.mkdir();
        file.transferTo(new File(filePath + "/" + file.getOriginalFilename()));
        return "redirect:/index.jsp";
    }
    @RequestMapping("/download")
    public void download(@RequestParam("fileName") String name, HttpServletRequest request, HttpServletResponse response) {
        String filePath = request.getSession().getServletContext().getRealPath("/Uploaded File");
        response.reset();
        response.setCharacterEncoding("utf-8");
        response.setContentType("multipart/form-data");
        response.setHeader("Content-Disposition", "attachment;fileName=" +
                URLEncoder.encode(name, StandardCharsets.UTF_8));

        InputStream is = null;
        OutputStream os = null;

        try {
            is = new FileInputStream(new File(filePath, name));
            os = response.getOutputStream();

            byte[] bytes = new byte[1024];
            int index;
            while ((index = is.read(bytes)) != -1) {
                os.write(bytes, 0, index);
                os.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {

                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

JSON传输

解决中文乱码
	<mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <constructor-arg value="UTF-8"/>
            </bean>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                        <property name="failOnEmptyBeans" value="false"/>
                    </bean>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

参考

【狂神说Java】SpringMVC最新教程IDEA版通俗易懂
狂神说SpringMVC01:什么是SpringMVC

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值