Spring MVC 学习笔记

Spring MVC 开发流程(重要)

轻量级Web MVC框架,基于Spring IoC容器运行,所有对象被IoC管理

  • C > Controller控制器 (Servlet) (核心)(作用:处理请求,产生响应)
  • M > Model 模型(业务逻辑Service)
  • V > View试图(Web)

Spring 官网: https://spring.io/
Spring MVC 文档:https://docs.spring.io/spring-framework/docs/current/reference/html/web.html

Spring MVC 环境配置步骤:

  1. Maven依赖
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.14.RELEASE</version>
  1. web.xml配置DispatcherServlet(核心)
<?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>springmvc</servlet-name>
        <!--        DispatchServlet是spring-mvc最核心的对象,-->
        <!--        用于拦截http请求,并根据请求的URL调用与值对应的Controller方法,-->
        <!--        来完成Http请求的处理-->
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
        <!--        并初始化DispatcherServlet-->
        <!--        在Web应用启动时自动加载Spring IOC容器-->
        <load-on-startup>0</load-on-startup>
    </servlet>
    <!--映射-->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <!--        "/"代表拦截所有请求-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>
  1. 配置applicationContext的MVC标记
<?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:mvc="http://www.springframework.org/schema/mvc"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       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标签作用-->
    <!--    在Spring IOC初始化过程中,自动创建并管理com.example.firstspringmvc.springmvc及子包中-->
    <!--    拥有以下注解的对象-->
    <!--    @Repository-->
    <!--    @Servoce-->
    <!--    @Controller-->
    <!--    @Component-->
    <context:component-scan base-package="com.example.firstspringmvc.springmvc"></context:component-scan>
    <!--    请用Spring MVC注解开发-->
    <mvc:annotation-driven/>
    <!--    将图片/JS/CSS等静态资源排除在外-->
    <mvc:default-servlet-handler/>
</beans>
  1. 开发Controller控制器
    创捷控制器类,并用@Controller进行注解

接收Web数据(重要)

HTML这边不写了,需要接收的数据名有name, course, purpose(复选内容)

使用数组来接受请求

@Controller
public class formController {
//    使用数组来接收数据
//    @RequestParam(value = "n", defaultValue = "ALAN"String name 默认值为name=ALAN
    @PostMapping("/apply")
    @ResponseBody
    public String apply(@RequestParam(value = "n", defaultValue = "ALAN") String name, String course, Integer[] purpose) {
        System.out.println(name);
        System.out.println(course);
        for (Integer p : purpose) {
            System.out.println(p);
        }
        return "SUCCESS";
    }

使用List接收请求时,将Integer[] 改为List >>>推荐

 //使用List来接收数据
    @PostMapping("/apply")
    @ResponseBody
    public String apply(String name, String course, @RequestParam List<Integer> purpose) {
        System.out.println(name);
        System.out.println(course);
        for (Integer p : purpose) {
            System.out.println(p);
        }
        return "SUCCESS";
    }

使用对象接收请求 >>>推荐

 //使用实体类来接收数据
    @PostMapping("/apply")
    @ResponseBody
    public String apply(Form form) {
        System.out.println(form.getName());
        System.out.println(form.getCourse());
        for (Integer p : form.getPurpose()) {
            System.out.println(p);
        }
        return "SUCCESS";
    }

使用Map接收请求,Key值是数据的name, Value是数据的值
需要注意Map不能接收复合数据

响应输出结果

  • @ResponseBody
    => 直接产品响应体的数据,过程不涉及视图
    => 可以生成标准字符串/JSON/XML等格式数据
    => 会被StringHttpMessageConverter所影响

  • ModelAndView“模型(数据)和视图(界面)”对象 ====用于动态数据
    => 利用模板引擎渲染输出
    => 可将包含数据的对象与模板进行绑定
    => SpringMVC默认的View是JSP,也可以配置其它模板引擎
    => mav.addObject()方法设置的属性默认存放在当前请求中(使用重定向时,原本放在请求中的数据会丢失)
    => ModelAndView默认使用请求转发(forward)
    请求转发:将当前的请求,直接转发给view.jsp,所以访问地址不会发生改变
    => 页面重定向使用 new ModelAndView(“redirect:/index.jsp”)
    使用重定向后,由于是系统通知发送新的请求,访问地址会发生改变
    应用:注册后跳转到首页,关联性不大 可以使用重定向

ModelAndView 快速上手

//ModelAndView练习模拟返回动态数据
    @GetMapping("/view")
    public ModelAndView showView(Integer userId) {
//      方法一
//      ModelAndView mav = new ModelAndView("/view.jsp");
//      方法二
        ModelAndView mav = new ModelAndView();
        // 没有"/"相对路径,有"/"绝对路径
        mav.setViewName("/view.jsp");
        User user = new User();
        if (userId == 1) {
            user.setUsername("Jack");
        } else if (userId == 2) {
            user.setUsername("Kate");
        }
        mav.addObject("u", user);
        return mav;
    }
<%--	创建view.jsp文件,使用EL表达式返回动态数据--%>
<body>
    <h1>I'm view page</h1>
    <hr>
<%--    利用EL表达式--%>
    <h2>Username:${u.username}</h2>
</body>

利用String与ModelMap代替ModelAndView对象

    //String与ModelMap
    //Controller方法放回String的情况
    //1. 方法被@ResponseBody描述,SpringMVC直接响应String字符转本手
    //2. 方法不存在@ResponseBody,则SpringMVC处理String指代的视图
    @GetMapping("/gg")
    public String showView(Integer userId, ModelMap modelMap) {
        String view = "/view.jsp";
        User user = new User();
        if (userId == 1) {
            user.setUsername("Jack");
        } else if (userId == 2) {
            user.setUsername("Kate");
        }
        modelMap.addAttribute("u",user);
        return view;
    }

URL Mapping(重要)

@PostMapping 接收Post请求
@GetMapping 接收Get请求
@RequestMapping 通用 - 忽略get/post

中文乱码问题(重要)

Web应用的中文乱码,Tomcat默认使用ISO-8859-1(西欧字符集),需要将其转换为UTF-8。Controller中的请求和响应都需要转换为UTF-8。

三个步骤:

  1. Get请求乱码 ⇒ Tomcat中的servlet.xml增加URIEncoding
    Tomcat 8.0之后不需要增加
    <Connector port="80" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" 
			   URIEncoding="UTF-8"/>
  1. Post请求乱码 ⇒ web.xml增加CharacterEncodingFilter
    <filter>
        <filter-name>characterFilter</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>characterFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
  1. Response响应乱码 ⇒ Spring applicationContext.xml配置StringHttpMessageConverter(消息转换器)
<mvc:annotation-driven conversion-service="conversionService">
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <!--response.setContextType("text/html:charset=utf-8")-->
                        <value>text/html;charset=utf-8</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

整合Freemarker

三个步骤:

  1. 添加Maven依赖
  2. 启用Freemarker模板引擎
  3. 配置Freemarker参数
<!--pox.xml添加依赖-->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.29</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>5.2.13.RELEASE</version>
        </dependency>
<!--	在applicationContext.xml中创建-->
<!--    启用Freemarker-->
    <bean id="ViewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
        <property name="contentType" value="text/html;charset=UTF-8"/>
        <property name="suffix" value=".ftl"/>
    </bean>
<!--    Freemarker配置-->
    <bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
        <property name="templateLoaderPath" value="/WEB-INF/ftl"/>
        <property name="freemarkerSettings">
            <props>
                <prop key="defaultEncoding">UTF-8</prop>
            </props>
        </property>
    </bean>
//创建一个Controller测试一下
@Controller
@RequestMapping("/fm")
public class FreemarkerController {
    @GetMapping("/test")
    public ModelAndView showTest(){
        ModelAndView mav = new ModelAndView("/test");
        User user = new User();
        user.setUsername("Jack");
        mav.addObject("u", user);
        return mav;
    }
}
创建test.ftl返回数据
<#--利用Freemarker返回数据-->
<h1>${u.username}</h1>

拦截器Interceptor(理解)

Interceptor底层依赖于Spring AOP,开发流程:

  1. Maven一再servlet-api
<dependency>
	<groupId>javax.servlet</groupId>
	<artifactId>javax.servlet-api</artifactId>
	<version>4.0.1</version>
	<scope>provided</scope>
</dependency>
  1. 实现HandlerInterceptor接口
    然后实现三个方法:
    preHandle
    postHandle
    afterCompletion
  2. applicationContext配置过滤地址
<mvc:interceptors>
	<mvc:interceptor>
		<mvc:mapping path="/**"/>
		<mvc:exclude-mapping path="/**.ico"/>
		<mvc:exclude-mapping path="/**.jpg"/>
		<mvc:exclude-mapping path="/**.gif"/>
		<mvc:exclude-mapping path="/**.js"/>
		<mvc:exclude-mapping path="/**.css"/>
		<bean class="com.example.interceptor.MyInterceptor"/>
	</mvc:interceptor>
</mvc:interceptros>

Restful(重要)

REST和Restfull

  • REST 表现层状态转换,资源在网络中以某种表现形式进行状态转移
  • RESTful是基于REST理念的一套开发风格,是具体的开发规则

RESTful开发规范

  • 使用URL作为用户交互入口
  • 明确的语义规范(GET/POST/PUT/DELETE)
  • 只返回数据(JSON/XML),不包含任何展现 >> 优先使用JSON

RESTful命名要求
URI 必须要有语义,必须使用名词,扁平化不超两级,名词区分单复数
GET /articles?au=jack

简单请求:GET/POST 直接发给服务器
非简单请求:PUT/DELETE 先发预检请求

<!--非简单请求需要增加过滤器 web.xml-->
    <filter>
        <filter-name>formContentFilter</filter-name>
        <filter-class>org.springframework.web.filter.FormContentFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>formContentFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

RESTful 控制器

//使用@RestController避免每个方法增加@ResponseBody
@RestController
@RequestMapping("/restful")
public class RestfulController {
    @GetMapping("/request")
//    @ResponseBody
    public String doGetRequest() {
        return "{\"message\":\"返回查询结果\"}";
    }

    // POST /artical/1
    // POST /restful/request/100 路径遍历,通常指向具体的ID号
    @PostMapping("/request/{rid}")
//    @ResponseBody
    public String doPostRequest(@PathVariable("rid") Integer requestId, Person person) {
        System.out.println(person.getName() + ":" + person.getAge());
        return "{\"message\":\"数据新建成功\",\"id\":" + requestId + "}";
    }

    @PutMapping("/request")
//    @ResponseBody
    public String doPutRequest(Person person) {
        System.out.println(person.getName() + ":" + person.getAge());
        return "{\"message\":\"数据更新成功\"}";
    }

    @DeleteMapping("/request")
//    @ResponseBody
    public String doDeleteRequest() {
        return "{\"message\":\"数据删除成功\"}";
    }
}

创建测试HTML,利用AJAX接收数据

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>RESTful_Test</title>
    <script src="jquery-3.5.1.min.js"></script>
    <script>
        $(function () {
            $("#btnGet").click(function () {
                $.ajax({
                    url: "/restful/request",
                    type: "get",
                    dataType: "json",
                    success: function (json) {
                        $("#message").text(json.message);
                    }
                })
            })
        })
    </script>
    <script>
        $(function () {
            $("#btnPost").click(function () {
                $.ajax({
                    url: "/restful/request/100",
                    type: "post",
                    data:"name=jack&age=23",
                    dataType: "json",
                    success: function (json) {
                        $("#message").text(json.message+":"+json.id);
                    }
                })
            })
        })
    </script>
    <script>
        $(function () {
            $("#btnDelete").click(function () {
                $.ajax({
                    url: "/restful/request",
                    type: "delete",
                    dataType: "json",
                    success: function (json) {
                        $("#message").text(json.message);
                    }
                })
            })
        })
    </script>
    <script>
        $(function () {
            $("#btnPut").click(function () {
                $.ajax({
                    url: "/restful/request",
                    type: "put",
                    data:"name=jack&age=23",
                    dataType: "json",
                    success: function (json) {
                        $("#message").text(json.message);
                    }
                })
            })
        })
    </script>
</head>
<body>
<input type="button" id="btnGet" value="发送Get请求">
<input type="button" id="btnPost" value="发送Post请求">
<input type="button" id="btnPut" value="发送Put请求">
<input type="button" id="btnDelete" value="发送Delete请求">
<h1 id="message"></h1>
</body>
</html>

Spring MVC 浏览器跨域访问CORS
注解模式:
增加Access-Control,在控制器(Controller增加配置项目)

//maxAge=3600 在缓存中存放一个小时,在这边时间内可以直接访问
@CrossOrigin(origins=("https://xxxxx","https://允许多个域名"),maxAge=3600)

xml配置模式:
在applicationContext.xml

<mvc:cors>
	<mvc:mapping path="/restful/**" allowed-origins="https://xxxxxx","https://允许多个域名",max-age="3600"/>
</mvc:cors>

JSON序列化(重要)

  1. 添加Maven依赖
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.12.3</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.3</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.12.3</version>
        </dependency>
  1. 只需要返回单个对象和数组
@RestController
@RequestMapping("/restful")
public class RestfulController {
    @GetMapping("/person")
    public Person findByPersonId(Integer id) {
        Person person = new Person();
        if (id == 1) {
            person.setName("jack");
            person.setAge(30);
        } else if (id == 2) {
            person.setName("Kate");
            person.setAge(30);
        }
        return person;
    }
     @GetMapping("/persons")
    public List<Person> findPersons(){
        List list = new ArrayList();
        Person p1 = new Person();
        p1.setName("jack");
        p1.setAge(30);
        Person p2 = new Person();
        p2.setName("Kate");
        p2.setAge(30);
        list.add(p1);
        list.add(p2);
        return list;
    }
  1. HTML利用AJAX获取JSON数据
<script>
$(function () {
            $("#btnPersons").click(function () {
                $.ajax({
                    url: "/restful/persons",
                    type: "get",
                    dataType: "json",
                    success: function (json) {
                        console.info(json)
                        for (var i = 0; i < json.length; i++) {
                            var p = json[i];
                            $("#divPerson").append("<h2>" + p.name + "-" + p.age + "</h2>")
                        }
                    }
                })
            })
        })
</script>
<body>
<!--获取JSON数据-->
<input type="button" id="btnPersons" value="查询所有人员"/>
<div id="divPerson"></div>
</body>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值