目录
一、SpringMVC。
(1)SpringMVC快速入门。
(2) SpringMVC组件、注解解析。
(3)SpringMVC的数据响应方式。
(1)页面跳转。
(2)回写数据。
(3)
标签的作用:
(4)
(4)获取请求参数。
(5)请求数据乱码问题。
(6)参数绑定注解。
(7)获取Restful风格的参数。
(8)自定义类型转换器。
(9)获取Servlet相关API (请求头等)。
(10)文件上传。
(1)文件上传客户端的三要素。
(2)单文件上传。
(3)多文件上传。
(11)知识总结。
@Controller是Spring框架中的一个注解,用于标注一个类为控制器。在Spring MVC应用程序中,控制器类负责接收和处理浏览器发来的请求,然后调用相应的业务逻辑进行处理,并最终返回响应结果。
DispatcherServlet
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:spring-mvc.xml
1
DispatcherServlet
/
@Controller//没有这个注解访问不了这个类的方法,标识这个类作为springMVC的控制器
@RequestMapping("/user")//不在类上面使用这个注解:http://localhost:8080/quick,在类上使用注解:http://localhost:8080/user/quick
public class UserController {
// @RequestMapping(value = "/quick",method = RequestMethod.GET,params = {"username","address","age!=100"})
@RequestMapping(value = "/quick")
public String save(){
System.out.println("Controller save running....");
return "success";
}
@RequestMapping(value = "/quick2")
public ModelAndView save2(){
/**
* Model:模型 作用封装数据
* View: 视图 作用展示数据
*/
ModelAndView modelAndView = new ModelAndView();
//设置视图名称
modelAndView.addObject("username","itcast");
modelAndView.setViewName("success");
return modelAndView;
}
@RequestMapping(value = "/quick3")
public ModelAndView save3(ModelAndView modelAndView){
modelAndView.addObject("username","itheima");
modelAndView.setViewName("success");
return modelAndView;
}
}
多个对象(list
以下是一个示例代码示意,演示了如何使用内部转换器将多个Java对象转换为JSON数组:
// 控制器方法,返回Java对象集合
@RequestMapping("/users")
@ResponseBody
public List getUsers() {
// 创建两个Java对象
User user1 = new User();
User user2 = new User();
// 将Java对象添加到集合中
List users = new ArrayList<>();
users.add(user1);
users.add(user2);
return users; // 返回Java对象集合
}
```
上述代码中,控制器方法getUsers返回一个Java对象集合,其中包含两个子对象user1和user2。在方法的注解@ResponseBody中,不需要显式地指定输出的格式为JSON,Spring MVC会自动使用内部转换器将Java对象集合转换为JSON数组输出。
单个对象(Map):如果在Spring MVC中返回的是一个Map类型,那么Spring MVC会将其转换为一个JSON对象。其中,Map的key将被转换为JSON对象的属性名称,value将被转换为JSON对象的属性值。
以下是一个示例代码示意,演示了如何使用Map类型将多个Java对象转换为JSON对象:
// 控制器方法,返回Java对象Map
@RequestMapping("/users")
@ResponseBody
public Map getUsers() {
// 创建两个Java对象
User user1 = new User();
user1.setId(1);
user1.setName("Alice");
User user2 = new User();
user2.setId(2);
user2.setName("Bob");
// 将Java对象添加到Map中
Map users = new HashMap<>();
users.put("user1", user1);
users.put("user2", user2);
return users; // 返回Java对象Map
}
上述代码中,控制器方法getUsers返回一个Java对象Map,其中包含两个子对象user1和user2。在方法的注解@ResponseBody中,不需要显式地指定输出的格式为JSON,Spring MVC会自动将Java对象Map转换为JSON对象输出。
标签的作用:
不添加这个标签,那么控制类无法被访问(如果有这个
)。
需要开启 Spring MVC 的注解驱动功能的情况包括但不限于以下几种:
@Controller
、@RequestMapping
、@RequestParam
等 Spring MVC 相关注解;@ResponseBody
注解将方法返回值转换成指定的格式(如 JSON、XML)并输出到响应体中;@Valid
和 @ModelAttribute
实现表单数据绑定和校验;@ExceptionHandler
处理全局异常;@PathVariable
处理 URL 中的占位符。如果不使用mvc:annotation-driven配置标签,那么Spring MVC将无法自动识别和处理控制器中的注解,无法正确地将请求映射到控制器方法上。这样,浏览器将无法访问控制器。
是 Spring MVC 的配置标签之一,用于开启 Spring MVC 框架的注解支持。该标签会自动注册必要的 HandlerMapping 和 HandlerAdapter 等组件,json自动转换等功能,以支持使用 @Controller、@RequestMapping、@RequestParam 等注解来定义请求处理器和处理方法等。
标签还可以通过设置各种属性来控制框架的行为,其中 conversion-service
属性用于显式地指定一个 ConversionService 实例,以支持自定义类型转换。如果没有设置 conversion-service
属性,Spring MVC 框架会通过检查应用上下文中的 bean,自动搜索一个名为 "conversionService" 的 ConversionService 类型的 Bean,并将其作为默认的 ConversionService 实例来使用。
因此,
与
的主要区别在于前者显式地指定了一个名为 "conversionService" 的 Bean 作为 ConversionService 实例,而后者则使用默认的 ConversionService 实例。
当应用中存在多个 ConversionService Bean 时,显式地指定 conversion-service
属性可以确保使用正确的 ConversionService 实例,防止出现错误的类型转换。
“
1、在 Web 应用程序中,静态资源(如 CSS、JavaScript、图片等)通常存放在某个特定的目录中,这些资源的请求不需要经过 Spring MVC 的控制器处理,而是直接由 Servlet 容器中的默认 Servlet 来处理。
2、当我们在 Spring MVC 的配置文件中添加了
静态资源:对于静态资源来说,例如图片、CSS文件、JS文件等,这些资源文件一般都是固定的,不需要进行逻辑处理,因此在前端控制器中会先进行路径匹配,将请求映射到对应的静态资源路径上,然后交由 Web 服务器的默认 Servlet 处理并直接返回给客户端。这样可以避免不必要的性能开销,提高 Web 应用程序的响应速度。
动态资源:而对于动态资源来说,例如需要进行业务逻辑处理的请求,这些资源需要通过前端控制器进行处理,并根据具体的业务需求生成相应的响应结果返回给客户端。通常,在前端控制器中会进行一系列的处理,包括路由分发、参数解析、业务处理、模板渲染等,最终将处理结果响应给客户端。
因此,虽然静态资源和动态资源都要经过前端控制器进行处理,但是它们的处理方式有所区别。对于静态资源来说,前端控制器的主要作用是进行路径匹配和映射,然后交由 Web 服务器的默认 Servlet 处理;而对于动态资源来说,前端控制器则需要进行一系列的逻辑处理,生成相应的响应结果返回给客户端。
解决方法(二选其一就行):
1、添加
2、删除
在SSM框架中,如果控制器方法需要传入一个参数,但客户端在发送请求时未传入该参数,则这个参数将被设置为null值。当控制器方法接收到请求时,SpringMVC框架会自动将请求中的参数绑定到控制器方法的参数上,如果请求中没有传递该参数,则方法参数会被设置为null值,而不会导致方法执行失败。
因此,如果在控制器方法中对传入的参数进行了非空判断,即使客户端未传递该参数,控制器方法也不会因为参数缺失而执行失败。
总之,在SSM框架中,如果控制器方法需要传入一个参数,但客户端在发送请求时未传入该参数,SpringMVC框架会将该参数设置为null值,不会导致方法执行失败,但需要注意参数的空指针异常问题。
mapping表示访问的路径符合这个,location是符合之后去这个位置找对应资源
注意:
/js/**:这个路径是一个通配符路径,表示以 /js/ 开头的任何路径和文件,包括 /js/ 目录下的所有子目录和文件。其中, ** 表示匹配任意多级子目录,也就是可以匹配 /js/ 目录下的任何深度的子目录。这个路径在许多 Web 开发框架和服务器软件中常常用来匹配前端 JavaScript 文件,例如浏览器端的脚本库、框架等等,这些文件通常放置在以 /js/ 开头的路径下。
/js/*:这个路径是一个通配符路径,表示以 /js/ 开头的任何子路径,但不包括子目录及文件。其中, * 表示通配符,匹配任意数量的字符。因此 /js/* 可以匹配 /js/ 目录下的任何直接子目录或文件,但不能匹配 /js/ 目录下的深度超过 1 层的子目录和文件。这个路径也常常用于匹配前端 JavaScript 文件的目录路径,例如可以用来匹配 /js/ 目录下的具体某个脚本文件。
@Controller//没有这个注解访问不了这个类的方法,标识这个类作为springMVC的控制器
@RequestMapping("/user")//不在类上面使用这个注解:http://localhost:8080/quick,在类上使用注解:http://localhost:8080/user/quick
public class UserController {
// @RequestMapping(value = "/quick",method = RequestMethod.GET,params = {"username","address","age!=100"})
@RequestMapping(value = "/quick")
public String save(){
System.out.println("Controller save running....");
return "success";
}
@RequestMapping(value = "/quick2")
public ModelAndView save2(){
/**
* Model:模型 作用封装数据
* View: 视图 作用展示数据
*/
ModelAndView modelAndView = new ModelAndView();
//设置视图名称
//在jsp页面中,Success!${username}
modelAndView.addObject("username","itcast");
modelAndView.setViewName("success");
return modelAndView;
}
@RequestMapping(value = "/quick3")
//当用户访问 /quick3 路径时,Spring MVC 框架会根据配置的 HandlerMapping 找到对应的控制器方法 save3()。
// 由于该方法使用了 ModelAndView 类型的参数,因此框架会在调用该方法时自动创建一个 ModelAndView 对象,并将其作为实参传递给该方法。
public ModelAndView save3(ModelAndView modelAndView){
modelAndView.addObject("username","itheima");
modelAndView.setViewName("success");
return modelAndView;
}
@RequestMapping(value = "/quick4")
public String save4(Model model){
model.addAttribute("username","tan");
return "success";
}
@RequestMapping(value = "/quick5")
public String save5(HttpServletRequest request){
request.setAttribute("username","博学谷");
return "success";
}
@RequestMapping(value = "/quick6")
public void save6(HttpServletResponse response) throws IOException {
response.setContentType("text/html;charset=utf-8");
response.getWriter().print("博学谷
");
}
@RequestMapping(value = "/quick7",produces = "text/html;charset=utf-8")//解决中文乱码问题(如果不是用响应对象回写,那么在响应对象中设置是没用的)
@ResponseBody //告知SpringMVC框架,不进行视图跳转,直接进行数据响应
public String save7(HttpServletResponse response) throws IOException {
return "博学谷";
}
@RequestMapping(value = "/quick8",produces = "text/html;charset=utf-8")//解决中文乱码问题(如果不是用响应对象回写,那么在响应对象中设置是没用的)
@ResponseBody //告知SpringMVC框架,不进行视图跳转,直接进行数据响应
public String save8(){
// return "{msg:'博学谷'}";
return "{\"username\":\"zhangsan\",\"age\":18}";
}
@RequestMapping(value = "/quick9",produces = "text/html;charset=utf-8")//解决中文乱码问题(如果不是用响应对象回写,那么在响应对象中设置是没用的)
@ResponseBody //告知SpringMVC框架,不进行视图跳转,直接进行数据响应
public String save9() throws JsonProcessingException {
User user = new User();
user.setUsername("zhangsan");
user.setAge(18);
//使用json的转换工具将对象转换成JSON格式字符串再返回
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(user);
}
@RequestMapping(value = "/quick10",produces = "application/json;charset=utf-8")//解决中文乱码问题(如果不是用响应对象回写,那么在响应对象中设置是没用的)
@ResponseBody //告知SpringMVC框架,不进行视图跳转,直接进行数据响应
//期望SpringMVC自动将User转换成json格式的字符串
public User save10(){
User user = new User();
user.setUsername("zhangsan");
user.setAge(18);
return user;
}
@RequestMapping(value = "/quick11",produces = "application/json;charset=utf-8")//解决中文乱码问题(如果不是用响应对象回写,那么在响应对象中设置是没用的)
@ResponseBody //告知SpringMVC框架,不进行视图跳转,直接进行数据响应
//期望SpringMVC自动将User转换成json格式的字符串
public void save11(String username,int age){
System.out.println(username);
System.out.println(age);
}
@RequestMapping(value = "/quick12",produces = "application/json;charset=utf-8")//解决中文乱码问题(如果不是用响应对象回写,那么在响应对象中设置是没用的)
@ResponseBody //告知SpringMVC框架,不进行视图跳转,直接进行数据响应
//期望SpringMVC自动将User转换成json格式的字符串
public void save12(User user){
System.out.println(user);
}
@RequestMapping(value = "/quick13",produces = "application/json;charset=utf-8")//解决中文乱码问题(如果不是用响应对象回写,那么在响应对象中设置是没用的)
@ResponseBody //告知SpringMVC框架,不进行视图跳转,直接进行数据响应
//期望SpringMVC自动将User转换成json格式的字符串
public void save13(String[] strs){
List list = Arrays.asList(strs);
System.out.println(list);
}
@RequestMapping(value = "/quick14",produces = "application/json;charset=utf-8")//解决中文乱码问题(如果不是用响应对象回写,那么在响应对象中设置是没用的)
@ResponseBody //告知SpringMVC框架,不进行视图跳转,直接进行数据响应
//期望SpringMVC自动将User转换成json格式的字符串
public void save14(VO vo){
System.out.println(vo);
}
@RequestMapping(value = "/quick15",produces = "application/json;charset=utf-8")//解决中文乱码问题(如果不是用响应对象回写,那么在响应对象中设置是没用的)
@ResponseBody //告知SpringMVC框架,不进行视图跳转,直接进行数据响应
//期望SpringMVC自动将User转换成json格式的字符串
public void save15(@RequestBody List userList){//只有ajax才能访问成功(json数据格式)
System.out.println(userList);
}
@RequestMapping(value = "/quick16",produces = "application/json;charset=utf-8",method = RequestMethod.GET)//解决中文乱码问题(如果不是用响应对象回写,那么在响应对象中设置是没用的)
@ResponseBody //告知SpringMVC框架,不进行视图跳转,直接进行数据响应
//期望SpringMVC自动将User转换成json格式的字符串
public void save16(@RequestParam(value = "name",required = false) String username){
System.out.println(username);
}
@RequestMapping(value = "/quick17/{name}",produces = "application/json;charset=utf-8",method = RequestMethod.GET)//解决中文乱码问题(如果不是用响应对象回写,那么在响应对象中设置是没用的)
@ResponseBody //告知SpringMVC框架,不进行视图跳转,直接进行数据响应
//期望SpringMVC自动将User转换成json格式的字符串
public void save17(@PathVariable(value = "name",required = true) String username){
System.out.println(username);
}
@RequestMapping(value = "/quick18",produces = "application/json;charset=utf-8",method = RequestMethod.GET)//解决中文乱码问题(如果不是用响应对象回写,那么在响应对象中设置是没用的)
@ResponseBody //告知SpringMVC框架,不进行视图跳转,直接进行数据响应
//期望SpringMVC自动将User转换成json格式的字符串
public void save18(Date date){
System.out.println(date);
}
@RequestMapping(value = "/quick19",produces = "application/json;charset=utf-8",method = RequestMethod.GET)//解决中文乱码问题(如果不是用响应对象回写,那么在响应对象中设置是没用的)
@ResponseBody //告知SpringMVC框架,不进行视图跳转,直接进行数据响应
//期望SpringMVC自动将User转换成json格式的字符串
public void save19(HttpServletRequest request, HttpServletResponse response, HttpSession session){
System.out.println(request);
System.out.println(response);
System.out.println(session);
}
@RequestMapping(value = "/quick20",produces = "application/json;charset=utf-8",method = RequestMethod.GET)//解决中文乱码问题(如果不是用响应对象回写,那么在响应对象中设置是没用的)
@ResponseBody //告知SpringMVC框架,不进行视图跳转,直接进行数据响应
//期望SpringMVC自动将User转换成json格式的字符串
public void save20(@RequestHeader(value = "User-Agent",required = false) String user_agent){
System.out.println(user_agent);
}
@RequestMapping(value = "/quick21",produces = "application/json;charset=utf-8",method = RequestMethod.GET)//解决中文乱码问题(如果不是用响应对象回写,那么在响应对象中设置是没用的)
@ResponseBody //告知SpringMVC框架,不进行视图跳转,直接进行数据响应
//期望SpringMVC自动将User转换成json格式的字符串
public void save21(@CookieValue(value = "JSESSIONID",required = false) String jsessionId){
System.out.println(jsessionId);
}
@RequestMapping(value = "/quick22",produces = "application/json;charset=utf-8")//解决中文乱码问题(如果不是用响应对象回写,那么在响应对象中设置是没用的)
@ResponseBody //告知SpringMVC框架,不进行视图跳转,直接进行数据响应
//期望SpringMVC自动将User转换成json格式的字符串
public void save22(String username, MultipartFile uploadFile, MultipartFile uploadFile2) throws IOException {
System.out.println(username);
//获取上传文件的名称
String originalFilename = uploadFile.getOriginalFilename();
uploadFile.transferTo(new File("C://"+originalFilename));
String originalFilename2 = uploadFile2.getOriginalFilename();
uploadFile2.transferTo(new File("C://"+originalFilename2));
}
@RequestMapping(value = "/quick23",produces = "application/json;charset=utf-8")//解决中文乱码问题(如果不是用响应对象回写,那么在响应对象中设置是没用的)
@ResponseBody //告知SpringMVC框架,不进行视图跳转,直接进行数据响应
//期望SpringMVC自动将User转换成json格式的字符串
public void save23(String username, MultipartFile[] uploadFile) throws IOException {
System.out.println(username);
//获取上传文件的名称
/*for (int i = 0; i < uploadFile.length; i++) {
String originalFilename = uploadFile[i].getOriginalFilename();
uploadFile[i].transferTo(new File("C://"+originalFilename));
}*/
for (MultipartFile multipartFile : uploadFile) {
String originalFilename = multipartFile.getOriginalFilename();
multipartFile.transferTo(new File("C://"+originalFilename));
}
}
}
@RequestMapping(value = "/quick11",produces = "application/json;charset=utf-8")//解决中文乱码问题(如果不是用响应对象回写,那么在响应对象中设置是没用的)
@ResponseBody //告知SpringMVC框架,不进行视图跳转,直接进行数据响应
//期望SpringMVC自动将User转换成json格式的字符串
public void save11(String username,int age){
System.out.println(username);
System.out.println(age);
}
注意:前端发送到服务器的数据都是字符串,上面方法中的参数int age其实就是通过转换器转换过来的,所以可以当成是前端发送来的日期参数经过我们自定义转换器就变成我们想要的参数。
假设控制器返回一个变量 name 的值为 "Tom",然后经过 Spring MVC 的 JSON 转换器处理之后,
变成的 JSON 数据格式将会是以下形式:
{ "name": "Tom"}
其中,name 是变量名,对应的值是 "Tom"。这个 JSON 格式的数据可以直接作为 HTTP
响应返回给客户端,供客户端进行进一步的处理和展示。
自定义转换器与内置转换器关系:共存。
自定义转换器和内置转换器并不是代替关系,而是在原有基础上增加一个。内置转换器是框架提供的默认实现,当你向转换服务中添加自定义转换器时,它们会与内置转换器一起被加载和使用,以提供更全面、灵活的转换和格式化支持。
Spring ConversionService
是一个通用类型转换服务,在应用程序中可以被用于执行各种类型间的转换。ConversionServiceFactoryBean
是 ConversionService
接口的一个工厂类,它可以通过配置转换器来创建一个可供应用程序使用的具体实现对象。在上述配置中,我们可以看到将 DateConverter
添加到 ConversionService
的转换器列表中,以支持将字符串类型的日期转换为 Java 中的 java.util.Date
类型(当然,还需要在相应的 Java 对象属性或方法参数上使用 @DateTimeFormat
或 @JsonFormat
等注解来指定日期的格式)。
你可以传入多个转换器,这些转换器可以是内置转换器、自定义转换器,甚至其他第三方框架提供的转换器。当需要对一个对象进行转换时,Spring 会按照转换器注册的顺序依次调用每个转换器的 convert()
方法,直到找到能够将源对象转换成目标类型的转换器为止。
笔记:自定义转换器:将客户端请求的字符串转换成方法中参数类型。