欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

springmvc笔记回顾——持续更新

程序员文章站 2022-09-20 16:28:47
springmvc 概述springmvc定义:是基于spring的一个框架,实际上就是spring的一个模块,专门是做web开发的。理解为servlet的升级。web开发底层是servlet,框架是在servlet基础上面加入一些功能,让开发方便。对比:springmvc:就是一个spring。spring是容器,ioc能够管理对象,使用标签,@Component,@Repository,@Service,@Controller标签。 springmvc:能够创建...

springmvc 概述



springmvc定义:是基于spring的一个框架,实际上就是spring的一个模块,专门是做web开发的。理解为servlet的升级。web开发底层是servlet,框架是在servlet基础上面加入一些功能,让开发方便。

对比:
springmvc:就是一个spring。spring是容器,ioc能够管理对象,
使用<bean>标签,@Component,@Repository,@Service,@Controller标签。
    
springmvc:能够创建对象,放入到容器中(springmvc容器),spring容器中放的是控制器对象。

我们要做的事 使用@Controller创建控制器对象 ,把对象放入到springmvc容器中,把创建的对象作为控制器使用。这个控制器对象能够接收用户的请求,显示处理结果,就当作是一个servlet使用。

使用@Controller注解创建的是一个普通的对象 ,不是servlet,springmvc赋予了控制器对象一些额外的功能。

web开发底层是servlet,springmvc中有一个对象是servlet:DispatcherServlet(*调度器)
DispatcherServlet:负责接收用户的所有请求,用户把请求给了DispatcherServlet,之后DispatcherServlet把请求转发给我们的Controller对象,最后Controller对象处理请求。




开发步骤

index.jsp —> DispatcherServlet(*调度器,类似servlet) ----> 转发,分配给Controller对象(@Controller 注解创建的对象)

需求:用户在页面发起一个请求,请求交给springmvc的控制器对象,并显示请求的处理结果

实现步骤:
1	新建web maven工程
2	加入依赖,spring-webmvc依赖,间接把spring的依赖加入到项目中,jsp,servlet依赖

3	重点:在web.xml中注册springmvc框架的核心对象 DispatcherServlet
	1)DispatcherServlet叫做:*调度器,是一个servlet,他的父类继承 HttpServlet
	2)DispatcherServlet也叫做:前端控制器(from controller)
	3)DispatcherServlet:负责接收用户提交的请求,调用其他控制器对象,并把请求的处理结果显示给用户
	
4	创建一个发起请求的页面 index.jsp
5	创建控制器类
	1)在类的上面加入@Controller注解,创建对象,并放到springmvc容器中
	2) 在类中的方法上面加入@RequestMapping注解
    
6	创建一个作为结果的jsp,显示请求的处理结果。
7	创建springmvc的配置文件(和spring的配置文件一样)
	1)声明组件扫描器,指定@Controller注解所在的包名
	2)声明视图解析器,帮助处理视图

springmvc 开发流程:

1	发起some.do请求
2	tomcat (web.xml	从url-pattern知道 *.do 的请求给DispatcherServlet)
3	DispatcherServlet(根据spring.xml配置知道some.dodoSome()方法)
4	DispatcherServlet把some.do转发给MyController.doSome()方法
5	框架执行doSome()把得到的ModelAndView进行处理,转发到show.jsp	

简化流程:

some.do -> DispatcherServlet -> MyController

流程如图:
springmvc笔记回顾——持续更新



创建好web项目后,在pom.xml中加入servlet和springmvc依赖

<!--servlet-->
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  <version>3.1.0</version>
  <scope>provided</scope>
</dependency>

<!--spring mvc-->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>5.2.5.RELEASE</version>
</dependency>

发送some.do请求的页面 index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <p>第一个springmvc项目</p>
    <p><a href="some.do">发起some.do请求</a></p>
</body>
</html>

核心配置文件 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">

        <!--声明:注册springmvc的核心对象DispatcherServlet

        需要在tomcat服务器启动后,创建DispatcherServlet对象实例

        为什么要创建DispatcherServlet对象的实例呢?
        因为在DispatcherServlet创建过程中,会同时创建springmvc容器对象,
        读取springmvc的配置文件,把这个配置文件中的对象都配置好,
        当用户发起请求时就可以直接使用对象了。

        servlet的初始化会执行init()方法,DispatcherServlet在init()中{
            //创建容器,读取配置文件
            webApplicationContext ctx = new ClassPathXmlApplicationContext("springmvc.xml");
            //把容器对象放入到ServletContext中
            getServletContext().setAttribute(key,ctx);
         }
    -->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

        <!--自定义springmvc读取文件的位置-->
        <init-param>
            <!--springmvc配置文件的位置属性-->
            <param-name>contextConfigLocation</param-name>
            <!--指定自定义文件的位置-->
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>

        <!--表示在tomcat启动后,创建servlet对象
            数字表示启动后创建对象的顺序,数值越小,tomcat创建对象越早,要求大于等于0的整数
        -->
        <load-on-startup>1</load-on-startup>

    </servlet>

        <servlet-mapping>
            <servlet-name>springmvc</servlet-name>
            <!--
                使用框架的时候,url-pattern可以使用两种值
                1.使用扩展名方式,语法 *.xxxx , xxxx时自定义扩展名。常用的方式 *.do, *.action, *.mvc等等
                    http://localhost:8080/myweb/some.do
                    http://localhost:8080?myweb/other.do
                2.使用斜杠"/"
            -->
            <url-pattern>*.do</url-pattern>
        </servlet-mapping>
</web-app>

tomcat启动,创建DispatcherServlet对象,同时创建springmvc容器对象,读取springmvc配置文件,
这里配置文件的根地址 classpath = springmvc.xml
在spring.xml中声明 组件扫描器视图解析器


springmvc.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: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 https://www.springframework.org/schema/context/spring-context.xsd">

    <!--声明组件扫描器-->
    <context:component-scan base-package="com.zh.controller"/>
    
     <!--声明 springmvc框架中的视图解析器,帮助开发人员设置视图文件的路径-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--前缀:视图文件位置-->
        <property name="prefix" value="/WEB-INF/view/"/>
        <!--后缀:视图文件的扩展名-->
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

创建控制器类 MyController.java

package com.zh.controller;

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

/*
* @Controller:创建处理器对象,对象放在springmvc容器中
*
* 能处理请求的都是控制器(处理器):MyController能处理请求,
*                               叫做后端控制器(back controller)
* */
@Controller
public class MyController {
    /*
    * 处理用户提交的请求,springmvc中是使用方法来处理的。
    * 方法是自定义的,可以有多种返回值,多种参数,方法名称自定义
    * */

    /*
    * 准备使用doSome方法处理some.do请求。
    * @RequestMapping:请求映射,作用是把一个请求地址和一个方法绑定在一起。
    *                  一个请求指定一个方法处理。
    *             属性:1. value是一个String类型,表示请求的uri地址(这里是:some.do)
    *                     value值是唯一的,不能重复
    *             说明:使用@RequestMapping修饰的方法叫做处理器方法或者控制器方法
    *                   可以处理请求,类似servlet中的doGet,doPost
    * */

    /*
    * 返回值 ModelAndView 表示本次请求的处理结果
    *   model:数据,请求处理完后,要显示给用户的数据
    *   view:视图,比如jsp等
    * */
    @RequestMapping(value = "/some.do")
    public ModelAndView doSome(){
        //处理some.do请求,相当于service调用处理完成了
        ModelAndView mv = new ModelAndView();
        //添加数据,框架在请求的最后把数据放入到request作用域
        //request.setAttribute("msg","欢迎使用....");
        mv.addObject("msg","欢迎使用springmvc做web开发");
        mv.addObject("fun","执行的是doSome方法");

        //指定视图,指定视图的完整路径
        //框架对视图执行的forward操作,request.getRequestDispather("/show.jsp").forward(...)
        mv.setViewName("/show.jsp");
        return mv;
    }
    
    
    //在springmvc.xml配置视图解析器后,修改 setViewName()
    @RequestMapping(value = {"/other.do","/second.do"})
    public ModelAndView doOther(){
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg","---------欢迎使用springmvc做web开发----------");
        mv.addObject("fun","执行的是doOther方法");
        
        //当配置了视图解析器后,可以使用逻辑名称(文件名),指定视图
        //框架会使用视图解析器的 前缀 + 逻辑名称 +后缀 组成完整路径
        mv.setViewName("other");
        return mv;
    }
}

对应的 show.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>show.jsp从request作用域获取数据</h3><br/>
    <h3>msg数据:${msg}</h3>
    <h3>fun数据:${fun}</h3>
</body>
</html>




springmvc注解式开发



@RequestMapping 定义请求规则



1 放在类上面使用

/*
* @RequestMapping
* 	value:所有请求的公共部分,叫做模块名称
*   位置:在类的上面
* */

@Controller
@RequestMapping("/user")
//或者@RequestMapping("/test")
public class MyController {

    @RequestMapping(value = "/some.do")
    public ModelAndView doSome(){
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg","欢迎使用springmvc做web开发");
        mv.addObject("fun","执行的是doSome方法");
        mv.setViewName("show");
        return mv;

    }
}

理解为在该方法在 user或者test模块下

springmvc笔记回顾——持续更新


2 method 属性 指定请求方式

@Controller
@RequestMapping("/test")
public class MyController {
    /*
    * @RequestMapping(value = "",method = )
    * 	属性:method 表示请求的方式,它的值是RequestMethod类枚举值
    *
    * 	get请求方式, method = RequestMethod.GET
    * 	post请求方式,method = RequestMethod.POST
    * 
    * */

    //指定some.do用get请求获取
    @RequestMapping(value = "/some.do",method = RequestMethod.GET)
    public ModelAndView doSome(){
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg","欢迎使用springmvc做web开发");
        mv.addObject("fun","执行的是doSome方法");
        mv.setViewName("show");
        return mv;
    }

    //指定other.do 用post请求获取
    @RequestMapping(value = "/other.do",method = RequestMethod.POST)
    public ModelAndView doOther(){
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg","---------欢迎使用springmvc做web开发----------");
        mv.addObject("fun","执行的是doOther方法");
        mv.setViewName("other");
        return mv;
    }

对应的index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <p>第一个springmvc项目</p>
    <p><a href="test/some.do">发起some.do的get请求</a></p>
    <br/>

    <form action="test/other.do" method="post">
        <input type="submit" value="post请求other.do">
    </form>

<%--    <p><a href="user/other.do">发起other.do请求</a></p>--%>
</body>
</html>


处理器方法的参数



处理器方法可以包含以下四类参数,这些参数会在系统调用时由系统自动赋值,即程序员可以在方法中直接使用。

1	HttpServletRequest		 请求
2	HttpServletResponse		 应答
3	HttpSession				会话
4	请求中所携带的请求参数		

前三类参数使用方式


@Controller
public class MyController {
    @RequestMapping(value = "/some.do")
    public ModelAndView doSome(HttpServletRequest request,
                               HttpServletResponse response,
                               HttpSession session){
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg","欢迎使用springmvc做web开发" + request.getParameter("name"));
        mv.addObject("fun","执行的是doSome方法");
        mv.setViewName("show");
        return mv;
    }

springmvc笔记回顾——持续更新


逐个参数接收

接收用户提交的参数:处理器(控制器)方法的形参名和请求中的参数必须一致

@Controller
public class MyController {
    /*
    * 逐个接收请求参数:
    *   要求:处理器(控制器)方法的形参名和请求中的参数必须一致
    *         同名的请求参数赋值给同名的参数
    *
    * 框架接收请求参数:
    * 1 使用request对象接收请求参数
    *   String strName = request.getParameter("name");
    *   String strAge = request.getParameter("age");
    * 2 springmvc框架通过dispatcherServlet 调用MyController的doSome方法
    *   调用方法时,按名称对应,把接收的参数赋值给形参 doSome(strName,Integer.valueOf(strAge))
    *   框架会提供类型转换的功能,把String转换为 int ,long ,float ,double等
    *
    * */
    @RequestMapping(value = "/some.do")
    public ModelAndView doSome(String name,Integer age){
        System.out.println("dosome方法的,name="+name+", age="+age);

        ModelAndView mv = new ModelAndView();
        mv.addObject("myname",name);
        mv.addObject("myage",age);
        mv.setViewName("show");
        return mv;
    }
}

对应的index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<p>提交参数给Controller</p>

<form action="some.do" method="post">
    姓名:<input type="text" name="name"><br/>
    年龄:<input type="text" name="age"><br/>
    <input type="submit" value="提交参数">
</form>

<%--    <p><a href="user/other.do">发起other.do请求</a></p>--%>
</body>
</html>

注意:在提交请求参数的时候,get请求方式中文没有乱码;post请求方式中文有乱码,需要使用过滤器处理乱码问题。
在web.xml配置过滤器

<!--注册声明过滤器,解决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>

    <!--强制请求对象(HttpServletRequest)使用encoding编码的值-->
    <init-param>
        <param-name>forceRequestEncoding</param-name>
        <param-value>true</param-value>
    </init-param>

    <!--强制应答对象(HttpServletResponse)-->
    <init-param>
        <param-name>forceResponseEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <!--
    /*  : 表示强制所有的请求先通过过滤器处理
    -->
    <url-pattern>/rl-pattern>
</filter-mapping>

springMVC 中的 M-model,V-view,C-controller

springmvc笔记回顾——持续更新



请求参数名和处理器方法的形参名不一样,使用 @RequestParam 注解


首页 index.jsp 的参数名是 iname 和 iage

<p>请求参数名和处理器方法的形参名不一样</p>
<form action="other.do" method="post">
    姓名:<input type="text" name="iname"><br/>
    年龄:<input type="text" name="iage"><br/>
    <input type="submit" value="提交参数">
</form>

控制器方法的 doOther 方法形参为 name 和 age

/*
* 请求参数名和处理器方法的形参名不一样
* @RequestParam:定义在处理器方法的形参前面
*   属性:1. value,请求参数名,可省略
*        2. required,是一个Boolean类型,默认为true,表示必须包含参数
* */
@RequestMapping(value = "/other.do")
public ModelAndView doOther(@RequestParam("iname" ) String name,
                            @RequestParam("iage") Integer age){
    System.out.println("doOther方法的,name="+name+", age="+age);

    ModelAndView mv = new ModelAndView();
    mv.addObject("myname",name);
    mv.addObject("myage",age);
    mv.setViewName("show");
    return mv;
}

但是有一个问题,当不通过首页传入参数,直接加载网址:http://localhost:8080/03_recevieparam/other.do ,将会报400的错,说明请求端输入有问题,如下图

springmvc笔记回顾——持续更新


此时将@RequestParam标签的属性required改为 fslse,不用参数也可以显示show.jsp。
当然我们希望required=true,作为前端限制。

public ModelAndView doOther(@RequestParam(value = "iname",required=false) String name,
                            @RequestParam(value = "iage",required = false) Integer age){

springmvc笔记回顾——持续更新



对象参数接收

将处理器方法的参数定义为一个对象,对象的属性名要求和请求中参数名一致


先在vo包下定义一个Student 类

springmvc笔记回顾——持续更新

//保存请求参数值的普通类
public class Student {
    //属性值要和请求参数值一样
    private String name;
    private int age;
    
    public Student() { System.out.println("---------Student的无参构造方法--------"); }
    public String getName() {return name;}
    public void setName(String name) {System.out.println("setName= "+name);this.name = name;}
    public int getAge() {return age;}
    public void setAge(int age) {System.out.println("setAge= "+age);this.age = age;}
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

主页index.jsp

<p>使用java对象接收参数</p>
<form action="object.do" method="post">
    姓名:<input type="text" name="name"><br/>
    年龄:<input type="text" name="age"><br/>
    <input type="submit" value="提交参数">
</form>

处理器方法

/*
* 处理器方法的形参是java对象,这个对象的属性名要求和请求中参数名一致
* 框架会创建形参的java对象,给属性赋值。请求中的参数是name,框架会调用setName()完成赋值
* */
@RequestMapping(value = "/object.do")
public ModelAndView doObject(Student student){
    System.out.println("doObject方法的,name="+student.getName()+", age="+student.getAge());

    ModelAndView mv = new ModelAndView();
    mv.addObject("myname",student.getName());
    mv.addObject("myage",student.getAge());
    mv.addObject(student);
    mv.setViewName("show");
    return mv;
}

页面结果

springmvc笔记回顾——持续更新


后台结果

springmvc笔记回顾——持续更新


处理器方法返回值



ModelAndView 返回值

若处理器方法处理完后,需要跳转到其他资源,且又要在跳转的资源间传递数据,此时处理器方法返回 ModelAndView 比较好。当然,若要返回 ModelAndView,则处理器方法中需要定义 ModelAndView对象。

本文地址:https://blog.csdn.net/weixin_40350981/article/details/109645897

相关标签: spring web java