springmvc

2023-11-05

前景介绍

springmvc图解

在这里插入图片描述

环境搭建

  • eclipse需要spring的环境,安装spring的插件。
    基于eclipse的spring插件安装可以看这个链接
  • 需要创建一个web项目
  • 需要的jar包
    springmvc需要spring的核心包:
      commons-logging-1.1.1.jar   //必须有Log包,不然报错
      spring-beans-5.2.6.RELEASE.jar
      spring-context-5.2.6.RELEASE.jar
      spring-core-5.2.6.RELEASE.jar
      spring-expression-5.2.6.RELEASE.jar
    
  • 对于mvc需要的jar包如下
    spring-web-5.2.6.RELEASE.jar
    spring-webmvc-5.2.6.RELEASE.jar
    
  • 使用注解,导入aop的包
    spring-aop-5.2.6.RELEASE.jar
    

工程起步

  • 项目结构
    在这里插入图片描述
    配置文件:①web.xml配置文件②框架本身的配置文件
  • 配置web.xml文件
    web.xml按下Alt+/快捷键.
    在这里插入图片描述
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
      <display-name>01-helloworld</display-name>
      
      <!-- The front controller of this Spring Web application, responsible for handling all application requests -->
        <!-- 前端控制器 -->
    	<servlet>
    		<servlet-name>springDispatcherServlet</servlet-name>
    		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    		<init-param>
    			<!-- 配置springmvc文件 -->
    			<param-name>contextConfigLocation</param-name>
    			<param-value>classpath:mvc.xml</param-value>
    		</init-param>
    		<!-- servlet启动加载,即服务器启动时创建对象,数值越小表示越先创造对象 -->
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    
    	<!-- Map all requests to the DispatcherServlet for handling -->
    	<servlet-mapping>
    		<servlet-name>springDispatcherServlet</servlet-name>	
    		<!-- 配置拦截所有 -->		
    		<url-pattern>/</url-pattern>
    	</servlet-mapping>
    </web-app>
    
  • 编写mvc.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"
	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/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">

	<!-- 配置需要扫描注解的类 如:后端Controller层的注解@Controller -->
	<context:component-scan base-package="com.hyq"/>
	<!-- 开启mvc注解驱动 -->
	<mvc:annotation-driven/>
	<!-- 默认使用tomcat的servlet -->
	<mvc:default-servlet-handler/>
</beans>
  • 编写Controller
	package com.hyq.controller;
	
	import org.springframework.stereotype.Controller;
	import org.springframework.web.bind.annotation.RequestMapping;
	
	@Controller
	public class HelloController {
	
		@RequestMapping("/")
		public String index() {
			System.out.println("------------");
			return "WEB-INF/index.html";
		}
		
		@RequestMapping("/success")
		public String success() {
			System.out.println("------------");
			return "WEB-INF/page/success.html";
		}
	}
  • 编写index.htmlsuccess.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="success">nihao</a>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
sssss
</body>
</html>
  • 还可以在mvc.xml配置视图解析器,这样controller层返回页面时不用带前缀和后缀(如.html)
    在这里插入图片描述
  • controller
    在这里插入图片描述

springmvc的配置文件

若没有指定配置文件会报错误,默认寻找/WEB-INF/XXX-servlet.xml文件
org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from ServletContext resource [/WEB-INF/springDispatcherServlet-servlet.xml]; nested exception is java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/springDispatcherServlet-servlet.xml]

在这里插入图片描述

相关的注解

RequestMapping的源码

//该注解可用于TYPE(类)上,也可用于METHOD(方法)上
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
	String name() default "";
	@AliasFor("path")
	String[] value() default {};
	@AliasFor("value")
	String[] path() default {};
	RequestMethod[] method() default {};
	String[] params() default {};
	String[] headers() default {};
	String[] consumes() default {};
	String[] produces() default {};
}

RequestMapping - params

myParam=myValue:请求中必须要包含myParam的参数,且值为myValue
如:@RequestMapping(value="/hello1",params="name=one").
访问地址:/XX项目名/hello1?name=one
myParam!=myValue:请求中必须包含myParam的参数,且值不能为myValue
如:@RequestMapping(value="/hello2",params="name!=one").
访问地址:/XX项目名/hello2?name=two,只要name不等于one就行
myParam:请求中必须包含myParam的参数,值任意
如:@RequestMapping(value="/hello3",params="name").
访问地址:/XX项目名/hello3?name,只要地址中有参数就行,值任意
!myParam:请求中不能包含myParam的参数
如:@RequestMapping(value="/hello4",params="!name").
访问地址:/XX项目名/hello4?pwd,只要地址中不包含name参数就行.

例子:@RequestMapping(value="/hello",params={"name","pwd=123"})
这种情况下,两个参数的顺序不能颠倒,且第一个参数必须是name它的值任意,第二个参数必须是pwd,值必须是123
/XX项目名/hello?name&&pwd=123

@ PathVariable的作用

他的作用在参数里用来提取url中的请求参数

@RequestMapping("/hyq/{url}/{name}")
	public String ant5(@PathVariable("url") String url,
			@PathVariable("url") String name) {
		System.out.println("url="+url+",name="+name);
		return "success";
	}

在这里插入图片描述

@RequestParam的注解使用

源码

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
		/**
	 * Alias for {@link #name}.
	 */
	@AliasFor("name")
	String value() default "";
		/**
	 * The name of the request parameter to bind to.
	 * @since 4.2
	 */
	@AliasFor("value")
	String name() default "";
	
	boolean required() default true;
	
	String defaultValue() default ValueConstants.DEFAULT_NONE;
}
  • 地址栏所带的参数和Java形参名称一致时,不用写@requestParam的注解
    在这里插入图片描述
    地址栏输入http://localhost:8080/test?username=3 控制台得到的结果是username=3
    当地址栏输入http://localhost:8080/test?user=3 控制台得到的结果是username=null
    当地址栏带参数但不带值时,http://localhost:8080/test?username 控制台得到的结果是username=
    当地址栏不带参数时,http://localhost:8080/test 控制台得到的结果是username=null
  • 地址栏所带的参数和Java形参名称不一致时,需要写@requestParam的注解
    在这里插入图片描述
    地址栏输入http://localhost:8080/test1?user=3,控制台输出username=3
    当地址栏的不带参数或参数不一致(和注解里面的不一致)时,http://localhost:8080/test1 直接报错,此时可以设置 参数可有可无 @RequestParam(required = false)
    地址栏带参数 但不带值时,http://localhost:8080/test1?user,控制台输出username=

@RequestParam和@PathVariable区别

@PahtVariable: 获取路径中的值 http://localhost:8080/user/{id}
@RequestParam: 获取?后面的值 http://localhost:8080/user?name=3

@RequestHeader注解

源码:

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestHeader{
		/**
	 * Alias for {@link #name}.
	 */
	@AliasFor("name")
	String value() default "";
		/**
	 * The name of the request parameter to bind to.
	 * @since 4.2
	 */
	@AliasFor("value")
	String name() default "";
	
	boolean required() default true;
	
	String defaultValue() default ValueConstants.DEFAULT_NONE;
}

作用:获取请求头中的值.
注解就相当于 request.getHeader(),当请求头中没有 值时 默认会报错
在这里插入图片描述

控制台输出:username=3
userAgent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36

@CookieValue

用法和上面类似,这里不再赘述

@RequestBody

作用:将返回的数据放在响应体中

Ant风格的请求

? 匹配单个字符
* 匹配0个或任意多个字符,可以匹配一层目录
** 匹配0个或任意多个目录

?的用法

@RequestMapping(value="/ant?"): ?处必须填写一个字符
在这里插入图片描述
若没有填写字符,则报错
在这里插入图片描述

* 的用法

@RequestMapping(value="/ant*"):* 处可以填写0个字符,也可以填写更多字符
在这里插入图片描述
填写多个字符一样通过
在这里插入图片描述
@RequestMapping(value="/*/ant"):* 处这里代表一个目录,形如/XX项目名称/a/ant
在这里插入图片描述

若是/XX项目名称/a/b/ant会报404,找不到页面。形如/XX项目名称/ant,把一级目录省略后,也会报404
在这里插入图片描述

** 的用法

@RequestMapping(value="/**/ant"):** 处可以填写多级目录.形如:/XX项目名称/a/b/c/d/ant,也可以不写目录,形如:/XX项目名称/ant
在这里插入图片描述
也可以不写目录,形如:/XX项目名称/ant
在这里插入图片描述
当访问地址有重复时,精确优先。看控制台输出的内容

@RequestMapping("/*/ant")
	public String ant3() {
		System.out.println("-----ant3-------");
		return "success";
	}
	
	@RequestMapping("/**/ant")
	public String ant4() {
		System.out.println("-----ant4-------");
		return "success";
	}

在这里插入图片描述

Rest 详解

表单形式的put/delete提交

1.web.xml配置过滤器
在这里插入图片描述
2. 表单中form的method必须是post提交,需要有一个隐藏的put/delete
在这里插入图片描述
3. 编写controller配置

@RequestMapping(value = "/getBook/{id}",method = RequestMethod.GET)
	public String getBook(@PathVariable("id") String id) {
		System.out.println("查询图书id="+id);
		return "success";
	}
	
	@RequestMapping(value = "/addBook",method = RequestMethod.POST)
	public String addBook() {
		System.out.println("添加图书");
		return "success";
	}
	
	@RequestMapping(value = "/delBook/{id}",method = RequestMethod.DELETE)
	public String delBook(@PathVariable("id") Integer id) {
		System.out.println("删除图书id="+id);
		return "success";
	}
	
	@RequestMapping(value = "/updBook/{id}",method = RequestMethod.PUT)
	public String updBook(@PathVariable("id") Integer id) {
		System.out.println("更新图书id="+id);
		return "success";
	}

HiddenHttpMethodFilter的源码分析

	private static final List<String> ALLOWED_METHODS =
			Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(),
					HttpMethod.DELETE.name(), HttpMethod.PATCH.name()));
	public static final String DEFAULT_METHOD_PARAM = "_method";
	private String methodParam = DEFAULT_METHOD_PARAM;
	
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {

		HttpServletRequest requestToUse = request;

		if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {
			String paramValue = request.getParameter(this.methodParam);  //通过request获取参数
			if (StringUtils.hasLength(paramValue)) {  //参数不为空
				String method = paramValue.toUpperCase(Locale.ENGLISH);  //转成大写
				if (ALLOWED_METHODS.contains(method)) {  //是否是Put/delete/patch之一
					requestToUse = new HttpMethodRequestWrapper(request, method);
				}
			}
		}

		filterChain.doFilter(requestToUse, response);
	}

POJO自动封装

  • 编写book1.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form method="post" action="submit">
	书名:<input type="text" name="name"><br>
	作者:<input type="text" name="author"><br>
	<!-- 下面是属于级联属性的操作 -->
	省:<input type="text" name="address.province"><br>
	市:<input type="text" name="address.city"><br>
	<input type="submit">
</form>
</body>
</html>
  • 编写Book1和Address类,代码中除了字段值,还包括get(),set(),toString(),无参有参构造器方法,其中必须有set()方法.
    在这里插入图片描述
    在这里插入图片描述
  • 编写Controller
    在这里插入图片描述
    效果
    在这里插入图片描述
    结果
    在这里插入图片描述
    当输入中文时,会有乱码出现,解决方案:在web.xml中配置字符编码过滤器,当有多个过滤器时,过滤器执行顺序从上往下执行,一般字符编码过滤器放在首位
<!-- 过滤器中加入字符编码过滤器即可 -->
<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>
		<init-param>
			<param-name>forceRequestEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
		<init-param>
			<param-name>forceResponseEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>characterEncodingFilter</filter-name>
		<!-- 拦截所有 -->
		<url-pattern>/*</url-pattern>

CharacterEncodingFilter核心源码
在这里插入图片描述

在web.xml中,filter的初始化参数encoding和forceRequestEncoding,forceResponseEncoding 设置的值,最终都要通过CharacterEncodingFilter的setXXX方法赋值。

在这里插入图片描述

数据输出-Model/Map/ModelMap

  • 编写index.jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>首页</h1>
<a href="success1">调转1</a>
<a href="success2">调转2</a>
<a href="success3">调转3</a>
</body>
</html>
  • 编写success.jsp页面
<body>
成功<br>
sessionScope:${sessionScope.msg }<br>
requestScope:${requestScope.msg }<br>
pageScope:${pageScope.msg }<br>
applicationScope:${applicationScope.msg }<br>
</body>
  • 编写控制器(处理器)
@RequestMapping("/success1")
	public String success1(Map<String, Object> map) {
		map.put("msg", "你好");
		System.out.println(map.getClass());
		return "success";
	}
	
	@RequestMapping("/success2")
	public String success2(Model model) {
		model.addAttribute("msg", "model");
		System.out.println(model.getClass());
		return "success";
	}
	
	@RequestMapping("/success3")
	public String success3(ModelMap mp) {
		mp.addAttribute("msg", "ModelMap");
		System.out.println(mp.getClass());
		return "success";
	}

效果:
在这里插入图片描述
分别点击 三个超链接,得到三个页面
在这里插入图片描述
结论:Model/Map/ModelMap最终都要都要转换为BindingAwareModelMap,数据保存在了request域中
Model(接口),Map(接口),ModelMap(类)之间关系
在这里插入图片描述

< mvc:annotation-driven/>的解释

< mvc:annotation-driven/>,< mvc:default-servlet-handler/>

  • 1)都没有配置的情况下,只有动态资源(@requestMapping映射的资源)能够访问,静态资源(js,HTML,.img等)不能访问
  • 2)配置< mvc:default-servlet-handler/>,没有配置< mvc:annotation-driven/>,静态资源可以访问,但是动态资源不能访问
  • 3)配置< mvc:annotation-driven/>,没有配置< mvc:default-servlet-handler/>,静态资源 依然不能访问
  • 4) 两个都配置,才能保证静态资源和动态资源都能访问

springmvc运行流程

1)发送请求,前端控制器(DispatcherServlet)收到请求,调用doDispatch处理
2)根据HandlerMapping中保存的请求映射信息找到处理当前请求的处理器执行链(包含拦截器)
3)根据当前处理器找到它的HandlerAdapter(适配器)
4)拦截器的preHandler先执行
5)适配器执行目标方法,并返回ModelAndView
6)拦截器的postHandler执行
7)处理结果;(页面渲染流程)
(1)如果有异常使用异常解析器处理,处理完毕后返回ModelAndView
(2)调用render进行页面渲染
(3)执行拦截器的afterCompletion;

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

springmvc 的相关文章

  • 如何让 BlazeDS 忽略属性?

    我有一个 java 类 它有一个带有 getter 和 setter 的字段 以及第二对 getter 和 setter 它们以另一种方式访问 该字段 public class NullAbleId private static final
  • 如何通过 javaconfig 使用 SchedulerFactoryBean.schedulerContextAsMap

    我使用 Spring 4 0 并将项目从 xml 移至 java config 除了访问 Service scheduleService 带注释的类来自QuartzJobBean executeInternal 我必须让它工作的 xml 位
  • Java 枚举与创建位掩码和检查权限的混淆

    我想将此 c 权限模块移植到 java 但是当我无法将数值保存在数据库中然后将其转换为枚举表示形式时 我很困惑如何执行此操作 在 C 中 我创建一个如下所示的枚举 public enum ArticlePermission CanRead
  • .properties 中的通配符

    是否存在任何方法 我可以将通配符添加到属性文件中 并且具有所有含义 例如a b c d lalalala 或为所有以结尾的内容设置一个正则表达式a b c anything 普通的 Java 属性文件无法处理这个问题 不 请记住 它实际上是
  • 为 java 游戏创建交互式 GUI

    大家好 我正在创建一个类似于 java 中的 farmville 的游戏 我只是想知道如何实现用户通常单击以与游戏客户端交互的交互式对象 按钮 我不想使用 swing 库 通用 Windows 看起来像对象 我想为我的按钮导入自定义图像 并
  • 如何使用assertEquals 和 Epsilon 在 JUnit 中断言两个双精度数?

    不推荐使用双打的assertEquals 我发现应该使用带有Epsilon的形式 这是因为双打不可能100 严格 但无论如何我需要比较两个双打 预期结果和实际结果 但我不知道该怎么做 目前我的测试如下 Test public void te
  • HSQL - 识别打开连接的数量

    我正在使用嵌入式 HSQL 数据库服务器 有什么方法可以识别活动打开连接的数量吗 Yes SELECT COUNT FROM INFORMATION SCHEMA SYSTEM SESSIONS
  • 如何在 Spring 中禁用使用 @Component 注释创建 bean?

    我的项目中有一些用于重构逻辑的通用接口 它看起来大约是这样的 public interface RefactorAwareEntryPoint default boolean doRefactor if EventLogService wa
  • Java 集合的并集或交集

    建立并集或交集的最简单方法是什么Set在 Java 中 我见过这个简单问题的一些奇怪的解决方案 例如手动迭代这两个集合 最简单的单行解决方案是这样的 set1 addAll set2 Union set1 retainAll set2 In
  • Hibernate 的 PersistentSet 不使用 hashCode/equals 的自定义实现

    所以我有一本实体书 public class Book private String id private String name private String description private Image coverImage pr
  • 内部类的构造函数引用在运行时失败并出现VerifyError

    我正在使用 lambda 为内部类构造函数创建供应商ctx gt new SpectatorSwitcher ctx IntelliJ建议我将其更改为SpectatorSwitcher new反而 SpectatorSwitcher 是我正
  • 不接受任何内容也不返回任何内容的函数接口[重复]

    这个问题在这里已经有答案了 JDK中是否有一个标准的函数式接口 不接受也不返回任何内容 我找不到一个 像下面这样 FunctionalInterface interface Action void execute 可运行怎么样 Functi
  • 如何使用 jUnit 将测试用例添加到套件中?

    我有 2 个测试类 都扩展了TestCase 每个类都包含一堆针对我的程序运行的单独测试 如何将这两个类 以及它们拥有的所有测试 作为同一套件的一部分执行 我正在使用 jUnit 4 8 在 jUnit4 中你有这样的东西 RunWith
  • Android:无法使用 DbHelper 和 Contract 类将数据插入 SQLite

    public class Main2Activity extends AppCompatActivity private EditText editText1 editText2 editText3 editText4 private Bu
  • 包 javax.el 不存在

    我正在使用 jre6 eclipse 并导入 javax el 错误 包 javax el 不存在 javac 导入 javax el 过来 这不应该是java的一部分吗 谁能告诉我为什么会这样 谢谢 米 EL 统一表达语言 是 Java
  • 如何将双精度/浮点四舍五入为二进制精度?

    我正在编写对浮点数执行计算的代码的测试 不出所料 结果很少是准确的 我想在计算结果和预期结果之间设置一个容差 我已经证实 在实践中 使用双精度 在对最后两位有效小数进行四舍五入后 结果始终是正确的 但是usually四舍五入最后一位小数后
  • 如果没有抽象成员,基类是否应该标记为抽象?

    如果一个类没有抽象成员 可以将其标记为抽象吗 即使没有实际理由直接实例化它 除了单元测试 是的 将不应该实例化的基类显式标记为抽象是合理且有益的 即使在没有抽象方法的情况下也是如此 它强制执行通用准则来使非叶类抽象 它阻止其他程序员创建该类
  • 双枢轴快速排序和快速排序有什么区别?

    我以前从未见过双枢轴快速排序 是快速排序的升级版吗 双枢轴快速排序和快速排序有什么区别 我在 Java 文档中找到了这个 排序算法是双枢轴快速排序 作者 弗拉基米尔 雅罗斯拉夫斯基 乔恩 本特利和约书亚 布洛赫 这个算法 在许多数据集上提供
  • 如何防止在Spring Boot单元测试中执行import.sql

    我的类路径中有一个 import sql 文件 其中包含一些 INSERT 语句 当使用 profile devel 运行我的应用程序时 它的数据被加载到 postgres 数据库中 到目前为止一切正常 当使用测试配置文件执行测试时 imp
  • Spring Rest 和 Jsonp

    我正在尝试让我的 Spring Rest 控制器返回jsonp但我没有快乐 如果我想返回 json 但我有返回的要求 完全相同的代码可以正常工作jsonp我添加了一个转换器 我在网上找到了用于执行 jsonp 转换的源代码 我正在使用 Sp

随机推荐