SpringMVC笔记_1

引入坐标

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <spring.version>5.1.6.RELEASE</spring.version>
  </properties>
  
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</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>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.1</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>

SpringMVC 配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:mvc="http://www.springframework.org/schema/mvc"
     xmlns:context="http://www.springframework.org/schema/context"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     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">
  <!--开启注解扫描-->
  <context:component-scan base-package="com.springMVC.controller"></context:component-scan>

  <!--配置视图解析器对象,请求时,可以帮你跳转到指定的页面-->
  <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  	<!--文件路经-->
      <property name="prefix" value="/WEB-INF/pages/"/>
  	<!-- 指明后缀-->
      <property name="suffix" value=".jsp"/>
  </bean>
  
<!--    开启springMVC框架注解的支持-->
  <mvc:annotation-driven/>
</beans>

DispatcherServlet是前置控制器,配置在web.xml文件中的。拦截匹配的请求,Servlet拦截匹配规则要自己定义,把拦截下来的请求,依据相应的规则分发到目标Controller来处理,是配置spring MVC的第一步。

  • 在工程的webapp/WEB_INF目录下配置web.xml:
<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <!--    配置解决中文乱码的过滤器-->
  <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>

  <!--  前端控制器-->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <!--      加载配置文件-->
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath*:springMVC.xml</param-value>
    </init-param>
    <!--    启动时创建的(在第一次时候)-->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <!--    /是拦截请求的内容(表示拦截所有)-->
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

SpringMVC测试

如果是在开始的时候,系统就给你创建了jsp文件,你就先把它删了,然后重新创建一个,这样就解决了页面中文乱码了。

  • 在index.jsp中:
<%@ page contentType="text/html;charset=UTF-8" language="java"  %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>测试</h3>
    <a href="user/testString">测试</a>
</body>
</html>

在Controller类中:

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/testString")
    public String testString(){
        return "success";
    }
}
  • 在工程的webapp/WEB_INF/pages目录下创建成功跳转视图success.jsp如下:
<%@ page contentType="text/html;charset=UTF-8" language="java"  isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>执行success</h3>
</body>
</html>
  • 配置tomcat
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 配置完,点击启动,就会自动打开浏览器访问了。
  • 在这里插入图片描述
  • 在这里插入图片描述

执行流程分析

  • 启动Tomcat服务器时,由于配置了标签,所以首先创建DispatcherServlet对象并加载bean.xml配置文件
  • 由于bean.xml中开启了注解扫描,HelloController对象被创建并加入Spring容器中
  • 浏览器请求index.jsp,请求会先到达DispatcherServlet核心控制器,根据配置@RequestMapping注解找到具体要执行的方法helloHandler
  • 执行方法helloHandler,得到返回值. 的视图解析器解析返回值,查找到对应的JSP文件success.jsp
  • Tomcat服务器渲染页面,做出响应
    在这里插入图片描述

核心流程

在这里插入图片描述

具体步骤:
  • 第一步:发起请求到前端控制器(DispatcherServlet)
  • 第二步:前端控制器请求HandlerMapping查找 Handler (可以根据xml配置、注解进行查找)
  • 第三步:处理器映射器HandlerMapping向前端控制器返回Handler,HandlerMapping会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象,多个HandlerInterceptor拦截器对象),通过这种策略模式,很容易添加新的映射策略
  • 第四步:前端控制器调用处理器适配器去执行Handler
  • 第五步:处理器适配器HandlerAdapter将会根据适配的结果去执行Handler
  • 第六步:Handler执行完成给适配器返回ModelAndView
  • 第七步:处理器适配器向前端控制器返回ModelAndView (ModelAndView是springmvc框架的一个底层对象,包括 Model和view)
  • 第八步:前端控制器请求视图解析器去进行视图解析 (根据逻辑视图名解析成真正的视图(jsp)),通过这种策略很容易更换其他视图技术,只需要更改视图解析器即可
  • 第九步:视图解析器向前端控制器返回View
  • 第十步:前端控制器进行视图渲染 (视图渲染将模型数据(在ModelAndView对象中)填充到request域)
  • 第十一步:前端控制器向用户响应结果
    其中处理器映射器HandlerMapping,处理器适配器HandlAdapter,视图解析器ViewResolver称为SpringMVC三大组件.在bean.xml中声明<mvc:annotation-driven conversion-service=“conversionService”/>标签相当于自动配置了处理器映射器和处理器适配

请求路径匹配

@RequestMapping注解: 匹配路径与处理器
  • @RequestMapping注解用于建立请求URL路径和处理器之间的对应关系.
    • 出现位置: 可以出现在类上,也可以出现在方法上.

      • 当它既出现在类上也出现在方法上时,类上注解值为请求URL的一级目录,方法上注解值为请求URL的二级目录
      • 当它只出现在方法上时,该注解值为请求URL的一级目录
  • 其属性如下:

path: value属性的别名,指定请求的URL,支持Ant风格表达式,通配符如下:

通配符说明
?匹配文件(路径)名中的一个字符
*匹配文件(路径)名中的任意数量(包括0个)的字符
**匹配任意数量(包括0个)的路径
例如
  • 路径/project/*.a匹配项目根路径下所有在/project路径下的.a文件

  • 路径/project/p?ttern匹配项目根路径下的/project/pattern和/project/pXttern,但不能匹配/project/pttern

  • 路径/**/example匹配项目根路径下的/project/example,/project/foo/example,和/example

  • 路径/project/**/dir/file.*匹配项目根路径下的/project/dir/file.jsp,/project/foo/dir/file.html,/project/foo/bar/dir/file.pdf

  • 路径//.jsp匹配项目根路径下的所有jsp文件
    另外,遵循最长匹配原则,若URL请求了/project/dir/file.jsp,现在存在两个匹配模式://
    .jsp和/project/dir/.jsp,那么会根据/project/dir/.jsp来匹配.

  • method: 指定HTTP请求方法(可选RequestMethod.GET,RequestMethod.HEAD,RequestMethod.POST,RequestMethod.PUT等),多个值之间是或的关系.

  • params: 指定请求参数的限制,支持简单的表达式,如:

    • @RequestMapping(params={“param1”}),表示请求参数中param1必须出现
    • @RequestMapping(params={"!param1"}),表示请求参数中param1不能出现
    • @RequestMapping(params={“param1=value1”}),表示请求参数中param1必须出现且为value1
    • @RequestMapping(params={“param1!value1”}),表示请求参数中param1必须出现且不为value1
      多个值之间是与的关系
  • headers: 限定HTTP请求中必须包含的请求头,同样支持简单的表达式
    其中path和method属性较常用

@PathVaribale注解: 绑定URL占位符,支持REST风格URL

REST风格URL

REST风格URL有以下特点:

  • 资源Resources: 通过一个URI来指定一个具体的资源
  • 表现层Representation: 把资源具体呈现出来的形式
  • 状态转化State Transfer: 通过HTTP请求方法来决定状态转化
    例如:
REST风格URL含义
GET /accounts查找所有用户
POST /accounts新建用户
GET /accounts/{ID}查找对应ID的用户
PUT /accounts/{ID}更新对应ID的用户
DELETE /accounts/{ID}删除对应ID的用户

@PathVaribale注解的使用

在@RequestMapping注解的path属性中用{param}声明占位符,将展位符@PathVariable注解的name属性来修饰处理器参数来将占位符对应的值赋给方法的参数.例如

对于以下的请求和方法:

<a href="account/findAccount/10">查询账户</a>
// 控制器类
@Controller
@RequestMapping(path = "/account")
public class HelloController {

    @RequestMapping("/findAccount/{id}")
    public void findAccount(@PathVariable(name = "id") Integer accountId) {
        // accountId = 10
        // 方法体...
    }
}

访问URLhttp://localhost:8080/myProject/account/findAccount/10会将10传给findAccount方法的accountId参数.

请求参数的绑定

参数绑定的示例

SpringMVC将请求参数中的param=value中的value传递给控制器方法的param参数,例如:

对于以下请求和方法:

<a href="account/findAccount?accountId=10">查询账户</a>
// 控制器类
@Controller
@RequestMapping(path = "/account")
public class HelloController {

	@RequestMapping(path = "/findAccount")
	public void findAccount(Integer accountId) {
		// accountId = 10
		// 方法体...
	}
}

SpringMVC中会将10传给findAccount方法的accountID参数传递给HandlerAdapter执行.

@RequestParam注解: 为处理器方法参数起别名
  • @RequestParam注解作用在方法参数上,把请求中指定名称的参数给处理器方法中的形参赋值,相当于给处理器方法起别名.其属性如下:

    • name: value属性的别名,指定请求参数的名称
    • required: 指定该请求参数是否必须的,默认为true

例如jsp中发送请求如下

<a href="testRequestParam?param1=value">测试requestParam注解</a>

处理器方法中给对应参数加上@RequestParam(name=“param1”)注解来接收参数

@RequestMapping("/testRequestParam")
public String handlerMethod(@RequestParam("param1") String username) {
    // 方法体...
}

各种类型请求参数的绑定

SpringMVC内置参数绑定类型
  • SpringMVC支持三种类型的参数绑定
    • 基本数据类型和String类型
    • JavaBean类型
    • 集合类型

数据绑定要求请求参数名和方法中的参数名相同,或使用@RequestParam为方法参数起别名.

基本数据类型和String类型的参数绑定

对于基本数据类型,只需要以方法参数名作为请求参数名即可.示例如下:

<a href="account/findAccount?accountId=10&accountName=zhangsan">查询账户</a>
// 控制器类
@Controller
@RequestMapping(path = "/account")
public class HelloController {

    @RequestMapping("/findAccount")
    public String findAccount(Integer accountId, String accountName) {
        // accountId = 10, accountName = "zhangsan"
        // 方法体...
    }
}
JavaBean类型的参数绑定
  • JavaBean类型的参数,要想实现绑定,就必须实现其空参构造函数和所有属性的get,set方法
  1. 若JavaBean参数的属性中只包含基本数据类型和String类型属性,以属性名作为请求参数名,则SpringMVC会自动将其封装成JavaBean对象.示例如下:

例如JavaBean类的定义如下:

// JavaBean类
public class Account implements Serializable {

    private String username;
    private Integer age;

    // 所有属性的getset方法...
}

则其对应的请求参数名如下:

<form action="account/updateAccount" method="post">
    <label>名称</label><input type="text" name="username"><br/>
    <label>年龄</label><input type="text" name="age"><br/>
    <input type="submit" value="保存">
</form>
  1. 若JavaBean参数的属性中包含其它JavaBean对象,则以外层类属性名.内层类属性名作为请求参数,示例如下:

例如JavaBean类的定义如下:

public class Account implements Serializable {

    private String username;
    private Intger age;
    private User user;

	// 所有属性的getset方法...
}

public class User implements Serializable{

    private String uname;
    private Double umoney;
    
    // 所有属性的getset方法...
}

则其对应的请求参数名如下:

<form action="account/updateAccount" method="post">
    <label>名称</label><input type="text" name="username"><br/>
    <label>年龄</label><input type="text" name="age"><br/>
    <label>用户名</label><input type="text" name="user.uname"><br/>
    <label>用户余额</label><input type="text" name="user.umoney"><br/>
    <input type="submit" value="保存">
</form>
集合类型的参数绑定

对JavaBean类中的集合属性进行参数绑定,可以分为List类型的参数绑定和Set类型的参数绑定

  • 对于List类型参数,其请求参数名为集合名[下标],List类型参数可以对List,Set,数组类型成员进行赋值,但是诡异的是对Set和数组成员进行赋值时,要在Bean类的构造函数中new出对应的Set或数组,然而对于List就不用,下边的代码就可以直接跑,不知道为什么,希望知道的朋友不吝赐教
  • 对于Set类型参数,其请求参数名为集合名[键],Set类型参数可以对Set,Propertis类型成员进行赋值.
    例如JavaBean类的定义如下:
public class Account implements Serializable {

    private String username;
    private Intger age;
    
    private List<User> list;		// List集合属性
    private Map<String, User> map;	// Map集合属性


	// 所有属性的getset方法...
}

public class User implements Serializable{

    private String uname;
    private Double umoney;
    
    // 所有属性的getset方法...
}

则其对应的请求参数名如下:

<form action="account/updateAccount" method="post">
	用户名称:<input type="text" name="username"><br/>
	用户密码:<input type="password" name="password"><br/>
	用户年龄:<input type="text" name="age"><br/>
	账户1名称:<input type="text" name="accounts[0].name"><br/>
	账户1金额:<input type="text" name="accounts[0].money"><br/>
	账户2名称:<input type="text" name="accounts[1].name"><br/>
	账户2金额:<input type="text" name="accounts[1].money"><br/>
	账户3名称:<input type="text" name="accountMap['one'].name"><br/>
	账户3金额:<input type="text" name="accountMap['one'].money"><br/>
	账户4名称:<input type="text" name="accountMap['two'].name"><br/>
	账户4金额:<input type="text" name="accountMap['two'].money"><br/>
	<input type="submit" value="保存">
</form>

另外还有一个比较诡异的地方.我尝试将集合类型的参数绑定到控制器方法的参数上,然而不行

若我将方法参数类型设为List<>,则会报500错误,提示List不能初始化
若我将方法参数设为ArrayList<>,不会报错,但是不能注入
下面是错误的代码
@RequestMapping("/saveAccounts")
 //public String saveAccounts(List<Account> accounts) {	// 若设为List类型,则会报500错误
 public String saveAccounts(LinkedList<Account> accounts) {	// 若设为LinkedList类型,不报错但是初始化不上
 	System.out.println(accounts);
 	return "success";
 }
上面是错误的代码
不知道为什么会这样,若有知道时怎么回事的朋友,还望不吝赐教

自定义数据类型参数绑定

表单提交的任何数据类型都是字符串类型,SpringMVC定义了转换器,将字符串转化为我们方法参数的各种类型.我们也可以实现自定义的转换器以实现自定义的参数类型转换
自定义的类型转换器要实现Converter<String, T>接口,并在Spring容器配置bean.xml中配置该实现类. 示例如下:

在工程的java目录下创建控制器类cn.maoritian.util.StringToDateConverter类,实现Converter<String, Date>接口,完成从String类到Date类的转换:

// 自定义的类型转换器,完成从String类到Date类的转换
public class StringToDateConverter implements Converter<String, Date> {

    public Date convert(String source) {
        try {
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
            Date date = df.parse(source);
            return date;
        } catch (Exception e) {
            throw new RuntimeException("类型转换错误");
        }
    }
}

在Spring容器配置bean.xml中加入如下配置:

<!-- 配置的类型转换器工厂 -->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <!-- 诸如我们自定义的类型转换器 -->
            <bean class="cn.maoritian.utils.StringToDateConverter"/>
        </set>
    </property>
</bean>

通过原始ServletAPI对象处理请求

SpringMVC支持使用原始ServletAPI作为控制器方法的参数,包括HttpServletRequest,HttpServletResponse,HttpSession对象,他们都可以直接用做控制器方法的参数.示例如下:

@RequestMapping("/path")
public void myHandler(HttpServletRequest request, HttpServletResponse response) throws IOException {
    System.out.println(request.getParameter("param1"));
    System.out.println(request.getParameter("param1"));
    response.getWriter().println("<h3>操作成功</h3>");
}

解决请求参数绑定中文乱码问题
在web.xml中配置编码转换过滤器,即可解决请求参数中文乱码的问题.
```xml
<!-- 配置编码转换过滤器 -->
<filter>
	<filter-name>characterEncodingFilter</filter-name>
	<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filterclass>
	<!-- 指定字符集 -->
	<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>

详细请查看原文:

作者:ncepu_Chen 
来源:CSDN 
原文:https://blog.csdn.net/ncepu_Chen/article/details/95060670 
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值