SpringMVC(一)
SpringMVC(一)
SpringMVC简介
springMVC概述
- Spring MVC属于SpringFrameWork的后续产品
- Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块
- 使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,
- 可以选择使用Spring的SpringMVC框架或集成其他MVC开发框架
- Spring web mvc和Struts2都属于表现层的框架
Springmvc处理流程
入门程序
1.创建web工程
2.导入springMVC相关jar包,在spring的基础上添加一个mvc的包
classmate.jar
com.springsource.com.mchange.v2.c3p0-0.9.1.2.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar
com.springsource.org.apache.commons.fileupload-1.2.0.jar
com.springsource.org.apache.commons.io-1.4.0.jar
com.springsource.org.apache.commons.logging-1.1.1.jar
com.springsource.org.apache.commons.pool-1.5.3.jar
com.springsource.org.apache.log4j-1.2.15.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
druid-1.0.15.jar
hamcrest-core-1.3.jar
hibernate-validator-5.jar
hibernate-validator-annotation-processor-5.jar
jackson-annotations-2.9.4.jar
jackson-core-2.9.4.jar
jackson-databind-2.9.4.jar
jboss-logging-3.1.1.jar
jstl.jar
junit-4.12.jar
lombok.jar
mysql-connector-java-5.1.7-bin.jar
spring-aop-5.0.7.RELEASE.jar
spring-aspects-5.0.7.RELEASE.jar
spring-beans-5.0.7.RELEASE.jar
spring-context-5.0.7.RELEASE.jar
spring-core-5.0.7.RELEASE.jar
spring-expression-5.0.7.RELEASE.jar
spring-jdbc-5.0.7.RELEASE.jar
spring-test-5.0.7.RELEASE.jar
spring-tx-5.0.7.RELEASE.jar
spring-web-5.0.7.RELEASE.jar
spring-webmvc-5.0.7.RELEASE.jar
standard.jar
validation-api-1.1.0.jar
3.添加配置文件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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.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-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
</beans>
4.配置前端控制器
在web.xml当中配置前端控制器
<!-- 配置SpringMVC前端控制器 -->
<servlet>
<servlet-name>mySpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 指定SpringMVC配置文件 -->
<!-- SpringMVC的配置文件的默认路径是/WEB-INF/${servlet-name}-servlet.xml -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>mySpringMVC</servlet-name>
<!-- 设置所有以action结尾的请求进入SpringMVC -->
<url-pattern>*.action</url-pattern>
</servlet-mapping>
springMVC中url-patten取值
/*
拦截所有 jsp js png .css 真的全拦截.不建议使用
*.action *.do
拦截以do action 结尾的请求
/
拦截所有,不包括jsp,包含.js .png.css 建议使用
5.创建控制器
package com.le.web.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class MyController {
@RequestMapping("/first.action")
public ModelAndView show(){
ModelAndView modelAndView = new ModelAndView();
//请求过来后, 跳转到另一个界面 往另一个界面当中传一些数据
modelAndView.addObject("name","le");
modelAndView.setViewName("le");
return modelAndView;
}
}
6.在springmvc核心配置文件当中添加控制器扫描范围
<!--注解扫描,扫描指定包下注解@Controller @Service -->
<context:component-scan base-package="com.le"/>
7.创建first.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>first.jsp</h1>
转发过来的数据name=${name}
</body>
</html>
8.index.jsp页面跳转
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<a href="${pageContext.request.contextPath}/first.action">发送请求-first.jsp</a>
</body>
</html>
执行流程
- first.jsp页面发送请求
- 在springmvc.xml中经过前端控制器
- 扫描指定包下注解,找到匹配
- 控制器返回模型视图
- 传回index.jsp
详细执行流程
架构流程
- 用户发送请求至前端控制器DispatcherServlet
- 前端控制器DispatcherServlet收到请求调用HandlerMapping处理器映射器
- 处理器映射器HandlerMapping根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
- 前端控制器DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
- 执行处理器(Handler,也叫后端控制器)执行完成返回ModelAndView
- 处理器适配器HandlerAdapter将Handler执行处理器的执行结果ModelAndView返回给前端控制器DispatcherServlet
- 前端控制器DispatcherServlet将ModelAndView传给ViewReslover视图解析器
- 视图解析器ViewReslover解析后返回具体View
- 前端控制器DispatcherServlet对View进行渲染视图(即 将模型数据填充至视图中)
- 前端控制器DispatcherServlet响应用户
流程图
组件说明
DispatcherServlet
- 前端控制器
- 用户请求到达前端控制器,它就相当于mvc模式中的C
- dispatcherServlet是整个流程控制的中心
- 由它调用其它组件处理用户的请求
- dispatcherServlet的存在降低了组件之间的耦合性
HandlerMapping
- 处理器映射器
- HandlerMapping负责根据用户请求url找到Handler处理器
- SpringMVC提供了不同的映射器实现不同的映射方式
- HandlerMapping会把找到的映射返回给前端控制器
Handler
- 后端控制器
- 在DispatcherServlet的控制下Handler对具体的用户请求进行处理
HandlAdapter
- 处理器适配器
- 通过HandlerAdapter对处理器进行执行
ViewResolver
- 视图解析器
- View Resolver负责将处理结果生成View视图
View
- SpringMVC框架提供了很多的View视图类型的支持,
- 包括:jstlView、freemarkerView、pdfView等。我们最常用的视图就是jsp
默认加载组件
处理器映射器
- @RequestMapping:定义请求url到处理器功能方法的映射
- 注解式处理器映射器,对类中标记了@ResquestMapping的方法进行映射
- 根据@ResquestMapping定义的url匹配@ResquestMapping标记的方法
- 匹配成功返回HandlerMethod对象给前端控制器
- HandlerMethod对象中封装url对应的方法Method
处理器适配器
- 对标记@ResquestMapping的方法进行适配
- 解析对应的方法
视图解析器
-
视图解析器使用SpringMVC框架默认的InternalResourceViewResolver
-
这个视图解析器支持JSP视图解析
-
配置视图解析器
当一个页面存放目录结构比较多时,就可以配置目录
springmvc.xml
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/myxq/"/>
<property name="suffix" value=".jsp"/>
</bean>
可以在返回地址上添加前缀和后缀
@Controller
public class MyController {
@RequestMapping("/first.action")
public ModelAndView show(){
ModelAndView modelAndView = new ModelAndView();
//请求过来后, 跳转到别一个界面
//往别一个界面当中传一些数据
modelAndView.addObject("name","le");
modelAndView.setViewName("/first"); //=> /WEB-INF/myxq/first.jsp
return modelAndView;
}
}
之前的注册映射器和适配器
- 3.2之前
- defaultAnnotationHandlerMapping
- AnnotationMethodHandlerAdapter
- < mvc:annotation-driven />
请求转发与重定向
启动服务器加载SpringMVC
web.xml
<!-- 配置SpringMVC前端控制器 -->
<servlet>
<servlet-name>mySpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 指定SpringMVC配置文件 -->
<!-- SpringMVC的配置文件的默认路径是/WEB-INF/${servlet-name}-servlet.xml -->
<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>mySpringMVC</servlet-name>
<!-- 拦截所有,不包括jsp,包含.js .png.css 建议使用 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
作用如下:
1.load-on-startup元素标记容器是否在启动的时候就加载这个servlet(实例化并调用其init()方法)。
2.它的值必须是一个整数,表示servlet应该被载入的顺序。;
3.当值为0或者大于0时,表示容器在启动时就加载并初始化这个servlet。
4.当值小于0或者没有指定时,则表示容器在该Servlet被请求时,才会去加载。
5.正数的值越小,表示该Servlet的优先级就越高,应用启动时就优先加载;而非启动延迟时间。
6.当值相同的时候,容器就会自己选择优先加载。
通常大多数Servlet是在用户第一次请求的时候由应用服务器创建并初始化,但
请求转发
index.jsp
<a href="${pageContext.request.contextPath}/first.action">发送请求-result.jsp</a>
<a href="${pageContext.request.contextPath}/second.action">发送请求-second.jsp</a>
@Controller
public class MyController {
//匹配请求可以去省略action
@RequestMapping("/first")
public ModelAndView show(){
ModelAndView modelAndView = new ModelAndView();
//请求过来后, 跳转到别一个界面 往别一个界面当中传一些数据
modelAndView.addObject("name","le");
modelAndView.setViewName("forward:/second");//发送请求不可以去省略action
return modelAndView;
}
@RequestMapping("/second")
public String show2(){
return "/result.jsp";
}
}
重定向
@Controller
public class MyController {
//匹配请求可以去省略action
@RequestMapping("/first")
public ModelAndView show(){
ModelAndView modelAndView = new ModelAndView();
//请求过来后, 跳转到别一个界面 往别一个界面当中传一些数据
modelAndView.addObject("name","le");
modelAndView.setViewName("redirect:/second.action");//发送请求不可以去省略action
return modelAndView;
}
@RequestMapping("/second")
public String show2(){
return "redirect:/result.jsp";
}
}
接收参数
使用传统request对象接收参数
- Springmvc框架会自动把Request对象传递给方法
index.jsp
<form action="${pageContext.request.contextPath}/myform">
user:<input type="text" name="user_name"><br>
age:<input type="text" name="user_age" ><br>
<input type="submit" value="提交">
</form>
FormController类
@Controller
public class FormController {
@RequestMapping("myform")
public ModelAndView form(HttpServletRequest request){
String user = request.getParameter("user_name");
String age = request.getParameter("user_age");
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("user",user);
modelAndView.addObject("age",age);
modelAndView.setViewName("/result.jsp");
return modelAndView;
}
}
result.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
用户:${user}<br/>
年龄:${age}
</body>
</html>
不使用request接收简单类型参数
- 当请求的参数名称和处理器形参名称一致时会将请求参数与形参进行绑定。
@Controller
public class FormController {
@RequestMapping("myform")
public ModelAndView form(String user,String age){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("user",user);
modelAndView.addObject("age",age);
modelAndView.setViewName("/result.jsp");
return modelAndView;
}
}
- @RequestParam
形参的类型与绑定的类型不一致时,可以使用@RequestParam进行匹配
value
请求参数名字
required
是否必须
默认是true
表示请求中一定要有相应的参数,否则将报错
defaultValue
默认值
表示如果请求中没有同名参数时的默认值
@RequestParam(value = "id",required = true,defaultValue = "100") Integer idkey
参数必须,有默认值时,哪怕请求中没有对应的参数,也不会报错
FormController类
@Controller
public class FormController {
@RequestMapping("myform")
public ModelAndView form(@RequestParam(value="user_name") String user,@RequestParam(value="user_age") String age){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("user",user);
modelAndView.addObject("age",age);
modelAndView.setViewName("/result.jsp");
return modelAndView;
}
}
以一个javaBean对象接收
要求对象当中的属性要和表单当中的名称一致
User类
package com.le.domain;
import lombok.Getter;
import lombok.Setter;
import java.util.Arrays;
import java.util.List;
@Setter@Getter
public class User {
private String user_name;
private String user_age;
private String hobby[];
private Dog dog;
private List<Dog> dogs;
@Override
public String toString() {
return "User{" +
"user_name='" + user_name + '\'' +
", user_age='" + user_age + '\'' +
", hobby=" + Arrays.toString(hobby) +
", dog=" + dog +
", dogs=" + dogs +
'}';
}
}
表单
<form action="${pageContext.request.contextPath}/myform.action">
user:<input type="text" name="user_name"><br>
age:<input type="text" name="user_age" ><br>
爱好:<input type="checkbox" name="hobby" value="篮球"> 篮球
<input type="checkbox" name="hobby" value="乒乓球"> 乒乓球
<input type="checkbox" name="hobby" value="足球"> 足球
<input type="submit" value="提交">
</form>
数组接收数据
name相同时,可以使用数组来接收对应的参数
表单
<form action="${pageContext.request.contextPath}/myform2.action">
user:<input type="text" name="user_name"><br>
age:<input type="text" name="user_age" ><br>
<input type="submit" value="提交">
</form>
User类
public class User {
private String user_name;
private String user_age;
private String hobby[];
}
包装类接收参数
QueryUser类
@Setter@Getter
public class QueryUser {
User user;
}
表单
<form action="${pageContext.request.contextPath}/myform2">
user:<input type="text" name="user.user_name"><br>
age:<input type="text" name="user.user_age" ><br>
爱好:<input type="checkbox" name="user.hobby" value="篮球"> 篮球
<input type="checkbox" name="user.hobby" value="乒乓球"> 乒乓球
<input type="checkbox" name="user.hobby" value="足球"> 足球
<input type="submit" value="提交">
</form>
FormController类
@RequestMapping("myform2")
public ModelAndView form(QueryUser queryUser){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("user",queryUser);
modelAndView.setViewName("/result.jsp");
return modelAndView;
}
result.jsp
用户:${queryUser.user.user_name}<br/>
年龄:${queryUser.user.user_age}
List集合接受数据
User类
@Setter@Getter
public class User {
private String user_name;
private String user_age;
private String hobby[];
private Dog dog;
private List<Dog> dogs;
}
表单
<form action="${pageContext.request.contextPath}/myform2">
user:<input type="text" name="user_name"><br>
age:<input type="text" name="user_age" ><br>
爱好:<input type="checkbox" name="hobby" value="篮球"> 篮球
<input type="checkbox" name="hobby" value="乒乓球"> 乒乓球
<input type="checkbox" name="hobby" value="足球"> 足球
<br>--------宠物---------<br>
宠物名称:<input type="text" name="dog.name"> <br>
宠物颜色:<input type="text" name="dog.color"> <br>
<br>--------宠物---------<br>
宠物名称:<input type="text" name="dogs[0].name"> <br>
宠物颜色:<input type="text" name="dogs[0].color"> <br>
<br>--------宠物---------<br>
宠物名称:<input type="text" name="dogs[1].name"> <br>
宠物颜色:<input type="text" name="dogs[1].color"> <br>
<input type="submit" value="提交">
</form>
@RequestMapping("myform2")
public String myform4(User user){
return "/result.jsp";
}
自定义参数绑定
需求
- 根据业务需求自定义数据显示格式
- 修改商品日期
- 由于日期数据有很多种格式,springmvc没办法把字符串转换成日期类型。所以需要自定义参数绑定
分析
- 前端控制器接收到请求后,找到注解形式的处理器适配器
- 对RequestMapping标记的方法进行适配,并对方法中的形参进行参数绑定
- 内部已经定义了很多的转换器,比如可以直接使用int类型来接收字符串
- 日期类型与字符串比较特殊,字符串的日期格式,有很多种
- 可以自己来定义是哪种格式的转换
- 可以在springmvc处理器适配器上自定义转换器Converter进行参数绑定。
步骤
把发布时间对象的字符串转换成日期接收
@Setter@Getter
public class User {
private String user_name;
private String user_age;
private String hobby[];
private Date birthdate;
}
1.创建转换器
package com.le.web.converter;
import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateConverter implements Converter<String, Date> {
@Override
public Date convert(String s) {
if(s != null){
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
try {
return simpleDateFormat.parse(s);
} catch (ParseException e) {
e.printStackTrace();
}
}
return null;
}
}
2.在springMVC核心配置文件当中自定义转换器
<bean id="dateConverter" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.le.web.converter.DateConverter"></bean>
</list>
</property>
</bean>
<!--注解驱动-->
<mvc:annotation-driven conversion-service="dateConverter"/>
post请求中文参数乱码
问题
当发送post请求时,带有中文的参数会发生乱码
解决办法
在web.xml当中添加一个过滤器
<!-- 解决post乱码问题 -->
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<!-- 设置编码参是UTF8 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】Flutter适配HarmonyOS 5知识地图,实战解析+高频避坑指南
【推荐】凌霞软件回馈社区,携手博客园推出1Panel与Halo联合会员
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何把ASP.NET Core WebApi打造成Mcp Server
· Linux系列:如何用perf跟踪.NET程序的mmap泄露
· 日常问题排查-空闲一段时间再请求就超时
· Java虚拟机代码是如何一步一步变复杂且难以理解的?
· 领域驱动的事实与谬误 一 DDD 与 MVC
· 如何把ASP.NET Core WebApi打造成Mcp Server
· 排行榜的5种实现方案!
· 在 .NET 中使用 Sqids 快速的为数字 ID 披上神秘短串,轻松隐藏敏感数字!
· 突破Excel百万数据导出瓶颈:全链路优化实战指南
· ChatGPT为何放弃WebSocket?揭秘EventSource的三大决胜优势