SpringMVC学习笔记

这里是javaWeb工程

1.Maven依赖

<?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-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>

        <!--自定义标签中写上spring的版本,下面可以用${srping-version}来引用}-->
        <spring-version>5.3.16</spring-version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring-version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring-version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring-version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring-version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring-version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring-version}</version>
        </dependency>

        <!--spring-mvc的JSON转换工具依赖-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.13.1</version>
        </dependency>

    </dependencies>

</project>

2.创建SpringMVC配置文件

在resources下创建spring-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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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/tx http://www.springframework.org/schema/tx/spring-tx.xsd
             http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
             http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
             http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">


    <!--开启注解配置-->
    <context:component-scan base-package="xin.students"/>

    <!--开启注Aspect生成代理对象-->
    <aop:aspectj-autoproxy/>

    <!--开启mvc注解配置-->
    <mvc:annotation-driven/>
</beans>

3.在web.xml中配置SpringMVC的前端控制器

SpringMVC气功了一个名为DispatcherServlet的类[SpringMVC前端控制器],用于拦截用户请求交由SpringMVC处理。

<?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">

    <!--服务器启动时就会实例化springMVC的前端控制器,同时会加载spring的配置文件-->
    <servlet>
        <servlet-name>SpringMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

        <!--配置springMVC的初始化文件-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-servlet.xml</param-value>
        </init-param>

        <!--初始化的等级,正整数数字越小越高-->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>SpringMVC</servlet-name>

        <!--拦截所有请求-->
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

</web-app>

SpringMVC的使用

在SpringMVC中,我们不用Servlet,而是把交给接收用户和请求处理用户请求的类:Controlelr(控制器)。

创建控制器

1.创建一个名为xin.students.controllercs的包(包需要在Spring注解扫描的范围内)。

2.在xin.students.controllercs包下创建一个类(这个类什么也不需要继承和实现),这里创建的是

BookController类。

3.在BookController类上添加@Controller注解声明此类为SpringMVC的控制器。

4.在BookController类上添加@RequestMapping("/book")声明此控制器的请求路径,斜杠可以有也可以没有,@RequestMapping("url")中的参数是url,类似于@WebServlet("/url")的作用。

package xin.students.controllers;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/book")
public class BookController {
}

在控制器类中定义处理请求的方法

在一个控制器类中可以定义多个方法处理不同的请求。

在每个方法上添加@RequestMapping("/url")用于声明当前方法请求的url。

如果类上面不加RequestMapping("/book"),则访问时直接用方法上面的url。

package xin.students.controllers;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/book")     
public class BookController {
    @RequestMapping("/add")  //方法访问路径location/book/add
    public void add(){}

    @RequestMapping("/list") //方法访问路径location/book/list
    public void list(){}
}

前端提交数据到控制器

创建前端页面

在webapp下创建book-add.jsp,表单的action属性设置控制器类的url和队形方法的url的组合

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <h3>添加图书</h3>
    <form action="/book/add" method="post">
        <p>图书名称:<input type="text" name="name"/></p>
        <p>图书作者:<input type="text" name="author"/></p>
        <p>图书价格:<input type="text" name="price"/></p>
        <p>图书名称:<input type="submit" value="提交"/></p>
    </form>
</body>
</html>

静态资源配置

静态资源:就是项目中的HTML,CSS,JS,图片,字体等。

静态资源放行配置

在springMVC配置文件,添加如下资源放行的配置,放行css文件夹下所有静态资源文件[webapp文件夹为根目录]。

<mvc:resources mapping="/css/**" location="/css/"/>

拦截器<url-pattern>/</url-pattern>"/*"和"/"的区别

"/*" 拦截所有的http请求,包括.jsp的请求,都会作为控制器类的请求路径类处理。
"/"  拦截所有的HTTP请求,但不包括.jsp的请求[jsp中引用的css文件等,也会被拦截],但是不会放         行静态资源请求(http/css/js/图片)。

前端页面提交数据

http传参的三种方式:请求头,请求行,请求体。

请求行传值:表单提交,URL提交,$.ajax请求的url传值,$.post()和$.get()中的传值。

请求头传值:ajax封装请求头数据。

$.ajax({
    ...
    headers:{}
    ...
})

请求体传值:ajax封装请求体数据

$.ajax({
    ...
    data:{}
    ...
})

1、表单提交[请求行传值]:输入框余姚提供name属性springMVC控制器是通过name属性取值的。

2、URL提交[请求行传值]:<a href="book/add?bookName=java">。

3、AJAX提交:请求行,请求头,请求体都可以传值。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <h3>添加图书</h3>
    <form action="/book/add" method="post">
        <p>图书名称:<input type="text" name="name"/></p>
        <p>图书作者:<input type="text" name="author"/></p>
        <p>图书价格:<input type="text" name="price"/></p>
        <p>图书名称:<input type="submit" value="提交"/></p>
    </form>
    
    <h3>超链接提交</h3>
    <a href="${pageContext.request.contextPath}/book/add?name=java"></a>
    
    <h3>超链接提交</h3>
    <input type="button" value="ajax提交" id="btn1">
    <script type="text/javascript" src="js/jquery-3.6.0.js"></script>
    <script type="text/javascript">
        $(function () {
            $("#btn1").click(function () {
    
                let obj = {};
                obj.bookName = "java";
                obj.bookAothor = "张三";
                obj.bookPrice = 3.33;
                
                $.ajax({
                    url: "book/add",
                    type: "post",
                    headers: {};
                    contentType: "application/json",   //因为下面传的是对象,所以这里声明一下传json
                    data: obj;
                    success: function (result) {
                        console.log(result);
                    }
                })
            });
        });
    </script>
</body>
</html>

接收请求行传递的参数

@RequestParma注解用于接收请求行提交的数据,参数的name属性,必须写在方法的参数前。

如果方法参数前加了@RequestParma注解,前端传过来的数据中就必须要有对应name的数据。

否则会报下面的错误

org.springframework.web.servlet.DispatcherServlet.noHandlerFoundNo 
    mapping for POST /book/book/add

org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.logExceptionResolv        
    ed [org.springframework.web.bind.MissingServletRequestParameterException: 
    Required request parameter '没有对应上的@RequestParam("xxx")中xxx的名称' for method         
    parameter type String is not present]

注:前端传过来几个值,方法就写几个参数,然后把@RequestParma("name")写在参数前去获取前端请求行传递过来的值,如果方法参数的名称与请求行中的name属性一直,可以不写@RequestParma("name")【只有请求行参数与传过来的name名称相同,参数前才可以不写注解】,什么注解都不写的话,方法的参数默认接收请求行的数据。

前端使用请求行的方式提交数据

<form action="/book/add" method="post">
    <p>图书名称:<input type="text" name="name"/></p>
    <p>图书作者:<input type="text" name="author"/></p>
    <p>图书价格:<input type="text" name="price"/></p>
    <p>图书名称:<input type="submit" value="提交"/></p>
</form>
控制器接收请求行数据
如果前端发过来的数据与方法参数中的名称不一样,需要写@RequestParam("name")来指定对应参数

@Controller
@RequestMapping("/book")
public class BookController {
    @RequestMapping("/add")  //方法访问路径location/book/add
    public void add(@RequestParam("name") String n,
                    @RequestParam("author") String a, 
                    @RequestParam("price") Double p) {
        System.out.println("book---add");
        System.out.println(n + "    " + a + "     " + p);
    }
}
控制器接收请求行数据
如果前端发过来的数据与方法参数中的名称一样,可以不写@RequestMapping("name")来指定对应参数

@Controller
@RequestMapping("/book")
public class BookController {
    @RequestMapping("/add")  //方法访问路径location/book/add
    public void add(String name, String author, Double price) {
        System.out.println("book---add");
        System.out.println(name + "    " + author + "     " + price);
    }

    @RequestMapping("/list") //方法访问路径location/book/list
    public void list() {
        System.out.println("book---list");
    }
}

如果前端提交的是表单,表单中的key与类中的属性一样,可以用类直接接收。

<form action="/test/addBook" method="post">
    <p>图书名称:<input type="text" name="name"/></p>
    <p>图书作者:<input type="text" name="author"/></p>
    <p>图书价格:<input type="text" name="price"/></p>
    <p>图书时间:<input type="text" name="date"/></p>
    <p>图书名称:<input type="submit" value="提交"/></p>
</form>
@Controller
@RequestMapping("/test")
public class TestController {
    @RequestMapping("/addBook")
    public String addBook(Book book){
        return "tips.jsp";
    }
}

接收请求头传递的参数

@RequestHeader("key")用于接收请求头提交的数据,必须写在参数前。

@接收请求头数据时RequestHeader("key")必须要写。

前端使用请求头的方式传递数据

$("#btn1").click(function () {
    $.ajax({
        url: "book/list",
        type: "post",
        headers: {
            xin: "heihei"
        }
    })
});

控制器接收请求头数据

@Controller
@RequestMapping("/book")
public class BookController {
    //接收请求头的数据,只能接收ajax的请求头数据
    @RequestMapping("/list") //方法访问路径location/book/list
    public void list(@ @RequestHeader("xin") String xin) {
        System.out.println("book---list");
        System.out.println(xin);
    }
}

接收请求体传递的参数

@RequestBody把前端传过来的JSON转为对象,该注解必须写在方法参数前。

@RequestBody只能接收前端对象转成JSON后的数据,这个注解依赖于jackson包。

使用请求体的方式传递参数,该参数必须是对象的JSON格式
let obj = {};
obj.name = "java";
obj.author = "张三";
obj.price = 3.33;

$.ajax({
    url: "book/update",
    type: "post",
    contentType: "application/json",   //因为下面传的是对象,所以这里声明一下传json
    //spring-mvc接收请求体数据时必须是对象的JSON格式[contentType必须设置为"application/json"],
    data: JSON.stringify(obj),         //JSON.stringify(xxxobj)把xxx对象转为JSON格式
    success: function (result) {
        console.log(result);
    }
})
接收前端请求体中的数据,前端传过来的数据必须是对应的JSON格式

@Controller
@RequestMapping("/book")
public class BookController {
    //接收请求体的数据
    @RequestMapping("/update")
    public void update(@RequestBody Book book) {
        System.out.println(book);
    }
}
Book类的代码
public class Book {
    private String name;
    private String author;
    private Double price;

    public String getName() {
        return name;
    }

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

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", author='" + author + '\'' +
                ", price=" + price +
                '}';
    }
}

控制器相应前端请求

控制器响应同步请求

同步请求::form,超链接。

注:同步请求一般会跳转到其它页面。

处理同步请求的方法的返回类型定义为String或ModelAndView,以实现页面的跳转。

方法返回类型类为String

转发:浏览器的URL为接口地址,如:localhost/book/add。

重定向:浏览器的URL为跳转到的地址,如:"localhost/tips.jsp"。

返回值为String,返回路径为[如:"/tips.jsp"]为转发。

返回值为String,返回路径为[如:"redirect:/book/add"]为重定向。

返回值为String时:处理完请求后让前端自动跳转到函数返回值写的路径。
例如:这里处理完请求后让前端跳转到“/tips.jsp“页面。

@Controller
@RequestMapping("/book")
public class BookController {

    @RequestMapping("/add")
    public String add(@RequestParam("name") String name,
                      @RequestParam("author") String author,
                      @RequestParam("price") Double price) {
        System.out.println("book---add");
        System.out.println(name + "    " + author + "     " + price);

        //return "redirect:/tips.jsp"为重定向
        
        return "/tips.jsp";   //这里为转发
    }
}

方法返回类型类为ModelAndView

返回值为ModelAndView,构造参数为[如:"/tips.jsp"]为转发。

返回值为ModelAndView,构造参数为[如:"redirect:/tips.jsp"]为重定向。

返回值为:ModelAndView与String功能一样,都是让前端跳转到指定页面。
返回值为ModelAndView时:处理完请求后让前端自动跳转到函数返回值写的路径。
例如:这里处理完请求后让前端跳转到“/tips.jsp“页面。
浏览器的地址为:http://localhost/book/add

@Controller
@RequestMapping("/book")
public class BookController {

    @RequestMapping("/add")
    public ModelAndView add(@RequestParam("name") String name,
                            @RequestParam("author") String author,
                            @RequestParam("price") Double price) {
        System.out.println("book---add");
        System.out.println(name + "    " + author + "     " + price);
        
        //ModelAndView modelAndView = new ModelAndView("redirect:/tips.jsp"); //这里为重定向

        ModelAndView modelAndView = new ModelAndView("/tips.jsp");    //这里为转发
        return modelAndView;
    }
}

当方法返回值为String或ModelAndVIew时,如果返回值为null,页面会跳转到访问接口的路径,前端看到的页面是空的。

控制器响应异步请求

异步请求:AJAX请求。

控制器方法的返回类型设置为响应给ajax请求的对象类型。

在控制器方法前添加@ResponseBody注解,将返回的对象转换为JSON响应给AJAX请求。

如果一个类的所有方法都是处理的AJAX请求,那么可以把@ResponseBody添加到类的上面,这样所有的方法都默认处理AJAX请求【加上之后类的所有方法都只能处理AJAX异步处理了】,返回的都是类的JSON数据,所有方法前面都不需要加@ResponseBody注解了。

后端接收前端传过来的对象的JSON,打印后返回一个对象数组的JSON

@Controller
@RequestMapping("/book")
public class BookController {
    
    //接收请求体的数据,并把Books数组转为JSON后转发回去
    @RequestMapping("/update")
    @ResponseBody
    public List<Book> update(@RequestBody Book book) {
        System.out.println("book----update");
        System.out.println(book);
        List<Book> books = new ArrayList<>();
        books.add(new Book());
        books.add(new Book());
        return books;
    }
}
后端传到前端对象的JSON格式,再从后端接收JSON格式的数据并打印出来

let obj = {};
obj.name = "java";
obj.author = "张三";
obj.price = 3.33;

$.ajax({
    url: "book/update",
    type: "post",
    contentType: "application/json",
    dataType: "json",    //接收到返回值为的JSON
    data: JSON.stringify(obj),
    success: function (result) {
        console.log(result);
    }
})

控制器相应同步请求的数据传递

对于同步请求的转发响应,我们可以传递参数到转发的页面。

同步提交必须要转发,不转发不能传值。

返回类型为String:

        在控制器方法中定义一个Model类型的参数。

        在return页面之前,向model中添加键值对,添加的键值对就会传递到转发的页面。

接收前端同步请求后,让前端跳转页面,并向跳转的页面传递值

@Controller
@RequestMapping("/book")
public class BookController {
    @RequestMapping("/add2")
    public String addBook2(@RequestParam("name") String name,
                           @RequestParam("author") String author,
                           @RequestParam("price") Double price,
                           Model model) {
        System.out.println("book---add");
        System.out.println(name + "    " + author + "     " + price);

        model.addAttribute("xin", "123");
        model.addAttribute("book", new Book());

        return "/tips.jsp";
    }
}
tips.jsp页面代码,这里用EL表达式接受,别问我怎么用HTML接收,我也不知道。。。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>tips</title>
</head>
<body>
    <h1 style="color: red">hello world</h1>
    <hr/>
    ${xin}
    <hr/>
    ${book}
</body>
</html>

返回类型为ModelAndView:

处理完前端请求后把要返回的地址写到ModelAndView中,
还可以把键对值写到ModelAndView中,把值传到新的页面中,前端接收方式与上一个一样

@Controller
@RequestMapping("/book")
public class BookController {
    @RequestMapping("/add3")
    public ModelAndView addBook3(@RequestParam("name") String name,
                                 @RequestParam("author") String author,
                                 @RequestParam("price") Double price) {
        System.out.println("book---add");
        System.out.println(name + "    " + author + "     " + price);

        ModelAndView modelAndView = new ModelAndView("/tips.jsp");
        modelAndView.addObject("xin", "heihei");
        modelAndView.addObject("book", new Book());
        return modelAndView;
    }
}

解决中文乱码问题

乱码出现的原因:前端的编码,传输中的编码,后端的编码不一致造成的。

前端编码

JSP页面

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8"%>

HTML页面

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8"></head>
<body></body>
</html>

服务器编码

这里用的是Tomcat。

设置Tomcat的编码方式

在Tomcat/conf/server.xml中大概在69行,添加"URIEncoding="UTF-8",设置默认编码为UTF-8。

 设置SpringMVC的编码方式

在web.xml中配置SpringMVC编码过滤器的编码方式。

在<web-app><web-app/>标签中添加。

<!--把SpringMVC的过滤器加载进来-->
<filter>
    <filter-name>EncodingFilter</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>

    <!--开启强制编码-->
    <init-param>
        <param-name>forceEncoding</param-name>
        <param-value>true</param-value>
    </init-param>

</filter>
<filter-mapping>
    <filter-name>EncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

日期格式处理

如果前端需要输入日期数据,在控制器中转换成Date对象,SpringMVC要求前端输入的日期格式必须要"yyyy/MM/dd"。

如果甲方要求日期格式必须是指定的格式,而这个指定格式SpringMVC不接受,那么就处理一下。

创建自定义类型转换器

public class MyDateConverter implements Converter<String, Date> {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
    
    @Override
    public Date convert(String s) {
        Date date= null;
        try {
            date = sdf.parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
}

配置自定义类型转换器

在SpringMVC的配置文件中配置。

<!--开启mvc注解配置,并配置自定义日期转换器-->
<mvc:annotation-driven conversion-service="converterFactory"/>


<!--自定义类型转换器-->
<bean id="converterFactory" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="xin.students.controllers.utils.MyDateConverter"/>
        </set>
    </property>
</bean>

扩展

在@Controller类方法的形参中添加HttpServletResponse或者HttpServletRequest,SpringMVC是会自动注入的。

@Controller
@RequestMapping("/book")
public class BookController {
    @RequestMapping("/download")
    //HttpServletResponse response, HttpServletRequest request会被String自动注入
    public void download(String fileName,HttpServletResponse response, HttpServletRequest request){

    }
}

扩展

@Controller与ResponseBody可以合写为@RestController

@RestController要与@Controller一起使用

@RestController
@RequestMapping("/books")
public class MsgServiceImpl {
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值