七 简单类型请求参数 – 基本数据类型及其包装类
1 请求参数名与方法的形参同名
// 根据请求路径接受参数
// http://localhost:8080/base/add?name=lisi&age=66
@RequestMapping("add")
public String add(String name,int age){
System.out.println(name+"===="+age);
return "forward";
}
2 请求参数名与方法的形参不同名
// http://localhost:8080/base/add1?name=lisi&age=66
// required = false 表示这个参数可以传也可以不传
// 此参数不传值时默认值为2,defaultValue = "2"
// 传递的话就用value的值(路径中传递的数据66)
@RequestMapping("add1")
public String add1(@RequestParam("name") String username,
@RequestParam(value = "age",defaultValue = "2",required = false) int userage){
System.out.println(username+"===="+userage);
return "forward";
}
3 乱码处理
① GET 方式传递中文参数乱码问题
Tomcat7 及之前手动修改配置文件,使用代码手动转;但若使用 Maven 的话,可以 pom.xml 中的 Tomcat 插件配置一行也可以解决,Tomcat8 已处理这个问题,不需要额外配置。
<uriEncoding>UTF-8</uriEncoding>
② POST 方法传递中文乱问题
web.xml 使用 Spring MVC 内置过滤器处理。需在前端控制器之前配置。(在请求进入前端控制器之前进行拦截)
<!-- 编码过滤器,仅针对 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>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
八 复合类型请求参数 – 数组及自定义类型
1 数组类型
// 请求路径 /del?ids=1&ids=2&ids=3
@RequestMapping("del")
public String del(int[] ids){
System.out.println(Arrays.toString(ids));
return "forward";
}
2 自定义类型
对于保存用户的需求,请求时携带用户名和密码参数,后端期望创建一个用户对象来封装这些参数值。
① 自定义类 – 用来封装参数值
public class User {
private Long id;
private String username;
private String password;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthday;
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", birthday=" + birthday +
'}';
}
}
② 编写处理方法
// 传递参数名与封装对象的属性名需一致
@RequestMapping("insert")
public String insert( User user){
System.out.println(user);
return "forward";
}
③ jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/base/add1" method="post">
姓名:<input type="text" name="name">
<input type="submit" value="提交">
</form>
<h3>增加用户</h3>
<form action="/base/insert" method="post">
<p> 账号:<input type="text" name="username"></p>
<p> 密码:<input type="text" name="password"></p>
<p> 生日:<input type="text" name="birthday"></p>
<p> <input type="submit" value="提交"></p>
</form>
</body>
</html>
底层 Spring MVC 根据请求地址对应调用处理方法,调用方法时发现要传递 User 类型的实参,Spring MVC 会反射创建 User 对象,之后通过请求参数名找对应的属性,为对象的属性设置对应的参数值。
九 处理日期类型请求参数
1 处理日期格式参数 – 方式1
// 在处理方法的 Date 类型的形参贴上 @DateTimeFormat 进行接收
// 形参的类型为 java.util.Date(将字符串类型转时间类型)
// 请求路径 /date1&birth=2024-01-01
@RequestMapping("date1")
public String date1(@DateTimeFormat(pattern = "yyyy-MM-dd") Date birth){
System.out.println(birth);
return "forward";
}
2 处理封装参数类字段 – 方式2
① User实体类
// 在封装参数类的 Date 类型的字段上贴 @DateTimeFormat
public class User {
// 省略其他字段
// 增加下面这个字段,并贴注解
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date date;
// 省略 setter getter toString
}
② 对应处理方法
// 直接用即可
@RequestMapping("insert")
public String insert( User user){
System.out.println(user);
return "forward";
}
十 ModelAttribute 注解
可贴在方法和形参上,形参前提是自定义类型,会存到模型中,可在视图中获取到。项目中常用于查询条件回显用(分页查询,条件查询回显,类似于存到作用域中)
1 处理方法
@RequestMapping("get")
public String get(@ModelAttribute("u") User u){
// 表示将参数u传递到作用域中,跳转页面可以获取该参数
System.out.println(u);
return "forward";
}
2 跳转后的JSP
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>请求接收完成页面</title>
</head>
<body>
<%--webapp/WEB-INF/views/目录下建立jsp--%>
<h3>请求处理完毕页面</h3>
<p>
账号:${u.username}
密码:${u.password}
</p>
</body>
</html>
3 存入数据的JSP
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>增加用户</h3>
<form action="/base/get" method="post">
<p> 账号:<input type="text" name="username"></p>
<p> 密码:<input type="text" name="password"></p>
<p> 生日:<input type="text" name="birthday"></p>
<p> <input type="submit" value="提交"></p>
</form>
</body>
</html>
十一 文件上传
1 上传页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<%--新建src/main/webapp/upload.jsp,请求数据类型必须是:multipart/form-data,且请求方式是 POST--%>
<title>Title</title>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
图片:<input type="file" name="pic">
<input type="submit" value="上传">
</form>
</body>
</html>
2 创建对应的Controller
@Controller
public class UploadController {
@Autowired
ServletContext servletContext;
/*文件上传*/
@RequestMapping("upload")
public String upload(Part pic){
// 通过Part对象获取数据
String name = pic.getName();
String contentType = pic.getContentType();
System.out.println(name);
System.out.println(contentType);
// 只看控制台输出即可
return "";
}
}
3 spring-mvc中配置文件上传解析器
<!--上传文件解析器 bean 名称固定,必须为 multipartResolver,前端控制器底层根据名字进行加载-->
<bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver">
</bean>
4 设置文件上传大小 – web.xml
<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:mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<multipart-config>
<max-file-size>52428800</max-file-size>
<max-request-size>52428800</max-request-size>
</multipart-config>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
十二 拦截器
1 作用
过滤器(过滤用户请求,进入前端控制器之前,拦截jsp,静态资源)在拦截器(处理器执行链,进入前端控制器之后,拦截访问后台的请求,不拦截jsp,静态资源)之前,拦截器是Spring MVC 提供的,配置在 Spring MVC 配置文件中,被 Spring 容器管理,主要用于对请求访问控制器的方法进行拦截,常用于登录与权限判断。
2 自定义拦截器
// 定义一个类实现 HandlerIntercepto 接口
public class MyIntercepter implements HandlerInterceptor {
// 处理方法之前,第一个方法有返回值
// 返回 false,就被拦截;返回 true 就放行
/*请求进入Controller控制器之前执行拦截*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("请求进入了前端控制器但是没有进入后台controller");
return true;
}
/*请求从Controller控制器出来,在渲染页面之前进行执行拦截*/
/*此时视图解析器还没有对 ModelAndView 对象进行解析*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("从controller返回但是还没有页面解析ModelAndView");
}
/*完成响应并对 ModelAndView 对象解析完毕后*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("请求执行完毕。。。。");
}
}
3 配置拦截器的拦截规则 – spring-mvc.xml
<!--拦截器拦截规则:可以配置多个拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--拦截的路径,/** 表示拦截所有路径以及子路径-->
<mvc:mapping path="/**"/>
<!--不需要拦截的路径,如登录页面等,可写多个-->
<mvc:exclude-mapping path="/base/add"/>
<mvc:exclude-mapping path="/base/get"/>
<!--自定义拦截器对象-->
<bean class="cn.tj.intercepter.MyIntercepter"></bean>
</mvc:interceptor>
</mvc:interceptors>
十三 核心组件
1 前端控制器 DispatcherServlet
框架提供,需要在 web.xml 中配置。作用:接受请求,处理响应结果,转发器,中央处理器。
2 处理器映射器 HandlerMapping
框架提供。作用,更具请求的 URL 找到对应的 Handler。
3 处理器适配器 HandlerAdapter
框架提供。作用:调用处理器(Handler/Controller)的方法。
4 处理器 Handler(Controller)
必须按照 HandlerAdapter 的规范去开发。作用:接收用户请求数据,调用业务方法处理请求。
5 视图解析器 ViewResolver
框架或者第三方提供。作用:视图解析,把逻辑视图名称解析成真正的物理视图。支持多种视图技术 Velocity、FreeMarker、JSP 等。
6 视图
作用:把数据展现给用户。
7 开发步骤
1.web.xml 配置前端控制器
2.mvc.xml 配置处理器映射器、处理适配器、视图解析器(默认可省略配置)
3.结合需求开发
4.先开发 Contoller,进行配置
5.开发 JSP
十四 SpringMVC执行流程分析
1 发送请求
当用户发送一个 HTTP 请求(如 GET、POST 等)到服务器时,Servlet 容器(如 Tomcat)会捕获到这个请求。如果你的应用程序配置了 Spring MVC 的前端控制器(通常是 DispatcherServlet
),Servlet 容器会将请求转发给这个前端控制器(位于web.xml文件中)。
2 请求分发
DispatcherServlet
接收请求后,会根据请求的 URL 查找对应的 HandlerMapping
(处理器映射器 主要作用为去后台验证有无访问路径,有的话进入处理器执行链(拦截器)。进行处理,之后再返回给前端控制器,它不会调用方法)。
3 控制器处理
再返回DispatcherServlet
(前端控制器),前端控制器将请求发往HandlerAdapter
(处理器适配器,主要进行后台方法的调用,crud,执行Handler处理器的方法,也就是Controller
,当 Controller
被选中后,它会处理请求,并可能调用 Service 层进行业务处理,再进一步可能调用 DAO 层与数据库交互。),通过springMVC的一个内置对象ModelAndView
将调用结果返回给HandlerAdapter,该对象包含了模型数据和视图名称。HandlerAdapter
处理器适配器再将ModelAndView
对象返回给前端控制器
4 视图解析
DispatcherServlet
拿到 ModelAndView 对象后,会将其传递给 ViewResolver
(视图解析器)。ViewResolver 会根据 ModelAndView 中的视图名称解析出具体的 View(视图)对象与View对象,将model对象渲染到view对象上,也就是将数据渲染到jsp页面上,最终展示给客户端。视图对象通常是 JSP、Thymeleaf、FreeMarker 等模板引擎的实例。
5 视图渲染
视图对象使用 ModelAndView 中的模型数据来渲染视图。
渲染过程可能涉及到模板引擎将数据和模板合并成 HTML 页面。
6 响应输出
渲染完成后,视图对象将结果(通常是 HTML 页面)作为 HTTP 响应返回给客户端。
DispatcherServlet
将这个响应发送回 Servlet 容器,并最终由容器发送给客户端浏览器。
7 拦截器与过滤器
在整个流程中,可能还涉及到拦截器(Interceptor)和过滤器(Filter)的处理。
拦截器可以在请求处理之前或之后执行一些操作,如权限检查、日志记录等。
过滤器在请求到达 DispatcherServlet 之前或响应离开 DispatcherServlet 之后执行,常用于执行一些通用的任务,如字符集设置、请求和响应的预处理等。