SpringMVC日常学习总结

SpringMVC的学习总结

1、SpringMVC 概述

  1. SpringMVC 可以被认为是 Spring 框架的子框架,SpringMVC 要想使用的话得需要依赖于 Spring,也可以说是 SpringMVC 是 Spring 容器的子容器;
  2. 我们需要了解何为 MVC,它其实就是一种架构的模式;
    1. M: Module, 模型层,负责跟数据库进行交互的操作层,pojo、service、dao(mapper);
    2. V: View, 视图层,主要是进行数据的展现,负责跟客户进行交互,jsp、html、css、js…
    3. C: Controller, 控制层, 起到了一个桥梁的作用,负责 M 和 V 之间的交互;
  3. 简单聊下 MVC 的发展阶段;
    1. jsp模型阶段, 快捷开发. 所有能放到jsp中的代码全写到jsp中, pojo;
    2. Model2, jsp+Servlet. jsp负责页面显示, servlet负责控制. MVC. 会出现很多重复性的工作(Servlet层): 参数接收, 作用域传参, 页面跳转.
    3. MVC框架, 更加灵活, 更加简单的完成上述操作. 常见的MVC框架: SpringMVC, Struts2, JFinal(国人写的)
  4. SpringMVC 框架简介;
    1. 是一个 MVC 框架,重点在于对 Controller 层代码的简化;之前我们的控制器是 Servlet ,而用了 SpringMVC 后就不需要写 Servlet 了,普通的一个 Java 类就能替代原先的 Servlet 来完成控制器的功能;
    2. SpringMVC 通过两种控制器来完成对 Controller 层的工作,分别是:
      1. 前端控制器:类似于我们之前的 BaseServlet ,可以对前端所有的请求进行分发(调度),前端控制器由 SpringMVC 提供,叫做:DispatcherServlet. 简单来说前端控制器就是一个 Servlet ,使用 SpringMVC 的第一件事就是配置前端控制器;
      2. 后端控制器:类似于之前其他自定义的 Servlet ,由我们程序员自己提供,后端控制器需要实现指定的接口(里面定义了规范),接口的名称是 Controller

2、SpringMVC 环境搭建

2.1、通过配置的形式搭建(简单了解即可)
2.1.1、创建项目并导包

首先要是一个 web 项目, 包

spring相关的包:

springmvc相关的包:spring-webmvc.jar

2.1.2、编写后端控制器
public class DemoController implements Controller { // 需要实现接口:Controller
    @Override
    public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        // 准备要返回的结果对象
        // Model代表request作用域
        // View代表要跳转的页面
        ModelAndView mv = new ModelAndView();
        // 向作用域存放数据: demo
        mv.addObject("demo", "Hello SpringMVC!");
        // 跳转到一个页面: index.jsp
        mv.setViewName("index.jsp");
        // 返回结果
        return mv;
    }
}
2.1.3、web.xml配置文件
<?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">
    
    <!--配置前端控制器:DispatcherServlet 它是一个 Servlet 得需要有:<servlet-mapping> -->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <!--不能配/*, 要配置/, 放行jsp-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>
2.1.4、编写 SpringMVC 的配置文件

注意:

SpringMVC 的配置文件的位置和名字是有要求的,必须放在 WEB-INF 目录下,名称必须叫做: <servlet-name>-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!--配置后端控制器 - 是由我们程序员提供的类 需要继承 Controller 接口-->
    <bean name="/demo, /bjsxt" class="com.bjsxt.controller.DemoController" />
    <!--处理器适配器: 帮助前端控制器去调用后端控制器-->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
    <!--处理器映射器: 帮助后端控制器映射客户的访问路径, 类似于url-pattern-->
    <!--使用后端控制器的名称作为访问的路径-->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
    <!--视图解析器: 定位显示页面的-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" />
</beans>
2.1.5、具体访问流程
  • 当客户端发起请求后,首先会被前端控制器(DispatcherServlet)接收,前端控制器会先解析访问的路径;
  • 接着,通过处理器映射器进行比对,定位到需要调用的后端控制器;
  • 接下来,前端控制器会通过处理器适配器去调用后端控制器中的 handleRequest 方法;
  • handleRequest 方法会返回 ModelAndView 对象,由视图解析器解析要响应的页面, 将页面响应到客户端,这样用户就能看到访问的页面了;
2.1.6、存在的问题
  • 比较麻烦,还没有 Servlet 简单;
  • 后端控制器存在严重的问题,它必须要实现接口:Servlet;
  • SpringMVC 的配置文件也有问题;
2.2、通过注解的形式进行搭建(必须掌握)
2.2.1、和之前一样创建项目并导包;
2.2.2、编写后端控制器(不需要实现任何接口)

控制器方法需要遵循特定的签名规范;

public * 方法名(…)

一般情况下, 方法签名如下:

public String 方法名(…). 其中返回类型String, 表示要跳转的页面, 相当于ModelAndView.setViewName(string).

@Controller
public class DemoController {

    @RequestMapping({"/demo1", "/bjsxt"})
    public String demo1() {
        System.out.println("DemoController.demo1");
        return "index.jsp";
    }
}
2.2.3、web.xml配置文件
<?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:mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>
2.2.4、SpringMVC 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans.xsd
                    http://www.springframework.org/schema/context
                    http://www.springframework.org/schema/context/spring-context.xsd
                    http://www.springframework.org/schema/mvc
                    http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--注解扫描-->
    <context:component-scan base-package="com.bjsxt.controller" />
    <!--注解驱动-->
    <mvc:annotation-driven />
</beans>

注意:

<mvc:annotation-driven />配置后, 自动提供了一些SpringMVC的核心组件;官方文档如下:

在这里插入图片描述

3、视图解析器和静态资源映射

<!--配置自定义视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/" />
    <property name="suffix" value=".jsp" />
</bean>
<!--静态资源映射-->
<mvc:resources mapping="/static/**" location="/static/" />

4、作用域

4.1、作用域的复习
  • request作用域:HttpServletRequest
  • session作用域:HttpSession
  • application作用域:ServletContext
4.2、SpringMVC 中使用作用域
  • request 作用域:
@RequestMapping("/test")
public String demo2(HttpServletRequest req) {
    System.out.println("DemoController.demo2");
    req.setAttribute("demo", "HttpRequest");
    return "demo";
}
// ---------------------------
@RequestMapping("/test")
public String demo2(Model model) {
    System.out.println("DemoController.demo2");
    model.addAttribute("demo", "Model");
    return "demo";
}
// --------------------------
@RequestMapping("/test")
public String demo2(Map<String, Object> map) {
    System.out.println("DemoController.demo2");
    map.put("demo", "Map");
    return "demo";
}
  • session 作用域
@RequestMapping("/test")
public String demo2(HttpServletRequest req) {
    System.out.println("DemoController.demo2");
    req.getSession().setAttribute("demo", "request --> session");
    return "demo";
}
// --------------------------
@RequestMapping("/test")
public String demo2(HttpSession session) {
    System.out.println("DemoController.demo2");
    session.setAttribute("demo", "HttpSession");
    return "demo";
}
  • application作用域(不能直接传递 ServletContext 作为参数)
@RequestMapping("/test")
public String demo2(HttpServletRequest req) {
    System.out.println("DemoController.demo2");
    req.getServletContext().setAttribute("demo", "request --> application");
    return "demo";
}
// --------------------------
@RequestMapping("/test")
public String demo2(HttpSession session) {
    System.out.println("DemoController.demo2");
    session.getServletContext().setAttribute("demo", "session --> application");
    return "demo";
}

5、请求参数接收

5.1、Servlet 中如何接收参数

request.getParameter(name), request.getParameterValues(name). 方法的特点如下:

  • 参数要求是表单域的 name 属性;
  • getParameter方法用于获取单个值, 返回类型是String;
  • getParameterValues方法用于获取一组数据, 返回结果是String[];
  • 代码冗余较多,使用比较麻烦,类型需要自己转换;
5.2、使用 SpringMVC 进行参数的接收
  • 简化参数接收形式(不需要调用任何方法,需要什么参数,就在控制器方法中提供什么参数)
  • 参数类型不需要自己转换了,但是日期时期需要注意,需要使用 @DateTimeFormat 注解声明日期转换时遵循的格式,否则会报400错误;
  • 我们还可以自动将参数封装成对象
5.3、代码实现
<form action="/demo" method="post">
  用户姓名: <input type="text" name="username"><br>
  用户年龄: <input type="text" name="age"><br>
  婚否: <input type="radio" name="married" value="true" />已婚
  <input type="radio" name="married" value="false" />未婚<br>
  爱好: <input type="checkbox" name="hob" value="java"> java
  <input type="checkbox" name="hob" value="php"> python
  <input type="checkbox" name="hob" value="python"> c#<br>
  生日: <input type="text" name="birthday" placeholder="yyyy-MM-dd"><br>
  住址: <input type="text" name="address.city"><br>
  收货地址: <input type="text" name="addrs[0].city"><br>
  <input type="text" name="addrs[1].city"><br>
  <input type="submit" value="提交">
</form>
@Controller
public class DemoController {
    @RequestMapping("/demo")
    public String demo2(User user) { // 将参数封装成一个对象
        System.out.println("user = " + user);
        return "index.jsp";
    }

    @RequestMapping("/demo1")
    public String demo1(String username, int age, String[] hob,
               @DateTimeFormat(pattern = "yyyy-MM-dd") Date birthday) {
        System.out.println("username = " + username);
        System.out.println("age = " + age);
        System.out.println("hob = " + Arrays.toString(hob));
        System.out.println("birthday = " + birthday);
        return "index.jsp";
    }
}

6、请求参数的进阶处理

用来解决参数名称不匹配的问题,解决基本类型参数接收问题;Restful 风格参数的传递;

6.1、@RequestParam 注解的使用

用于对请求参数进行处理,该注解有三个属性:

  1. value | name: 表示前端传参的名称,如果前端传递的参数名和方法使用的参数名一致, 可以省略不写;
  2. required: 布尔值, 表示参数是否必须. 默认为true, 表示该参数必须传递;
  3. defaultValue: 默认值. 当某个参数前台没有传递或传递的是空字符串, 此时, 默认值就会生效;
<%--参数名称不匹配和基本类型问题--%>
<a href="demo?page=1&size=6">同名传参</a><br>
<a href="demo?param_1=1&param_2=10">不同名传参</a><br>
<a href="demo">没有参数传递</a><br>
<a href="demo?param_1=">空串传参</a>
@RequestMapping("/demo")
public String demo(
        @RequestParam(value = "param_1", defaultValue = "1") int page,
        @RequestParam(name = "param_2", defaultValue = "10") int size) {
    System.out.println("page = " + page);
    System.out.println("size = " + size);
    return "index.jsp";
}
6.2、Restful 风格参数传递

传统的形式进行参数传递:http://xxx/xxx?password1=value1&password2=value2…

Restful 风格形式进行参数传递:http://xxx/xxx/value1/value2/…

从访问路径中获取参数, 需要使用注解: @PathVariable

<%--Restful风格传参--%>
<a href="demo2/zhangsan/123">Restful</a>
@RequestMapping("/demo2/{username}/{pswd}")
public String demo2(
        @PathVariable String username,
        @PathVariable("pswd") String password) {
    System.out.println("username = " + username);
    System.out.println("password = " + password);
    return "/index.jsp";
}

7、@RequestMapping 详解

该注解用于后端控制器方法映射访问路径,同时,还可以对访问路径进行限制(窄化),该注解可以用在方法上,表示给方法映射访问路径;还可以用在控制器类上,表示对当前控制器类下所有的方法添加访问前缀路径,下面是常用属性介绍:

  • value | path: 字符串数组, 代表映射到该控制器方法的所有访问路径;

    当配置为: @RequestMapping("/demo"), 能匹配的路径有:

    • http://localhost:8080/demo
    • http://localhost:8080/demo.xxx
    • http://localhost:8080/demo/
  • method: RequestMethod数组, 表示当前控制器方法允许处理的请求方式. 默认允许所有请求方式. spring4.3后提供了两个简化注解: @GetMapping@PostMapping

    /**
     * 当前方法用于处理get请求
     *
     * @return
     */
    // @RequestMapping(method = RequestMethod.GET)
    @GetMapping
    public String demo3() {
        System.out.println("DemoController.demo3: GET");
        return "/index.jsp";
    }
    
    /**
     * 当前方法用于处理post请求
     *
     * @return
     */
    // @RequestMapping(method = RequestMethod.POST)
    @PostMapping
    public String demo2() {
        System.out.println("DemoController.demo2: POST");
        return "/index.jsp";
    }
    
  • params: 字符串数组, 表示对请求携带的参数进行限制. 要求请求中必须携带指定的参数, 否则抛出异常. token

    /**
     * 要求必须传递username和password参数
     * 而且username的值必须是admin
     * 
     * @param username
     * @param password
     * @return
     */
    @PostMapping(path = "/demo2", params = {"username=admin", "password"})
    public String demo4(String username, String password) {
        System.out.println("DemoController.demo4");
        return "/index.jsp";
    }
    
  • produces: 字符串数组, 用于设置响应头信息. 需要配合另外一个注解一起使用, 叫@ResponseBody.

: Http支持的请求方式: https://www.cnblogs.com/weibanggang/p/9454581.html (Restful 格式的访问链接)

8、页面跳转

8.1、页面跳转有两种方式
  1. 请求转发
  • request.getRequestDispatcher(path).forward(request, response);
  • 一次请求;
  • 地址栏路径不会发生改变;
  • 可以使用请求作用域进行传参;
  • 只能访问内部资源(就是当前目录下的资源);
  • 可以访问安全目录下的资源(就是WEB-INF)
  • 路径下的 / 表示项目的根路径
  1. 响应重定向
    • response.sendRedirect(location);
    • 多次请求;
    • 地址栏会发生变化(显示的是最后一次的请求路径);
    • 不能使用请求作用域传参;
    • 既可以访问内部资源也可以访问外部资源;
    • 不能访问安全目录下的资源(WEB-INF);
    • 同样 / 表示项目的根路径;
8.2、SpringMVC 实现页面跳转
8.2.1 请求转发
  • 通过HttpServletRequest实现;

  • 通过返回字符串实现(forward:);

  • 通过返回 null 或 void 返回实现

    @Controller
    @RequestMapping("/demo")
    public class DemoController {
        @GetMapping("/demo4")
        public Object demo4() {
            System.out.println("DemoController.demo4");
            return null;
        }
    
        @GetMapping("/demo3")
        public void demo3() {
            System.out.println("DemoController.demo3");
        }
    
        @GetMapping("/demo2")
        public String demo2() {
            System.out.println("DemoController.demo2");
            // /表示项目根路径
            return "forward:/demo/demo1";
        }
    
        @GetMapping("/demo1")
        public void demo1(HttpServletRequest req, HttpServletResponse resp) throws Exception {
            System.out.println("DemoController.demo1");
            req.getRequestDispatcher("/WEB-INF/jsp/demo.jsp").forward(req, resp);
        }
    }
    
8.2.2 响应重定向
  • 通过HttpServletResponse对象实现

  • 通过返回字符串实现(redirect:)

  • 通过返回View对象实现

    @Controller
    @RequestMapping("/demo")
    public class DemoController {
        @GetMapping("/demo3")
        public View demo3(HttpServletRequest req) {
            // /表示服务器根路径
            RedirectView view = new RedirectView(req.getContextPath() + "/demo.jsp");
            return view;
        }
    
        @GetMapping("/demo2")
        public String demo2() {
            System.out.println("DemoController.demo2");
            // /表示项目根路径
            return "redirect:/demo.jsp";
        }
    
        @GetMapping("/demo1")
        public void demo1(HttpServletRequest req, HttpServletResponse resp) throws Exception {
            System.out.println("DemoController.demo1");
            // /表示服务器根路径
            resp.sendRedirect(req.getContextPath() + "/demo.jsp");
        }
    }
    

9、文件上传

9.1、文件上传的前提准备
  • 需要导包: commons-fileupload.jar, commons-io.jar;
  • 需要提供上传文件的表单域: <input type=”file”name=”” />;
  • 表单的提交方式必须是post方式;
  • 表单的enctype属性必须是multipart/form-data
9.2、使用 SpringMVC 进行文件上传

除了上述要求以外, 需要配置文件上传解析器(多部件解析器). 如果配置了多部件解析器, 那么, 在控制器方法中, 就可以通过MultipartFile对象来接收到上传的文件.

<!--多部件解析器, 文件上传, 底层依赖commons-fileupload.jar-->
<!--id必须是multipartResolver, 别的不可以,是无效的-->
<bean id="multipartResolver" 		        class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>
@Controller
public class DemoController {
    @PostMapping("/upload")
    public String upload(MultipartFile photo, String username, HttpServletRequest req) throws Exception {
        /*System.out.println("isEmpty: " + photo.isEmpty());
        System.out.println("originalFilename: " + photo.getOriginalFilename());
        System.out.println("表单域的name属性: " + photo.getName());
        System.out.println("文件的MIME类型: " + photo.getContentType());
        System.out.println("文件的大小: " + photo.getSize());*/
        // 定位存储路径
        File dir = new File(req.getServletContext().getRealPath("/upload"));
        // 没有就创建
        if(!dir.exists()) {
            dir.mkdirs();
        }
        // 重新生成文件的名称: 时间戳, uuid
        String oname = photo.getOriginalFilename();
        String name = UUID.randomUUID().toString() +
                oname.substring(oname.lastIndexOf("."));
        // 定位文件
        File file = new File(dir, name);
        // 完成文件的上传
        photo.transferTo(file);
        return "forward:/index.jsp";
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值