DAY07-Sping04

作者: 建国同学 | 来源:发表于2020-04-30 11:36 被阅读0次

    一、Spring Web框架

    MVC思想

    Spring MVC


    Servlet:Web 服务的模块,包含对 MVC 与 REST 的实现,Spring MVC。
    Web:提供与 Web 的集成,基于 Web 应用程序上下文。
    WebSocket:实现客户端与服务端主动通信。
    Portlet:提供了在 Portlet 环境中实现 MVC。

    它解决 Web 开发中常见的问题(参数接收、文件上传、表单验证、国际化等),而且使用简单,与 Spring无缝集成。
    Spring3.0 后全面超越 Struts2,成为最优秀的 MVC 框架 (更安全,性能更好,更简单)。
    支持 RESTful 风格的 URL 请求 ,非常容易与其他视图技术集成,如 Velocity、FreeMarker、JSP 等。
    采用了松散耦合可插拔组件结构,比其他 MVC 框架更具扩展性和灵活性。

    • Spring FrameWork体系


    二、前端控制器

    在MVC框架中都存在一个前端控制器,在WEB应用的前端(Front)设置一个入口控制器(Controller)

    what

    是用来提供一个集中的请求处理机制,所有的请求都被发往该控制器统一处理,然后把请求分发给各自相应的处理程序

    do

    一般用来做一个共同的处理,如权限检查,授权,日志记录等

    why

    因为前端控制的集中处理请求的能力,因此提高了可重用性和可拓展性

    Spring MVC中的前端控制器

    • 其提供了 DispatcherServlet 类作为前端控制器,要使用Spring MVC必须在 web.xml 中配置前端控制器
    • 把处理请求的对象称之为处理器或后端控制器,Spring MVC中习惯称之为Controller,如处理员工请求的就会命名为EmployeeController

    三、 开发步骤

    打包方式是war

    添加依赖

    <properties>
        <spring.version>5.0.8.RELEASE</spring.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.1</version>
                <configuration>
                    <port>8080</port>
                    <path>/</path>
                    <uriEncoding>UTF-8</uriEncoding>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
    
    

    配置前端控制器

    • web.xml
        <!-- 配置前端控制器 -->
        <servlet>
            <servlet-name>dispatcherServlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!-- 指定启动容器的 Spring 配置文件 -->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:mvc.xml</param-value>
            </init-param>
            <!-- Tomcat 启动完之后就帮我们初始化这个servlet -->
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>dispatcherServlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
        
        <!-- 配置映射路径 -->
        <filter-mapping>
            <filter-name>characterEncodingFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
    • 配置如.do、.htm 是最传统方式,可以访问静态文件(jpg、 js、 css),但不支持 RESTful 风格。
    • 配置成 /,可以支持流行的 RESTful 风格,但会导致静态文件(jpg、 js、 css)被拦截后不能访问。

    怎么让静态资源可以访问到:
    在 Spring MVC的配置文件中配置<mvc:default-servlet-handler/>即可。
    上述配置会在Spring MVC上下文中定义一个DefaultServletHttpRequestHandler,它会对进入DispatcherServlet 的请求进行筛查,若不是映射的请求,就将该请求交由容器默认的Servlet处理。

    • 配置成 /*,是错误的方式,可以请求到 Controller 中,但跳转到调转到 JSP 时被拦截,不能渲染 JSP 视图,也会导致静资源访问不了。


    编写一个处理器类及JSP

    编写Spring MVC配置文件

    • mvc.xml


      mvc.xml

    四、处理响应

    找视图文件和往作用域中存入数据

    返回ModelAndView

    返回String

    消除视图前缀和后缀

    • mvc.xml
    <!-- 配置视图解析器 -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/views/"></property> <!-- 视图前缀 -->
            <property name="suffix" value=".jsp"></property> <!-- 视图后缀 -->
        </bean>
    

    视图就是:前缀+逻辑视图名+后缀名

    五、 请求转发及URL重定向

    请求转发

    加上forward前缀方式,表示请求转发,相当于request.getRequestDispatcher().forward(request,response),转发后浏览器地址栏不变,共享之前请求中的数据。

    @RequestMapping("/f")
        public String forward() {   
            // 不会使用到视图解析器的前缀与后缀
            //return "forward:/WEB-INF/views/03.f_r.jsp";
            
            //也可以转发到控制器里的方法路径
            return "forward:/resp1";
        }
    

    URL重定向

    redirect前缀方式,表示重定向,相当于response.sendRedirect(),重定向后浏览器地址栏变为重定向后的地址,不共享之前请求的数据。

    @RequestMapping("/r")
        public String redirect() {  
            // 不会使用到视图解析器的前缀与后缀
            //return "redirect:/01.static.html";
            
            //也可以重定向到控制器里的方法路径
            return "redirect:/resp2";
        }
    

    路径问题

    /response/test6.do ---> “redirect:/hello.html” ---> localhost:/hello.html
    /response/test6.do ---> “redirect:hello.html” ---> localhost:/response/hello.html

    六、 处理简单类型请求参数

    请求参数名 和 处理方法方法的形参 不同名时使用 @RequestParam

    //  /req1.do?username=xx&age=11
        @RequestMapping("/req1")
        public ModelAndView rep1(@RequestParam("username")String name, int age) {   
            System.out.println(name);
            System.out.println(age);
            return null; // 不找视图,不往作用域里存数据
        }
    

    乱码处理

    • get方式传递中文参数乱码问题
      使用 Maven 的话,可以 pom.xml 中的tomcat 插件配置一行这个也可以解决 <uriEncoding>UTF-8</uriEncoding>
      Tomcat 8已处理这个问题,不需要额外配置

    • post方法传递中文乱问题
      直接使用Spring MVC内置的过滤器来处理。
      web.xml

    <!-- 针对POST请求设置编码过滤器 -->
        <filter>
            <filter-name>characterEncodingFilter</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>characterEncodingFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    

    七、处理复合类型请求参数

    数组类型参数

    //   /req2.do?ids=1&ids=2&ids=3     使用环境:比如批量删除
        @RequestMapping("/req2")
        public ModelAndView req2(Long[] ids) {  
            System.out.println(Arrays.toString(ids));
            return null; // 不找视图,不往作用域里存数据
        }
    

    JavaBean类型参数

    @RequestMapping("/req3")
        /*反射创建User对象,遍历这个对象属性username, password id
         *  req.getParameter("属性名") 转型后设置到这个User对象属性上
         * */
        public ModelAndView req3(User user) {   
            System.out.println(user);
            return null; // 不找视图,不往作用域里存数据
        }
    

    八、处理日期类型请求参数

    处理日期格式参数

    • 在Controller形参贴上@DateTimeFormat
    //  /req4.do?date=2020-05-01
        @SuppressWarnings("deprecation")
        @RequestMapping("/req4")
        public ModelAndView req4(@DateTimeFormat(pattern="yyyy-MM-dd")Date date) {  
            System.out.println(date.toLocaleString());
            return null; // 不找视图,不往作用域里存数据
        }
    
    • 在封装参数类的Date类型的字段上贴@DateTimeFormat

      省略了setter和getter方法

    九、ModelAttribute注解使用

    项目中用于查询条件回显用

        //  /req5.do?keyword=x&minAge=1&maxAge=18
        @RequestMapping("/req5")
        public String req5(@ModelAttribute("qo")UserQueryObject qo) {   // model.addAttribute("userQueryObject",查询对象)
            System.out.println(qo);
            return "04.m";
        }
    

    在JSP中可通过${qo}获取

    十、 文件上传

    添加依赖

    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.2.2</version>
    </dependency>
    

    准备上传表单

    \color{#FF0000}{ 注意请求的类型必须是 }multipart/form-data,且是POST

    <form action="/upload.do" method="POST" enctype="multipart/form-data">
        姓名:<input type="text" name="username"/><br/>
        年龄:<input type="text" name="age"/><br/>
        文件:<input type="file" name="pic"><br>
             <input type="submit" value="提交"/>
    </form>
    

    配置上传解析器

    \color{#FF0000}{ 注意上传解析器这个bean名称是固定的,必须为}multipartResolver

    • mvc.xml
    <!-- 配置上传解析器 -->
        <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
            <property name="maxUploadSize" value="102400"></property>
        </bean>
    

    编写上传控制器

    @Controller
    public class UploadController {
        
        @Autowired
        private ServletContext servletContext; 
        
        // 在调用这个方法之前String MVC 会使用上传解析器帮你把上传的文件的内容封装成MultipartFile
        @RequestMapping("/upload")
        public ModelAndView upload(String username, int age, MultipartFile pic) throws IOException {
            System.out.println(username);
            System.out.println(age);
            System.out.println(pic.getContentType());// 文件类型
            System.out.println(pic.getName());// 上传文件的参数名name="pic"
            System.out.println(pic.getOriginalFilename());// 文件名
            System.out.println(pic.getSize());// 文件大小
            System.out.println(pic.getInputStream());// 文件输入流
            System.out.println(pic.getClass());// pic实现类
            
            // 根据项目上传文件的相对路径获取其绝对路径
            String uploadDir = servletContext.getRealPath("/uploaddir");
            System.out.println(uploadDir);
            // 获取文件后缀名
            String suffix = pic.getOriginalFilename().substring(pic.getOriginalFilename().lastIndexOf("."));
            System.out.println(suffix);
            // 第一个参数是源,第二个参数是目标
            FileCopyUtils.copy(pic.getInputStream(), new FileOutputStream(uploadDir+"/"+UUID.randomUUID().toString() + suffix));
            return null;
        }
    }
    

    十一、 拦截器

    • Spring MVC 提供的,若配置在Spring MVC配置文件中,则被Spring容器管理,主要用于对请求访问控制器的方法进行拦截
    • 项目中用于登录与权限判断

    定义一个类实现HandlerInterceptor

    public class MyHandlerInterceptor implements HandlerInterceptor {
    
        // 前置拦截,在控制器方法执行之前执行
        // 如果是false , 阻止执行
        // 如果是true , 执行放行 
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            System.out.println("preHandle");
            return false;
        }
        
        // 后置拦截,处理方法之后,渲染视图之前
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                ModelAndView modelAndView) throws Exception {
            System.out.println("postHandle");
        }
    
        // 渲染视图之后
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
                throws Exception {
            System.out.println("afterCompletion");
        }
    
    }
    

    配置拦截器

    被排除的路径
    <mvc:exclude-mapping path="/index.html"/>

    <!-- 配置拦截器 -->
        <mvc:interceptors>
            <mvc:interceptor>
                <!-- 映射路径,对哪些路径需要拦截 -->
                <mvc:mapping path="/**"/>
                <!-- 拦截处理器类 -->
                <bean class="cn.wolfcode.web.interceptor.MyHandlerInterceptor"></bean>
            </mvc:interceptor>
        </mvc:interceptors> 
    

    十二、核心组件说明

    不需要我们开发

    • 前端控制器DispatcherServlet
      不需要我们开发,由框架提供,需要在web.xml中配置。作用:接受请求,处理响应结果,转发器,中央处理器。
    • 处理器映射器HandlerMapping
      不需要我们开发,由框架提供。作用,更具请求的URL找到对应的Handler。
    • 处理器适配器HandlerAdapter
      不要我们开发,由框架提供。作用:调用处理器(Handler / Controller)的方法。
    • 视图解析器ViewResolver
      不需要我们开发,有框架或者第三方提供。作用:视图解析,把逻辑视图名称解析成真正的物理视图。支持多种视图技术Velocity、FreeMarker、JSP等。

    需要我们开发

    • 处理器Handler(又名Controller),后端控制器
      必须按照HandlerAdapter的规范去开发。作用:接收用户请求数据,调用业务方法处理请求。
    • 视图
      需要我们开发。作用:把数据展现给用户。

    开发步骤

    • 1、配置前端控制器
    • 2、配置处理器映射器、处理适配器、视图解析器(用默认的可不配置)。
    • 3、需要开发(结合需求):
      先开发Contoller,再配置。
      开发JSP。

    十三、 执行流程分析

    1. 用户发送出请求到前端控制器 DispatcherServlet。
    2. DispatcherServlet 收到请求调用 HandlerMapping(处理器映射器)。
    3. HandlerMapping 找到具体的处理器(通过 XML 或注解配置),生成处理器对象及处理器拦截器(若有),再一起返回给 DispatcherServlet。
    4. DispatcherServlet 调用 HandlerAdapter(处理器适配器)。
    5. HandlerAdapter 经过适配调用具体的处理器的某个方法(Handler/Controller)。
    6. Controller 执行完成返回 ModelAndView 对象。
    7. HandlerAdapter 将 Controller 返回的 ModelAndView 再返回给 DispatcherServlet。
    8. DispatcherServlet 将 ModelAndView 传给 ViewReslover(视图解析器)。
    9. ViewReslover 解析后返回具体 View(视图)。
    10. DispatcherServlet 根据 View 进行渲染视图(即将模型数据填充至视图中)。
    11. DispatcherServlet 响应用户。

    相关文章

      网友评论

        本文标题:DAY07-Sping04

        本文链接:https://www.haomeiwen.com/subject/mxgawhtx.html