SpringMVC配置

作者: 小杨小杨神采飞杨 | 来源:发表于2020-04-24 17:36 被阅读0次

第一个MVC项目-HelloWorld

基本原理:

引用西部开源秦疆老师的图
1、首先确认目录结构
确认目录结构
2、编写web.xml,主要是配置DispatcherServlet
web.xml
3、配置SpringMVC-servlet.xml
SpringMVC-servlet.xml
4、配置解析类
解析类
之后用户访问解析类内配置的名称,springmvc会自动调用在web.xml中配置的DispatcherServlet,DispatcherServlet首先会调用视图解析器根据设置的头尾拼接出完整资源名称,之后根据该名称查找对应的已注册的bean,找到后访问指定资源进行跳转

注意:若代码没出错依旧无法运行,检查idea配置问题
点击右上角


配置

查看当前web项目下是否有对应的lib包,若没有手动创建并导包


配置问题

使用注解配置

配置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>SpringMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:SpringMVC-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>

    <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>
</web-app>

配置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:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <!--扫描指定包-->
    <context:component-scan base-package="cn.yzx.controller"/>
    <!--不处理静态资源-->
    <mvc:default-servlet-handler/>
    <!--
    开启支持mvc注解驱动,要想使@RequestMappering注解生效,需要开启
    处理器映射
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    处理器适配器
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
    <mvc:annotation-driven/>自动注入了以上两个实例
    -->
    <mvc:annotation-driven/>
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

以上两个配置是死的,无序过多改动
接下来就很简单了,随意的创建一个类,随意的创建一个方法,使用两个注解完成所有操作

@Controller
public class helloController {
    @RequestMapping("hello")
    public String hello(Model model) {
        model.addAttribute("msg","你好世界!!!"); //使用model共享数据
        return "hello"; //在视图解析器配置了前置后置,所以这里直接返回资源的名称即可
    }
}

补充:

  1. @Controller:
    就是将bean注册到ioc容器中的效果,但是@Controller稍微特殊一点,可以让容器知道他是一个Controller层的类

  2. @RequestMapping:

  • 标注在方法上,是告诉SpringMVC,这个方法用于处理什么请求,/是可以省略的,默认也是从当前项目开始寻找,加上比较好
  • 标注在类上,等于为WEB应用设置了一个根目录,下边的所有资源访问都要带上这一级目录名称例如标注在类上为"/haha",那么访问这个通过这个类下的所有方法访问资源都要带上/haha,访问hello就是/haha/hello以此类推
    标注在类上
    测试结果
    可见效果正是给该类下的资源添加了根路径信息
  1. @RequestMapping的其他属性;
    method:限定请求方式


    method

params:设置请求参数信息,支持简单的表达式

params = {"username"} //请求必须带有名为username的参数
params = {"!username"} //请求不能带有名为username的参数
params = {"username=123"} //请求必须带有名为username的参数且参数值必须为123
params = {"username!=123"} //请求若带有名为username的参数,则参数值不能为123
            //注意此时不带username等于值为null,也满足条件
params = {"username","pwd!=123","id=123"} //请求必须满足以上所有规则

headers:设置请求头信息,支持简单的表达式
consumes:规定请求头中Content-type信息
produces:告诉浏览器响应的类型是什么,等于给响应头加上Content-type信息

  1. @RequestMapping的模糊匹配功能
    ?:能替代任意一个字符


    ?
    访问成功

*:能替代任意夺个字符和一层路径


*替代字符 访问成功 *替代路径 访问成功

**:能替代多层路径


** 访问成功

注意:当满足多个匹配条件时,精确度高的匹配优先度更高(明确 > ? > * > **),例如有haha和h?h?,但是指定资源不同,访问haha会访问haha指定的精确资源而不会访问模糊匹配的资源

  1. 路径中可以有占位符,效果就是占据一层路径,可以是任意字符,搭配@PathVariable注解可以获取路径中占位符处的值


    获取值
测试结果

REST风格的URL

REST:(资源)表现层状态转化
springMVC支持REST风格的URL

传统的url区分CRUD操作:
获取:/getInfo?id=1
更新:/updateInfo?id=1
删除:/deleteInfo?id=1
添加:/addInfo

当操作多了,取名会很多,很复杂
而rest的思想就是,URL统一为/资源名/资源表示符,转而使用不同的提交方式来区分CRUD操作

rest风格url区分CRUD:
获取:/Info?id=1 使用GET方式提交
更新:/Info?id=1 使用PUT方式提交
删除:/Info?id=1 使用DELETE方式提交
添加:/Info 使用POST方式提交

问题:从页面只能发出get和post两种请求,怎么办?

测试:使用rest风格的url完成CRUD实验
环境搭建:
在controller类中根据四种不同的请求方式,给页面传递不同的信息,模拟CRUD操作

@Controller
public class myController {
    @RequestMapping(value = "/info/{sid}",method = RequestMethod.GET)
    public String getInfo(@PathVariable("sid")Integer id, Model model) {
        model.addAttribute("msg","成功获取了"+id+"号学生的信息");
        return "success";
    }

    @RequestMapping(value = "/info",method = RequestMethod.POST)
    public String addInfo(Model model) {
        model.addAttribute("msg","成功添加了新的学生的信息");
        return "success";
    }

    @RequestMapping(value = "/info/{sid}",method = RequestMethod.DELETE)
    public String deleteInfo(@PathVariable("sid")Integer id, Model model) {
        model.addAttribute("msg","成功删除了"+id+"号学生的信息");
        return "success";
    }

    @RequestMapping(value = "/info/{sid}",method = RequestMethod.PUT)
    public String updateInfo(@PathVariable("sid")Integer id, Model model) {
        model.addAttribute("msg","成功更新了"+id+"号学生的信息");
        return "success";
    }
}
页面运行结果

简单测试后发现,因为页面无法发出除了get和post之外的请求,所以点击获取学生信息和增加学生信息可以正常跳转,但是点击更新和删除学生信息默认是以get方式发送请求,所以跳转的依然是获取学生信息的页面

解决方案:
在web.xml中,配置HiddenHttpMethodFilter过滤器


HiddenHttpMethodFilter

在index.jsp页面中,将删除、更新两个超链接更换为post提交方式的表单,并且在表单内添加name属性为"_method",value值为对应提交方式的input标签


页面

之后提交这两个表单就会以name属性为"_method"的input标签的value值规定的方式进行提交

注意:如果使用Tomcat8.0+版本进行测试,会报错,应为Tomcat8之后的版本默认不允许PUT、DELETE等提交方式


错误信息

解决方法:在跳转之后的jsp页面上,将isErrorPage值设置为true


isErrorPage
这之后就可以正常执行了

原理:
观察HiddenHttpMethodFilter过滤器的原码可以发现


原理

请求处理

  1. 获取请求参数的值
    默认方式获取参数值:
    直接在方法形参中添加和参数值名称类型相同的属性即可获取


    页面
形参 测试结果
  1. 当username形参已经在方法中大量使用,此时将请求参数名称改为user,则需要大量的修改,此时可以使用@RequestParam("user")注解来修改获取的参数名称
    @RequestParam
    此时使用user可以传递参数
    测试结果
    但是@RequestParam指定的请求参数,默认是必须要有的,即设置之后,请求不能不带这个参数,可以为空,但不能没有,没有就报错
    错误
    可以通过设置@RequestParam的属性来解决这个问题
    required:是否可以为null,true表示不能为null,false表示可以
    设置
    测试结果

defaultValue:设置默认值,即传空的数据,会默认使用这个数据

defaultValue 测试结果

注意,设置默认值之后,即使不设置required属性,也可以为null,为null时,也是用默认值


测试结果
  1. 获取请求头的信息
    使用方法与@RequestParam一致


    @RequestParam
测试结果
若请求参数中没有指定的请求头信息,就会报错,此时也可以通过设置属性来解决问题,属性required和defaultValue使用方法效果与@RequestParam一致
  1. 获取cookie信息
    使用@CookieValue可以根据key值获取cookie中对应的值


    @CookieValue
测试结果
若cookie中没有指定的key信息,则报错,此时也可以通过设置属性来解决问题,属性required和defaultValue使用方法效果与@RequestParam一致
  1. 自动封装pojo类以及级联封装
    springmvc强大的功能,可以直接根据参数名自动封装到对应的pojo类中
    创建表单


    表单

    根据表单创建实体类


    实体类
    修改方法,设置对应实体类的形参
    修改方法
    测试
    测试结果

问题:
1、如果有比实体类更多的请求参数

表单
例如111,则springmvc只会将和实体类set方法名称相同的参数封装到实体类中
2、级联属性封装需要使用级联属性.属性的方式设置请求参数名
3、tomcat8之后,默认解决了get获取中文的乱码问题,而8之前的版本需要将tomcat的server.xml种8080端口后加上编码格式才能不乱吗
4、使用post请求方式会出现乱码问题
问题
解决方式:在web.xml中配置CharacterEncodingFilter过滤器,解决乱码
CharacterEncodingFilter
CharacterEncodingFilter必须配置在所有过滤器之前,应为要在获取请求的第一时间先解决乱码问题
测试结果
6、如果是delete、put等请求方式,解决方案和post一致,因为本质上他们都是post请求方式
7、springmvc支持直接使用原生API
原生API

传输数据到页面

  1. 使用Model、ModelMap、Map集合共享数据


    代码
测试结果

共同点:
通过这三种方式共享的数据,都在requestScope域中,且他们都是通过实现了BindingAwareModelMap实现了共享数据的功能,本质上是同一个东西

实现方式
  1. 使用@SessionAttributes可以将放在请求域中的数据copy一份到session域中,使用key值直接指定或使用type指定类型,但是有bug,所以想共享数据到session中,建议使用原生api,可控,易删除


    原生API使用session

转发&重定向

当视图解析器的前缀和后缀设置好之后,若想去其他路径下的页面,可以使用../跳到上一级页面


上一级页面

也可以使用转发,使用forward:+路径可以跳过视图解析器的拼串环节

代码 测试结果

或者重定向,传统重定向需要带上虚拟目录路径,而在springmvc中,框架会自动帮我们添上


代码 测试结果

二者的区别是转发只能在服务器内部资源中跳转,而重定向可以跳转到其他服务器的资源

重定向

且转发可以共享数据,而重定向不行

相关文章

网友评论

    本文标题:SpringMVC配置

    本文链接:https://www.haomeiwen.com/subject/xztfwhtx.html