SpringMVC

1.SpringMVC快速入门

  • MVC是一种软件架构模式,分离了哑无逻辑和显示界面,包括model 模型、view视图、controller控制器,其中model负责处理业务逻辑,封装试题,view视图展现内容,controller控制器负责调度分发,如接受请求,调用模型,发出响应

SpringMVC

 

 

  •  SpingMVC是一种基于java的实现MVC 设计模式的轻量级web框架,属于SpringFrameWork的后续产品,融合在Spring Web Flow中,通过一套注解让一个简单的java成为处理请求的控控制器,无须实现任何借口,同时还支持RESTful编程风格的请求
  • 封装了原来的servlet中的共有行为,实现了参数封装,视图转发等功能

SpringMVC

  • 快速入门
    • 创建web项目,导入SpringMVC相关坐标
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>org.example</groupId>
        <artifactId>springmvc_quick</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>war</packaging>
    
        <dependencies>
        <!--springMVC坐标-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>
        <!--servlet坐标-->
        <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
        </dependency>
            <!--jsp坐标-->
            <dependency>
                <groupId>javax.servlet.jsp</groupId>
                <artifactId>jsp-api</artifactId>
                <version>2.2</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
    
    
    </project>
    • 配置SpringMVC前端控制器 DispathcerServlet
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
        <servlet>
            <servlet-name>DispatcherServlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:spring_mvc.xml</param-value>
            </init-param>
        <!-- 启动时加载-->
            <load-on-startup>2</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>DispatcherServlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>
    • 编写Controller类和视图页面,使用注解配置Controller类中业务方法的映射地址
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>成功响应</title>
    </head>
    <body>
    <%--视图页面--%>
    <h2>成功响应springmvc</h2>
    </body>
    </html>
    package com.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    public class UserController {
    //    编写Controller类,跳转到/quick地址并响应
        @RequestMapping("/quick")
        public String quick(){
            System.out.println("收到请求了");
            return "success.jsp";
        }
    
    
    }
    • 配置SpringMVC核心文件 spring-mvc.xml
    <!-- 开启注解扫描-->
    <context:component-scan base-package="controller"/>
  • 执行流程:Tomcat接受客户端发出的请求,解析请求资源地址,创建代表请求对象和响应对象,调用目标资源,此时通过前置DispatchServlet进行地址解析,将请求发送给对应的/quick的controller,执行响应,将响应传给前置DispatchServlet解析,组装成对应的响应发送给客户端

SpringMVC

 

 

 2.springmvc执行流程

  • 执行组件(springMVC三大组件是处理器映射器,处理器适配器,和视图解析器;四大组件是前端控制器,视图解析器,处理器适配器和处理器映射器)
    • 前端控制器DispatcherServlet:用户请求到达前端控制器,由它调用其他组件处理用户的请求,降低了组件之间的耦合性
    • 处理器映射器HandlerMapping:通过映射器对处理器进行适配,对更多类型的处理器进行执行,采用了适配器模式
    • 处理器Handler:由开发者编写,是真正执行请求的控制器,对具体业务进行处理
    • 视图解析器ViewResolver:负责将处理结果生成view视图,它首先将逻辑视图名解析层物理视图名,找到对应的页面地址,再生成view视图对象,对view进行渲染并将结果通过页面展示给用户
    • 视图view:有开发者编写,springMVC支持很多的view视图类型,如jstlView、freemarkerView、pdfView等,最常用的是jsp,通过页面标签或页面模板技术将页面展示给用户
  • 自定义配置三大组件
    • 处理器适配器和处理器映射器
    <!-- 配置处理器适配器和处理器映射器 ,可以对json格式解析,进行了方法的增强-->
        <mvc:annotation-driven/>
    • 视图解析器,一遍用于逻辑视图到物理视图地址的拼接
     
  • 执行流程
    • 用户发送请求到前端控制器DispatcherServlet,前端控制器收到请求后调用处理器映射器HandlerMapping
    • 处理器映射器根据请求,通过xml配置或注解方式找到对应的处理器,生成处理器对象和处理器拦截器,并返回给前端控制器
    • 前端控制器调用处理器适配器HandlerAdapter,由适配器通过适配方式找到具体的控制器即处理器(后端控制器)
    • 处理器执行完返回ModelAndView,处理器适配器将后端控制器的执行结果ModelAndView返还给前端控制器
    • 前端控制器将ModelAndView传给ViewReslover视图解析器,由视图解析器后返还具体的view
    • 前端控制器根据view进行视图渲染,并响应客户

    SpringMVC

  • 常用注解
    • Controller:SpringMVC基于Spring容器,所以在进行SpringMVC操作时,需要将Controller存储到Spring容器中,如果使用@Controller注解标注的话,就需要使用
      <!--配置注解扫描-->
      <context:component-scan base-package="com.controller"/>
    • RequestMapping:用于建立请求url和处理请求方法之间的对应关系
      • 类上:URL的一级访问目录,以/开头,方便模块化管理
    • 方法上:URL的二级访问目录,和一级目录组成一个完整的 URL 路径
      • value:用于指定请求的URL。它和path属性的作用是一样的
      • method:用来限定请求的方式
      • params:用来限定请求参数的条件,如{"accountName"} 表示请求参数中必须有accountName;{"money!100"} 表示请求参数中money不能是100
    • 访问页面或跳转时,WEB-INF下默认是安全资源,在其包下的资源不可以通过url直接获取,只可以在服务器内转发

3. SpringMVC请求

  • springMVC可以接收的参数类型:基本参数类型、对象参数类型、数组参数类型、集合参数类型。
    <%--
      Created by IntelliJ IDEA.
      User: Administrator
      Date: 2021/7/17
      Time: 14:51
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>请求数据</title>
    </head>
    <body>
    
    <%--不要有空格--%>
    <a href="${pageContext.request.contextPath}/data?username=大明&age=19" >普通数据类型</a>
    <a href="${pageContext.request.contextPath}/object?name=大明&id=2" >对象类型</a>
    
    <form method="post" action="${pageContext.request.contextPath}/array">
    
        <input type="checkbox" name="ids" value="1">1<br>
        <input type="checkbox" name="ids" value="2">2<br>
        <input type="checkbox" name="ids" value="3">3<br>
        <input type="checkbox" name="ids" value="4">4<br>
        <input type="checkbox" name="ids" value="5">5<br>
        <input type="submit" value="数组元素">
    </form>
    
    <form method="post" action="${pageContext.request.contextPath}/listormap">
        关键词 <input type="text" name="keyword">
        用户id<input type="text" name="user.id">姓名<input type="text" name="user.name">
        第一个集合<input type="text" name="userList[0].id"><input type="text" name="userList[0].name">
        第二个集合<input type="text" name="userList[1].id"><input type="text" name="userList[1].name">
        第一个map<input type="text" name="map['u1'].id"><input type="text" name="map['u1'].name">
        第二个map<input type="text" name="map['u2'].id"><input type="text" name="map['u2'].name">
        <input type="submit" value="集合数据类型">
    </form>
    
    <form method="post" action="${pageContext.request.contextPath}/date">
    自定义转换器 生日<input type="text" name="date">
        <input type="submit" value="自定义转换器 生日">
    </form>
    
    
    <a href="${pageContext.request.contextPath}/page?pageNo = 2" >对象类型</a>
    </body>
    </html>
    package domain;
    
    import java.util.List;
    import java.util.Map;
    
    public class QueryVo {
    
        private String keyword;
        private User user;
        private List<User> userList;
        private Map<String,User> map;
    
        @Override
        public String toString() {
            return "QueryVo{" +
                    "keyword='" + keyword + '\'' +
                    ", user=" + user +
                    ", userList=" + userList +
                    ", map=" + map +
                    '}';
        }
    
        public String getKeyword() {
            return keyword;
        }
    
        public void setKeyword(String keyword) {
            this.keyword = keyword;
        }
    
        public User getUser() {
            return user;
        }
    
        public void setUser(User user) {
            this.user = user;
        }
    
        public List<User> getUserList() {
            return userList;
        }
    
        public void setUserList(List<User> userList) {
            this.userList = userList;
        }
    
        public Map<String, User> getMap() {
            return map;
        }
    
        public void setMap(Map<String, User> map) {
            this.map = map;
        }
    }
    package domain;
    
    public class User {
        private int id;
        private String  name;
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    '}';
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    }
    package domain;

    public class User {
    private int id;
    private String name;

    @Override
    public String toString() {
    return "User{" +
    "id=" + id +
    ", name='" + name + '\'' +
    '}';
    }

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }

    public int getId() {
    return id;
    }

    public void setId(int id) {
    this.id = id;
    }
    }
    package controller;
    
    import domain.QueryVo;
    import domain.User;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.*;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import java.util.Arrays;
    import java.util.Date;
    
    @Controller
    public class UserController {
    
        @RequestMapping("/data")
        public String data(String username,Integer age){
            System.out.println(username);
            System.out.println(age);
            return "success";
        }
        @RequestMapping("/object")
        public String object(User user){
            System.out.println(user);
            return "success";
        }
        @RequestMapping(path = "/array")
        public String array(Integer[] ids){
            System.out.println(Arrays.toString(ids));
            return "success";
        }
        @RequestMapping("/listormap")
        public String listormap(QueryVo queryVo){
            System.out.println(queryVo);
            return "success";
        }
      
    
    }
  • controller中的业务方法会对参数值进行自动映射匹配和类型转换,将参数由string类型转为对应的要求类型
  • 中文乱码过滤器:当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>
        
  • 自定义转换器:springMVC提供了一些常用的类型转换器,对于特有的行为让那个开发者自定义处理
    package converters;
    
    import org.springframework.core.convert.converter.Converter;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class ConverterDate implements Converter<String,Date> {
    
        @Override
        public Date convert(String birth) {
            SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd");
            Date date =null;
            try {
                 date = sdf.parse(birth);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return date;
        }
    }
    <!-- 配置处理器适配器和处理器映射器 ,可以对json格式解析,进行了方法的增强-->
        <mvc:annotation-driven conversion-service="conversionService"/>
    
    <!-- 配置自定义转换器-->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="converters.ConverterDate"/>
            </set>
        </property>
    </bean>
    package controller;
    
    import domain.QueryVo;
    import domain.User;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.*;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import java.util.Arrays;
    import java.util.Date;
    
    @Controller
    public class UserController {
        @RequestMapping("/date")
        public String date(Date date){
            System.out.println(date);
            return "success";
        }
     
    }
  • 请求常用注解
    • @RequestParam:当请求参数名与controller业务方法的参数名不一致时,可以显示绑定,设置默认值和数据非必须
    • @RequestHeader:获取请求头数据
    • @CookieValue:获取cookie中的数据
    • 获取相关的Servlet相关API:SpringMVC支持使用原始ServletAPI对象作为控制器方法的参数进行注入,如request,response和session
package controller;

import domain.QueryVo;
import domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Arrays;
import java.util.Date;

@Controller
public class UserController {
    @RequestMapping("/page")
//    required 设置是否必须传递参数,默认值为true;如果设置了默认值,值自动改为false
    public String page(@RequestParam(name="pageNo", defaultValue ="1", required = false) Integer pageNum, @RequestParam(defaultValue = "5") Integer pageSize){
        System.out.println(pageNum);
        System.out.println(pageSize);
        return "success";
    }

    @RequestMapping("/header")
    public String header(@RequestHeader("cookie") String cookie){
        System.out.println(cookie);
        return "success";
    }
    @RequestMapping("/cookie")
    public String cookie(@CookieValue("JSESSIONID") String cookie){
        System.out.println(cookie);
        return "success";
    }
    @RequestMapping("/springAPI")
    public String springAPI(HttpServletRequest request, HttpServletResponse response, HttpSession session){
        System.out.println(request);
        System.out.println(response);
        System.out.println(session);
        return "success";
    }

}

4. springMVC响应

  • 页面跳转方式包括返回字符串逻辑视图、void原始ServletAPI和ModelAndView方式
  • void原始ServletAPI格式
   // 原始Servlet
    @RequestMapping("/servlet")
    public void servlet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;utf-8");
        response.getWriter().println("我收到额");
        request.setAttribute("username", "原始servlet");
        //  request.getRequestDispatcher("success.jsp").forward(request, response);

    }
  • 返回的数据格式可以通过直接返回字符串数据方式或将对象、集合转为json格式返回
  • 使用字符串逻辑视图实现页面的跳转实际上是执行请求转发,相当于forward
  • forward关键字实现转发,则路径必须是实际视图URL,相当于 request.getRequestDispatcher("url").forward(request,response) ,既可以转发到jsp,也可以转发到其他的控制器方法
 @RequestMapping("/forward")
    public String forward(Model model) {
        model.addAttribute("username", "转发");
        return "forward:success.jsp";
    }
  • Redirect重定向实现重定向,路径必须是实际视图URL,虚拟目录springMVC框架自动完成拼接
    @RequestMapping("/redirect")
    public String redirect(Model model) {
        model.addAttribute("username", "重定向");
// 重定向的页面不会展示username的值
        return "redirect:success";
    }
  • ModelAndView有两种方式实现,推荐方式二
    • 在Controller中方法创建并返回ModelAndView对象,并且设置视图名称
    • 在Controller中方法形参上直接声明ModelAndView,无需在方法中自己创建,在方法中直接使用该对象设置视图,同样可以跳转页面
    //ModelAndView方式一
        @RequestMapping("/model1")
        public ModelAndView model1() {
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.addObject("username", "modelAndView方式一");
            modelAndView.setViewName("success");
            return modelAndView;
        }
    
        //ModelAndView方式二
        @RequestMapping("/model2")
        public ModelAndView model2(ModelAndView modelAndView) {
            modelAndView.addObject("username", "modelAndView方式二");
            modelAndView.setViewName("success");
            return modelAndView;
        }
  • @SessionAttributes:适用于在多个请求之间共有数据,在控制器类上标注并配置需要在session中存放的数据,Spring MVC将存放在model中对应的数据暂存到HttpSession
 @RequestMapping("/forward")
    public String forward(Model model) {
        model.addAttribute("username", "转发");
        return "forward:success.jsp";
    }

    @RequestMapping("/returnString")
    public String returnString() {
        return "success";
    }

5.静态资源的开启

  • 问题:当有静态资源需要加载,如query文件,通过谷歌开发者工具抓包发现没有加载到jquery文件
  • 原因:SpringMVC的前端控制器DispatcherServlet的url-pattern配置的是 /(缺省),代表对所有的静态资源都进行处理操作,这样就不会执行Tomcat内置的DefaultServlet处理
  • 解决:配置文件放行静态资源
<!--方式一:在springmvc配置文件中指定放行资源-->
<mvc:resources mapping="/js/**" location="/js/"/>
<mvc:resources mapping="/css/**" location="/css/"/>
<mvc:resources mapping="/img/**" location="/img/"/>

<!--方式二(推荐):在springmvc配置文件中开启DefaultServlet处理静态资源-->
<mvc:default-servlet-handler/>
上一篇:springmvc 注解总结


下一篇:SpringMVC 框架基础