Hello,今天给各位童鞋们分享Spring MVC,赶紧拿出小本子记下来吧!
1.SpringMVC概述
1.1 三层架构
三层架构:
表现层:负责数据展示
业务层:负责业务处理
数据层:负责数据操作
1.2 MVC
MVC(Model View Controller),一种用于设计创建web应用程序表现层的模式
Model(模型):数据模型,用户封装数据
View(视图):页面视图,用户展示数据
jsp
html
Controller(控制器):处理用户交互的调度器,用于根据用户需求处理程序逻辑
Servlet
SpringMVC
2.入门案例
2.1 入门案例制作(重点)
XML版
XML+注解版(主体)
纯注解版(变形)
基于Spring环境开发
步骤:
导入坐标
2.定义业务层处理器Controller,并配置成spring的bean(等同于Servlet)
该bean的处理需要使用独立的配置文件扫描(XML版):spring-mvc.xml
3.web.xml中配置SpringMVC核心控制器,用于将请求转发到对应的具体业务处理器Controller中(等同于Servlet配置)
4.设定具体Controller的访问路劲(等同于Servlet在web.xml中的配置),并设置返回页面
此处记录一个问题:
问题现象:org.apache.catalina.core.ContainerBase.addChildInternal ContainerBase.addChild: start: org.apache.catalina…
问题解决:
查看web.xml是否无误,路径等是否有误,一个servlet不能同时使用xml和注解配置,否则也很会出现该错误;
查看项目lib目录是否存在,idea默认不创建,
进入Project Structures(ctrl+shift+alt+S)–>点击左侧Project Settings下的Artifacts。
点击中间栏项目,这里会两个文件,一个是:项目名:war(war压缩包),一个是项目名:war exploded(war未压缩包)。
点击war exploded项目,在右侧中第一栏Output Layout(项目发布生成的文件)下,展开WEB-INF文件夹,此时该目录下只有classes目录,无lib目录,自己手动创建一个lib目录,并点击上面+选择Library File添加maven导入的jar包
重启tomcat就解决了(我是这样解决的,不保证所有类似问题都能解决)
2.2 入门案例工作流程分析(重点)
服务器启动:
加载web.xml中的DispatcherServlet
读取spring-mvc.xml中的配置,加载所有com.itheima包中所有标记为bean的类
读取bean中方法上标注@RequestMapping("/save")的内容
处理请求:
DispatcherServlet配置拦截所有请求 /
使用请求路径与所有加载的@RequestMapping的内容进行比对
执行对应的方法
根据方法的返回值在webapp目录中查找对应的页面并展示
2.3 SpringMVC技术架构图(重点)
SpringMVC技术架构图:
DispatcherServlet:前端控制器,是整体流程控制中心,由其调用其他组件处理用户的请求,有效的降低了组件间的耦合性
HandleMapping:处理器映射器,负责根据用户请求找到对应具体的Handler处理器
Handler:处理器,业务处理的核心类,通常由开发者编写,描述具体的业务
HandlerAdapter:处理器适配器,通过它对处理器进行执行
ViewResolver:视图解析器,将处理结果生成View视图
View:视图,最终产出结果,常用视图入jsp、html
3.基础配置
3.1 Controller加载控制(重点)
SpringMVC的处理器对应bean必须按照规范格式开发,为避免加入无效的bean可通过bean加载过滤器进行包含设定或排除设定,表现层bean标注通常设为@Controller
type="annotation" expression="org.springframework.stereotype.Controller"/> 此处记录一个问题: 问题现象:启动tomcat完成时,idea弹窗提示“http://localhost:80/找不到应用程序” 解决方法:点击idea主界面运行图标旁下拉列表,选择Edit Configuration,进入配置界面,Open Browser选择一个固定浏览器,不要使用默认的浏览器(tomcat启动完成自动使用该浏览器访问) 制作案例:和前面案例一样,只需修改spring-mvc.xml配置文件: bean加载控制说明: 业务层与数据层bean加载由spring控制,参照spring课程加载方式 表现层bean加载由SpringMVC单独控制 表现层处理器bean使用注解@Controller声明 bean加载控制使用包含性过滤器 过滤器类型为通过注解进行过滤 过滤的注解名称为Controller 核心控制器拦截的是所有请求,需要对非普通资源请求进行放行,通过配置放行资源实现 使用简化格式可以放行所有普通资源调用,无需一一枚举 还是之前案例内容,只需做如下修改: 在webap下新建img目录,并导入一张图片 修改spring-mvc.xml配置文件: 注意:webapp下img目录需设置为resources目录,否则无法访问 SpringMVC提供专用的中文字符过滤器,用于处理乱码问题。在web.xml进行如下配置: 使用注解形式转化SpringMVC核心配置文件为配置类 @Configuration @ComponentScan(value = "com.itheima", excludeFilters = @ComponentScan.Filter( type = FilterType.ANNOTATION, classes = Controller.class) ) public class SpringMvcConfiguration { } 操作过程: 创建配置类 2. 基于servlet3.0规范,自定义servlet容器初始化配置类,加载SpringMVC核心配置类 3. 静态资源加载过滤(注解版) 配置类实现WebMvcConfigurer接口,覆盖addResourceHandlers方法,在其中对具体的资源进行设定 @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/img/**").addResourceLocations("/img/"); registry.addResourceHandler("/js/**").addResourceLocations("/js/"); registry.addResourceHandler("/css/**").addResourceLocations("/css/"); } 或者覆盖configureDefaultServletHandling方法,使用Servlet默认过滤规则 @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } 4.中文乱码处理(注解版) Servlet3.0规范启动服务器时做的工作通过实现ServletContainerInitializer接口,在onStartup方法中完成,包括监听器注册、过滤器注册等 SpringMVC将传递的参数封装到处理器方法的形参中,达到快速访问参数的目的 访问URL:http://localhost/requestParam?name=itheima @RequestMapping("/requestParam") public String requestParam(String name) { System.out.println("name = "+name); return "page.jsp"; } 请求参数类型: 普通类型参数 POJO类型参数 数组类型参数 集合类型参数 普通类型参数 参数名与处理器方法形参名保持一致 访问URL:http://localhost/requestParam?name=itheima&age=20 参数设定 名称:@RequestParam 类型:形参注解 位置:处理器类中的方法形参前方 作用:绑定请求参数与对应处理方法形参间的关系 范例: @RequestMapping("/requestParam2") public String requestParam2(@RequestParam(value = "userName",required = true,defaultValue = "value") String name) { System.out.println("name = "+name); return "page.jsp"; } 注意:若设置了required = true,则在 浏览器URL地址栏必须加上参数,否则报错404。可以通过设置默认参数defaultValue = "value"避免未输入报错 访问路径:http://localhost/requestParam2?userName=zhangsan POJO类型参数 当POJO中使用简单类型属性时,参数名称与POJO类属性名保持一致 访问URL:http://localhost/requestParam?name=itheima&age=20 注意:这里需要注释掉上面的方法requestParam2,否者此处也需要给参数添加注解@RequestParam,否则报错500:java.lang.IllegalArgumentException: Name for argument type [java.lang.String] not available, and par… 参数冲突 当POJO类型属性与其他参数出现同名问题时,将被同时覆盖 访问URL:http://localhost/requestParam4?name=Jock&age=30 控制台打印结果:user = User{name=‘Jock’, age=30}, name = Jock 建议使用@RequestParam注解进行区分 注意:这里也需要注释上一个方法,否者报错500:java.lang.IllegalStateException: Method [requestParam4] was discovered in the .class file but cannot be resolved in the class object 复杂POJO类型参数 当POJO中出现对象属性时,参数名称与对象层次结构名称保持一致 访问URL:http://localhost/requestParam5?address.city=bejing public class Address { private String province; private String city; private String address; } public class User { private String name; private Integer age; private Address address; } @RequestMapping("/requestParam5") public String requestParam5(User user) { System.out.println("city = "+user.getAddress().getCity()); return "page.jsp"; } 控制台打印结果:city = bejing 当POJO中出现集合,保存简单数据,使用多个相同名称的参数为其进行赋值 URL:http://localhost/requestParam6?nick=Jock1&nick=Jock2&nick=Jocker 控制台打印结果:user = User{name=‘null’, age=null, address=null, nick=[Jock1, Jock2, Jocker]} 当POJO中出现List,保存对象数据,参数名称与对象层次结构名称保持一致,使用数组格式描述集合中对象的位置 URL:http://localhost/requestParam7?addresses[0].city=beijing&addresses[1].province=hebei @RequestMapping("/requestParam7") public String requestParam7(User user) { System.out.println("addresses = "+user.getAddresses()); return "page.jsp"; } 访问报错400:java.lang.IllegalArgumentException: 在请求目标中找到无效字符。有效字符在RFC 7230和RFC 3986中定义 百度解决方案:tomcat配置文件–>conf–>server.xml,修改内容 relaxedPathChars="|{}[],%" relaxedQueryChars="|{}[],%" /> 然而,修改了还是报该错误 当POJO中出现Map,保存对象数据,参数名称与对象层次结构名称保持一致,使用映射格式描述集合对象的位置 URL:http://localhost/requestParam8addressMap[‘home’].city=beijing&addressMap[‘job’].province=hebei 同样报错 数组类型参数 请求参数名与处理器方法形参名保持一致,且请求参数数量>1个 访问URL:http://localhost/requestParam9?nicks=jock&nicks=jocker 控制台打印结果:name = jock name = jocker 集合类型参数 保存简单类型数据,请求 参数名与处理器方法形参名保持一致,且请求参数数量>1个 访问URL:http://localhost/requestParam10?nick=jock&nick=jocker 控制台打印结果:nick = [jock, jocker] 注意:SpringMVC默认将List作为对象处理,赋值前先创建对象,然后将nick作为对象的属性进行处理。由于List是接口,无法创建对象,报错无法找到构造方法异常;修复类型可创建对象的ArrayList类型后,对象可以创建,但没有nick属性,因此数据为空。此时需要告知SpringMVC的处理器nick是一组数据,而不是一个单一数据。通过@RequestParam注解,将数量大于1个names参数打包成参数数组后,SpringMVC才能识别该数据格式,并判定形参类型是否为数组或集合,并按照数组或集合对象的形式操作数据。 SpringMVC对接收的数据进行自动类型转换,该工作通过Converter接口实现 标量转换器: StringToBooleanConverter String → Boolean ObjectToStringConverter Object → String StringToNumberConverterFactory String → Number(Integer、Long等) NumberToNumberConverterFactory Number子类型之间(Integer、Long、Double等) StringToCharsetConverter String → java.lang.Character NumberToCharacterConverter Number子类型(Integer、Long、Double等) → java.lang.Character CharacterToNumberFactory java.lang.Character → Number子类型(Integer、Long、Double等) StringToEnumConverterFactory String → Enum类型 EnumToStringConverter Enum类型 → String StringToLocaleConverter String → java.util.Local PropertiesToStringConverter java.util.Properties → String StringToPropertiesConverter String → java.util.Properties 集合、数组相关转换器 ArrayToCollectionConverter 数组 → 集合(List、Set) … 默认转换器 ObjectToObjectConverter Object间 IdToEntityConverter Id → Entity FallbackObjectToStringConverter Object → String 访问URL:http://localhost/requestParam11?date=2021/4/30 控制台打印结果:date = Fri Apr 30 00:00:00 CST 2021 当输入格式变换会报错,如:http://localhost/requestParam11?date=2021-4-30 日期类型格式转换 修改spring-mvc.xml配置使输入格式满足需求 日期类型格式转换(简化版) 名称:DateTimeFormat 类型:形参注解、成员变量注解 位置:形参前面 或 成员变量上方 作用:为当前参数或变量指定类型转换规则 范例: @RequestMapping("/requestParam12") public String requestParam12(@DateTimeFormat(pattern = "yyyy-MM-dd") Date date) { System.out.println("date = "+date); return "page.jsp"; } @DateTimeFormat(pattern = "yyyy-MM-dd") private Date birthday; 注意:依赖注解驱动支持 自定义类型转换器 自定义类型转换器,实现Converter接口,并指定转换前与转换后的类型 注册自定义转换器 通过注册自定义转换器,将该功能加入到SpringMVC的转换服务ConverterService中 名称:@RequestMapping 类型:方法注解 位置:处理器类中方法定义上方 作用:绑定请求地址与对应处理方法间的关系 范例: @RequestMapping("/requestURL") public String requestParam12(@DateTimeFormat(pattern = "yyyy-MM-dd") Date date) { System.out.println("date = "+date); return "page.jsp"; } 访问路径:/requestURL 请求返回的页面地址默认为当前路径 当设置了公共的访问前缀后,当前路径发生了变化,需要根据变化修改地址或修改访问页面的路径 访问root路径下的页面 @Controller public class UserController { @RequestMapping("/requestURL1") public String requestURL1() { System.out.println(); return "page.jsp"; } } 访问root路径下的user路径下的页面 @Controller @RequestMapping("/user") public class UserController { @RequestMapping("/requestURL2") public String requestURL2() { System.out.println(); return "/page.jsp"; } } @RequestMapping属性 常用属性 value method 响应方式:(数据流) 页面 HTML(页面) JSP(页面+数据) … 数据 JSON数据 XML数据 文本数据 文件 数据流 页面跳转设定: 当处理器方法的返回值类型为String类型,即可通过具体的返回字设置访问的页面 页面跳转方式: 转发(默认) @RequestMapping("/showPage1") public String showPage1() { System.out.println("user mvc controller is running..."); return "forward:page.jsp"; } 重定向 @RequestMapping("/showPage2") public String showPage2() { System.out.println("user mvc controller is running..."); return "redirect:page.jsp"; } 注意:页面访问地址所携带的/可以使用。但是在WEB-INF目录下的资源forward可以访问,而redirect不能访问。 页面访问快捷设定 展示页面的保存位置通常固定,且结构相似,可以设定通用的访问路径,简化页面配置格式(spring-mvc.xml) @RequestMapping("/showPage3") public String showPage3() { System.out.println("user mvc controller is running..."); return "page"; } 使用了简化配置,跳转页面名称前不能加forward,否则报错 @RequestMapping("/showPage4") public String showPage4() { System.out.println("user mvc controller is running..."); return "forward:page";//HTTP状态 404 - 未找到 } 页面访问快捷设定缺省页面: 如果设定了返回值,使用void类型,则默认使用访问路径作页面地址的前缀后缀 @RequestMapping("/showPage5") public void showPage5() { } 等同于 @RequestMapping("/showPage5") public String showPage5() { return "showPage5"; } 方式一:使用HttpServletRequest类型形参进行数据传递 @RequestMapping("showPageAndData1") public String showPageAndData1(HttpServletRequest request) { request.setAttribute("name","itheima"); return "page"; } 方式二:使用Model类型形参进行数据传递 @RequestMapping("showPageAndData2") public String showPageAndData2(Model model) { model.addAttribute("name","Jock"); Book book = new Book(); book.setName("SpringMVC入门案例"); book.setPrice(66.66); model.addAttribute(book); return "page"; } 方式三:使用ModelAndView类型形参进行数据传递,将该对象作为返回字传递给调用者 重定向: @RequestMapping("showPageAndData5") public ModelAndView showPageAndData5(ModelAndView modelAndView) { modelAndView.setViewName("redirect:page");//等同于return "redirect:page.jsp"; return modelAndView; } 注意:使用重定向需要注释前面设置的spring-mvc.xml配置中添加的WEB-INF/page目录,因为WEB-INF有安全访问,重定向不能访问。 导入json坐标pom.xml 运行tomcat可能会报错:rg.apache.catalina.core.StandardContext.filterStart 启动过滤器异常 java.lang.ClassNotFoundException: org.springframework.web.filter.CharacterEncodingFilter 解决方案:在上面讲过,Project Structures(ctrl+shift+alt+S)–> Project Settings下的Artifact --> swar exploded项目 --> Output Layout --> 展开WEB-INF–>手动创建一个lib目录(由于上面已经创建了,此处不再创建),并点击上面+选择Library File添加maven导入的jar包。重启tomcat就解决了 返回数据: 方式一:使用response对象完成数据返回 @RequestMapping("/showData1") public void showData1(HttpServletResponse response) throws IOException { response.getWriter().write("message"); } 方式二:(简化格式) @RequestMapping("/showData2") @ResponseBody public String showData2() { return "message"; } 返回JSON数据: 方式一:基于response返回数据的简化格式,返回json数据 @RequestMapping("/showData2") @ResponseBody public String showData2() { return "{'name':'Jock'}"; } 方式二(对象):使用SpringMVC提供的消息类型转换器将对象与集合数据自动转换为json数据 spring-mvc.xml添加注解驱动: 方式三(集合):使用SpringMVC注解驱动简化配置 注解驱动格式 @Configuration @ComponentScan("com.itheima") public class SpringMVCConfiguration { } SpringMVC提供访问原始Servlet接口API的功能,通过形参声明即可 打印结果: org.apache.catalina.connector.RequestFacade@1f787c3e org.apache.catalina.connector.ResponseFacade@45b7d257 org.apache.catalina.session.StandardSessionFacade@411f594e Head数据获取: 名称:@RequestHeader 类型:形参注解 位置:处理器类中的方法形参前方 作用:绑定请求头数据与对应处理方法形参间的关系 范例: 打印结果:3AE4C46FC4AE80D62FAA29DA2DDD383F Session数据获取: 名称:@SessionAttribute 类型:形参注解 位置:处理器类中的方法形参前方 作用:绑定请求Session数据与对应处理方法形参间的关系 范例: 打印结果:itheima Session数据设置(了解): 名称:@SessionAttributes 类型:类注解 位置:处理器类上方 作用:声明放入Session范围的变量名称,适用于Model类型数据传参 范例: 数据的来源不同,对应的处理策略要进行区分 Head Cookie … SpringMVC使用策略模式进行处理分发 顶层接口:HandlerMethodArgumentResolver 实现类:… 好啦,今天的文章就到这里,希望能帮助到屏幕前迷茫的你们!3.2 静态资源加载
3.3 中文乱码处理
3.4 注解驱动
4.请求
4.1 请求参数(重点)
4.2 类型转换器
4.3 请求映射(重点)
5.响应
5.1 无数据跳转页面
5.2 带数据跳转页面(重点)
5.3 存数据返回(JSON)(重点)
6.Servlet相关接口
6.1 HttpServletRequest
6.2 HttpServletResponse
6.3 HttpSession
6.4 Head
6.5 Session
6.6 注解式参数数据封装底层原理