java 框架

DAY07-Sping04

2020-04-30  本文已影响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 框架更具扩展性和灵活性。

二、前端控制器

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

what

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

do

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

why

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

Spring MVC中的前端控制器

三、 开发步骤

打包方式是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>

配置前端控制器

    <!-- 配置前端控制器 -->
    <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>

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

编写一个处理器类及JSP

编写Spring MVC配置文件

四、处理响应

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

返回ModelAndView

返回String

消除视图前缀和后缀

<!-- 配置视图解析器 -->
    <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; // 不找视图,不往作用域里存数据
    }

乱码处理

<!-- 针对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; // 不找视图,不往作用域里存数据
    }

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

处理日期格式参数

//  /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; // 不找视图,不往作用域里存数据
    }

九、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

<!-- 配置上传解析器 -->
    <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;
    }
}

十一、 拦截器

定义一个类实现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> 

十二、核心组件说明

不需要我们开发

需要我们开发

开发步骤

十三、 执行流程分析

  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 响应用户。
上一篇下一篇

猜你喜欢

热点阅读