目录
传统方式操作资源 :通过不同的参数来实现不同的效果!方法单一,post 和 get
使用Restful操作资源 :可以通过不同的请求方式来实现不同的效果!如下:请求地址一样,但是功能可以不同!
ssm:mybatis + Spring + SpringMVC MVC三层架构
JavaSE:认真学习,老师带,入门快
JavaWeb:认真学习,老师带,入门快
SSM框架:研究官方文档,锻炼自学能力,锻炼笔记能力,锻炼项目能力
SpringMVC + Vue + SpringBoot + SpringCloud + Linux
SpringMVC:SpringMVC的执行流程!【重点】
SpringMVC:SSM框架整合!
Model(模型):数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或JavaBean组件(包含数据和行为),不过现在一般都分离开来:Value Object(数据Dao) 和 服务层(行为Service)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。
View(视图):负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。
Controller(控制器):接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。也就是说控制器做了个调度员的工作。
最典型的MVC就是JSP + servlet + javabean的模式。
在web早期的开发中,通常采用的都是Model1。
Model1中,主要分为两层,视图层和模型层。
Model1优点:架构简单,比较适合小型项目开发;
Model1缺点:JSP职责不单一,职责过重,不便于维护;
假设:你的项目的架构,是设计好的,还是演进的?
Model2把一个项目分成三部分,包括视图、控制、模型。
用户发请求
Servlet接收请求数据,并调用对应的业务逻辑方法
业务处理完毕,返回更新后的数据给servlet
servlet转向到JSP,由JSP来渲染页面
响应给前端更新后的页面
职责分析:
Controller:控制器
取得表单数据
调用业务逻辑
转向指定的页面
Model:模型
业务逻辑
保存数据的状态
View:视图
显示页面
Model2这样不仅提高的代码的复用率与项目的扩展性,且大大降低了项目的维护成本。
Model 1模式的实现比较简单,适用于快速开发小规模项目,Model1中JSP页面身兼View和Controller两种角色,将控制逻辑和表现逻辑混杂在一起,从而导致代码的重用性非常低,增加了应用的扩展性和维护的难度。Model2消除了Model1的缺点。
1.新建一个Maven工程当做父工程!pom依赖!
-
- <dependencies>
- <dependency>
- <groupId>junitgroupId>
- <artifactId>junitartifactId>
- <version>4.12version>
- dependency>
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-webmvcartifactId>
- <version>5.1.9.RELEASEversion>
- dependency>
- <dependency>
- <groupId>javax.servletgroupId>
- <artifactId>servlet-apiartifactId>
- <version>2.5version>
- dependency>
- <dependency>
- <groupId>javax.servlet.jspgroupId>
- <artifactId>jsp-apiartifactId>
- <version>2.2version>
- dependency>
- <dependency>
- <groupId>javax.servletgroupId>
- <artifactId>jstlartifactId>
- <version>1.2version>
- dependency>
- dependencies>
2.建立一个Moudle:springmvc-01-servlet,添加Web app的支持!
3.导入servlet 和 jsp 的jar依赖
- <dependency>
- <groupId>javax.servletgroupId>
- <artifactId>servlet-apiartifactId>
- <version>2.5version>
- dependency>
- <dependency>
- <groupId>javax.servlet.jspgroupId>
- <artifactId>jsp-apiartifactId>
- <version>2.2version>
- dependency>
4.编写一个Servlet类,用来处理用户的请求
- public class HelloServlet extends HttpServlet {
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- //1.获取前端参数
- String method = req.getParameter("method");
- if (method.equals("add")) {
- req.getSession().setAttribute("msg", "执行了add方法");
- }
- if (method.equals("delete")) {
- req.getSession().setAttribute("msg", "执行了delete方法");
- }
-
- //2.调用业务层
-
- //3.视图转发
- req.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(req, resp);
- }
-
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- doGet(req, resp);
- }
- }
5.编写Hello.jsp,在WEB-INF目录下新建一个jsp的文件夹,新建hello.jsp
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>Kuangshentitle>
- head>
- <body>
- ${msg}
- body>
- html>
6.在web.xml中注册Servlet
- "1.0" encoding="UTF-8"?>
- <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
- version="4.0">
-
- <servlet>
- <servlet-name>HelloServletservlet-name>
- <servlet-class>com.kuang.HelloServletservlet-class>
- servlet>
- <servlet-mapping>
- <servlet-name>HelloServletservlet-name>
- <url-pattern>/userurl-pattern>
- servlet-mapping>
- web-app>
7.配置Tomcat,并启动测试
将url映射到java类或java类的方法 .
封装用户提交的数据 .
处理请求--调用相关的业务处理--封装响应数据 .
将响应的数据进行渲染 . jsp / html 等表示层数据
说明:
常见的服务器端MVC框架有:Struts、Spring MVC、ASP.NET MVC、Zend Framework、JSF;常见前端MVC框架:vue、angularjs、react、backbone;由MVC演化出了另外一些模式如:MVP、MVVM 等等....
Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架。
官方文档:Web on Servlet Stack
我们为什么要学习SpringMVC呢?
Spring MVC的特点:
轻量级,简单易学
高效 , 基于请求响应的MVC框架
与Spring兼容性好,无缝结合
约定优于配置
功能强大:RESTful、数据验证、格式化、本地化、主题等
简洁灵活
Spring的web框架围绕DispatcherServlet [ 调度Servlet ] 设计。
DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用Java 5或者以上版本的用户可以采用基于注解形式进行开发,十分简洁;
正因为SpringMVC好 , 简单 , 便捷 , 易学 , 天生和Spring无缝集成(使用SpringIoC和Aop) , 使用约定优于配置 . 能够进行简单的junit测试 . 支持Restful风格 .异常处理 , 本地化 , 国际化 , 数据验证 , 类型转换 , 拦截器 等等......所以我们要学习。
最重要的一点:使用的人多,使用的公司多。
Spring的web框架围绕DispatcherServlet设计。DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用Java 5或者以上版本的用户可以采用基于注解的controller声明方式。
Spring MVC框架像许多其他MVC框架一样, 以请求为驱动 , 围绕一个中心Servlet分派请求及提供其他功能,DispatcherServlet是一个实际的Servlet (它继承自HttpServlet 基类)。
具体执行流程:
1. 用户通过浏览器发起 HttpRequest 请求到前端控制器 (DispatcherServlet)。
2. DispatcherServlet 将用户请求发送给处理器映射器 (HandlerMapping)。
3. 处理器映射器 (HandlerMapping)会根据请求,找到负责处理该请求的处理器,并将其封装为处理器执行链 返回 (HandlerExecutionChain) 给 DispatcherServlet。
4. DispatcherServlet 会根据 处理器执行链 中的处理器,找到能够执行该处理器的处理器适配器(HandlerAdaptor) 。 --注,处理器适配器有多个
5. 处理器适配器 (HandlerAdaptoer) 会调用对应的具体的 Controller。
6. Controller 将处理结果及要跳转的视图封装到一个对象 ModelAndView 中并将其返回给处理器适配器 (HandlerAdaptor)。
7. HandlerAdaptor 直接将 ModelAndView 交给 DispatcherServlet ,至此,业务处理完毕。
8. 业务处理完毕后,我们需要将处理结果展示给用户。于是DisptcherServlet 调用 ViewResolver,将 ModelAndView 中的视图名称封装为视图对象。
9. ViewResolver 将封装好的视图 (View) 对象返回给 DIspatcherServlet。
10. DispatcherServlet 调用视图对象,让其自己 (View) 进行渲染(将模型数据填充至视图中),形成响应对象 (HttpResponse)。
11. 前端控制器 (DispatcherServlet) 响应 (HttpResponse) 给浏览器,展示在页面上。
1、新建一个Moudle , springmvc-02-hello , 添加web的支持!
2、确定导入了SpringMVC 的依赖!
3、配置web.xml , 注册DispatcherServlet
- "1.0" encoding="UTF-8"?>
- <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
- version="4.0">
-
-
-
- <servlet>
- <servlet-name>springmvcservlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
-
- <init-param>
- <param-name>contextConfigLocationparam-name>
- <param-value>classpath:springmvc-servlet.xmlparam-value>
- init-param>
-
- <load-on-startup>1load-on-startup>
- servlet>
-
-
-
- <servlet-mapping>
- <servlet-name>springmvcservlet-name>
- <url-pattern>/url-pattern>
- servlet-mapping>
-
- web-app>
4、编写SpringMVC 的 配置文件!名称:springmvc-servlet.xml : [servletname]-servlet.xml
说明,这里的名称要求是按照官方来的
- "1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- 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">
-
-
- beans>
5、添加 处理映射器
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
6、添加 处理器适配器
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
7、添加 视图解析器
-
- <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
-
- <property name="prefix" value="/WEB-INF/jsp/"/>
-
- <property name="suffix" value=".jsp"/>
- bean>
8、编写我们要操作业务Controller ,要么实现Controller接口,要么增加注解;需要返回一个ModelAndView,装数据,封视图;
- //注意:这里我们先导入Controller接口
- public class HelloController implements Controller {
-
- public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
- //ModelAndView 模型和视图
- ModelAndView mv = new ModelAndView();
-
- //封装对象,放在ModelAndView中。Model
- mv.addObject("msg","HelloSpringMVC!");
- //封装要跳转的视图,放在ModelAndView中
- mv.setViewName("hello"); //: /WEB-INF/jsp/hello.jsp
- return mv;
- }
-
- }
9、将自己的类交给SpringIOC容器,注册bean
-
- <bean id="/hello" class="com.kuang.controller.HelloController"/>
10、写要跳转的jsp页面,显示ModelandView存放的数据,以及我们的正常页面;
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>Kuangshentitle>
- head>
- <body>
- ${msg}
- body>
- html>
11、配置Tomcat启动测试!
可能遇到的问题:访问出现404,排查步骤:
查看控制台输出,看一下是不是缺少了什么jar包。
如果jar包存在,显示无法输出,就在IDEA的项目发布中,添加lib依赖!
重启Tomcat 即可解决!
小结:看这个估计大部分同学都能理解其中的原理了,但是我们实际开发才不会这么写,不然就疯了,还学这个玩意干嘛!我们来看个注解版实现,这才是SpringMVC的精髓。
1、新建一个Moudle,springmvc-03-hello-annotation 。添加web支持!
2、由于Maven可能存在资源过滤的问题,我们将配置完善
- <build>
- <resources>
- <resource>
- <directory>src/main/javadirectory>
- <includes>
- <include>**/*.propertiesinclude>
- <include>**/*.xmlinclude>
- includes>
- <filtering>falsefiltering>
- resource>
- <resource>
- <directory>src/main/resourcesdirectory>
- <includes>
- <include>**/*.propertiesinclude>
- <include>**/*.xmlinclude>
- includes>
- <filtering>falsefiltering>
- resource>
- resources>
- build>
3、在pom.xml文件引入相关的依赖:主要有Spring框架核心库、Spring MVC、servlet , JSTL等。我们在父依赖中已经引入了!
4、配置web.xml
注意点:
web.xml版本问题,要最新版!
- "1.0" encoding="UTF-8"?>
- <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
- version="4.0">
-
-
- <servlet>
- <servlet-name>springmvcservlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
-
- <init-param>
- <param-name>contextConfigLocationparam-name>
- <param-value>classpath:springmvc-servlet.xmlparam-value>
- init-param>
-
- <load-on-startup>1load-on-startup>
- servlet>
-
- <servlet-mapping>
- <servlet-name>springmvcservlet-name>
- <url-pattern>/url-pattern>
- servlet-mapping>
- web-app>
5、添加Spring MVC配置文件
在视图解析器中我们把所有的视图都存放在/WEB-INF/目录下,这样可以保证视图安全,因为这个目录下的文件,客户端不能直接访问。
注意点:
- "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"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/context
- https://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/mvc
- https://www.springframework.org/schema/mvc/spring-mvc.xsd">
-
-
- <context:component-scan base-package="com.kuang.controller"/>
-
- <mvc:default-servlet-handler/>
-
-
- <mvc:annotation-driven/>
-
- <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
- <property name="prefix" value="/WEB-INF/jsp/"/>
- <property name="suffix" value=".jsp"/>
- bean>
-
- beans>
6、创建Controller
编写一个Java控制类:com.kuang.controller.HelloController , 注意编码规范。
- package com.kuang.controller;
-
- import org.springframework.stereotype.Controller;
- import org.springframework.ui.Model;
- import org.springframework.web.bind.annotation.RequestMapping;
-
- @Controller
- @RequestMapping("/hello")
- public class HelloController {
-
- //真实访问地址:localhost:8080/项目名/hello/h1
- @RequestMapping("/h1")
- public String hello(Model model) {
-
- //封装数据
- //向模型中添加属性msg与值,可以在JSP页面中取出并渲染
- model.addAttribute("msg", "Hello,SpringMVCAnnotation");
-
- //WEB-INF/jsp/hello.jsp
- return "hello"; //会被视图解析器处理
- }
- }
@Controller是为了让Spring IOC容器初始化时自动扫描到;
@RequestMapping是为了映射请求路径,这里因为类与方法上都有映射所以访问时应该是/和/hello/h1;
方法中声明Model类型的参数是为了把Action中的数据带到视图中;
方法返回的结果是视图的名称hello,加上配置文件中的前后缀变成WEB-INF/jsp/hello.jsp。
7、创建视图层
在WEB-INF/ jsp目录中创建hello.jsp , 视图可以直接取出并展示从Controller带回的信息;
可以通过EL表示取出Model中存放的值,或者对象;
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>SpringMVCtitle>
- head>
- <body>
- ${msg}
- body>
- html>
8、配置Tomcat运行
小结:
实现步骤其实非常的简单:
新建一个web项目
导入相关jar包
编写web.xml , 注册DispatcherServlet
编写springmvc配置文件(开启注解扫描、mvc注解驱动、配置视图解析器)
接下来就是去创建对应的控制类 , controller
最后完善前端视图和controller之间的对应
测试运行调试。
使用SpringMVC必须配置的三大件:
处理器映射器、处理器适配器、视图解析器
通常,我们只需要手动配置视图解析器,而处理器映射器和处理器适配器只需要开启注解驱动即可,而省去了大段的xml配置。
控制器提负责供访问应用程序的行为,通常通过接口定义或注解定义两种方法实现。
控制器负责解析用户的请求并将其转换为一个模型。
在Spring MVC中一个控制器类可以包含多个方法
在Spring MVC中,对于Controller的配置方式有很多种
1.新建一个Moudle,springmvc-04-controller 。将刚才的03 拷贝一份, 我们进行操作!
2.编写一个Controller类,ControllerTest1
- //只要实现了Controller接口的类,就是一个控制器
- public class ControllerTest1 implements Controller {
- @Override
- public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
- ModelAndView mv = new ModelAndView();
-
- mv.addObject("msg", "ControllerTest1");
- mv.setViewName("test");
-
- return mv;
- }
- }
3.编写完毕后,去Spring配置文件中注册请求的bean;name对应请求路径,class对应处理请求的类
<bean id="/t1" class="com.kuang.controller.ControllerTest1"/>
4.编写前端test.jsp,注意在WEB-INF/jsp目录下编写,对应视图解析器
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>Titletitle>
- head>
- <body>
- ${msg}
- body>
- html>
5.配置Tomcat运行测试
说明:
实现接口Controller定义控制器是较老的办法。
缺点是:一个控制器中只有一个方法,如果要多个方法则需要定义多个Controller;定义的方式比较麻烦;
- @Component 组件
- @Service service
- @Controller controller
- @Respository dao
- package com.kuang.controller;
-
- import org.springframework.stereotype.Controller;
- import org.springframework.ui.Model;
- import org.springframework.web.bind.annotation.RequestMapping;
-
-
- @Controller //代表这个类会被Spring接管,
- // 类中所有的方法如果返回值为String,并且有具体页面跳转,那么就会被视图解析器解析
- public class ControllerTest2 {
-
- @RequestMapping("/t2")
- public String test1(Model model) {
-
- model.addAttribute("msg", "ControllerTest2");
-
- return "test";
- }
- }
两个请求都可以指向一个视图,但是页面结果的结果是不一样的,从这里可以看出视图是被复用的,而控制器与视图之间是弱偶合关系。
@RequestMapping注解用于映射url到控制器类或一个特定的处理程序方法。可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
测试:加上项目名 myweb
只注解在方法上
- @Controller
- public class ControllerTest3 {
- @RequestMapping("h3")
- public String test(Model model) {
- model.addAttribute("msg", "ControllerTest3");
- return "test";
- }
- }
访问路径:localhost:8080/ myweb /h3
同时注解类与方法
- @Controller
- @RequestMapping("test3")
- public class ControllerTest3 {
- @RequestMapping("h3")
- public String test(Model model) {
- model.addAttribute("msg", "ControllerTest3");
- return "test";
- }
- }
访问路径:localhost:8080/ myweb / test3 / h3
Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
资源:互联网所有的事物都可以被抽象为资源
资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。
分别对应 添加、 删除、修改、查询。
http://127.0.0.1/item/queryItem.action?id=1 查询,GET
http://127.0.0.1/item/saveItem.action 新增,POST
http://127.0.0.1/item/updateItem.action 更新,POST
http://127.0.0.1/item/deleteItem.action?id=1 删除,GET或POST
http://127.0.0.1/item/1 查询,GET
http://127.0.0.1/item 新增,POST
http://127.0.0.1/item 更新,PUT
http://127.0.0.1/item/1 删除,DELETE
测试:
1.新建一个RestFulController
2.在Spring MVC中可以使用 @PathVariable 注解,让方法参数的值对应绑定到一个URI模板变量上。
- @Controller
- public class RestFulController {
-
- //原来的方式: http://localhost:8080/myweb/add?a=1&b=2
- //Restful风格: http://localhost:8080/myweb/add/a/b
-
- @RequestMapping("/add/{a}/{b}")
- public String test(@PathVariable int a, @PathVariable int b, Model model) {
- int res = a + b;
- model.addAttribute("msg", "结果为:" + res);
- return "test";
- }
- }
3.测试请求
使用method属性指定请求类型
用于约束请求的类型,可以收窄请求范围。指定请求谓词的类型如GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE等
- @Controller
- public class RestFulController {
-
- //原来的方式: http://localhost:8080/myweb/add?a=1&b=2
- //Restful风格: http://localhost:8080/myweb/add/a/b
-
- @RequestMapping(value = "/add/{a}/{b}",method = RequestMethod.POST)
- public String test(@PathVariable int a, @PathVariable int b, Model model) {
- int res = a + b;
- model.addAttribute("msg", "结果为:" + res);
- return "test";
- }
- }
测试结果
组合注解
- @GetMapping
- @PostMapping
- @PutMapping
- @DeleteMapping
- @PatchMapping
@GetMapping 是一个组合注解,平时使用的会比较多!
@GetMapping(value="url")
等价于
@RequestMapping(value="url",method =RequestMethod.GET)
使用Restful的好处
设置ModelAndView对象 , 根据view的名称 , 和视图解析器跳到指定的页面 .
页面 : {视图解析器前缀} + viewName +{视图解析器后缀}
- <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
- id="internalResourceViewResolver">
-
- <property name="prefix" value="/WEB-INF/jsp/" />
-
- <property name="suffix" value=".jsp" />
- bean>
- public class ControllerTest1 implements Controller {
-
- public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
- //返回一个模型视图对象
- ModelAndView mv = new ModelAndView();
- mv.addObject("msg","ControllerTest1");
- mv.setViewName("test");
- return mv;
- }
- }
通过设置ServletAPI , 不需要视图解析器 .
通过HttpServletResponse进行输出
通过HttpServletResponse实现重定向
通过HttpServletRequest实现转发
- package com.kuang.controller;
-
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.GetMapping;
-
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
-
- @Controller
- public class ServletAPITest {
-
- @GetMapping("/servlet/t1")
- public void test1(HttpServletRequest request, HttpServletResponse response) throws IOException {
- response.getWriter().write("Hello,Spring BY servlet API");
- }
-
- @GetMapping("/servlet/t2")
- //响应重定向
- public void test2(HttpServletRequest request, HttpServletResponse response) throws IOException {
- response.sendRedirect(request.getContextPath()+"/index.jsp");
- }
-
- @GetMapping("/servlet/t3")
- //请求转发
- public void test3(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
- request.setAttribute("msg","/servlet/t3");
- request.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(request,response);
- }
-
- }
第一种:无需视图解析器;
先注释掉视图解析器。
- @Controller
- public class ResultSpringMVC {
- private HttpServletRequest request;
-
- //直接访问,转发
- @RequestMapping("/rsm/t1")
- public String test1(Model model) {
- model.addAttribute("msg", "ResultSpringMVC_test1");
- return "/WEB-INF/jsp/test.jsp";
- }
-
- //转发2
- @RequestMapping("/rsm/t2")
- public String test2(Model model) {
- model.addAttribute("msg", "ResultSpringMVC_test2");
- return "forward:/WEB-INF/jsp/test.jsp";
- }
-
- //重定向
- @RequestMapping("/rsm/t3")
- public String test3(Model model) {
- model.addAttribute("msg", "ResultSpringMVC_test3");
- return "redirect:/index.jsp";
- }
- }
第二种:有视图解析器;
重定向 , 不需要视图解析器 , 本质就是重新请求一个新地方嘛 , 所以注意路径问题.
可以重定向到另外一个请求实现
- @Controller
- public class ResultSpringMVC2 {
-
- //请求转发
- @RequestMapping("/rsm2/t1")
- public String test1(Model model) {
- model.addAttribute("msg", "ResultSpringMVC2_test1");
- return "test";
- }
-
- //响应重定向
- @RequestMapping("/rsm2/t2")
- public String test2() {
- // return "redirect:/index.jsp";
- return "redirect:hello.do"; //hello.do为另一个请求
- }
-
- @RequestMapping("/rsm2/hello.do")
- public String test3(Model model) {
- model.addAttribute("msg", "hello");
- return "test";
- }
- }
1、提交的域名称和处理方法的参数名一致
提交数据 : http://localhost:8080/user/t1?name=xxx
处理方法 :
- @Controller
- @RequestMapping("/user")
- public class UserController {
-
- //localhost:8080/user/t1?name=xxx
- @RequestMapping("t1")
- public String test1(String name, Model model) {
- //1.接收前端参数
- System.out.println("接收到的前端参数为:" + name);
- //2.将返回的结果传递给前端
- model.addAttribute("msg", name);
- //3.视图跳转
- return "test";
- }
-
- }
2、提交的域名称和处理方法的参数名不一致
提交数据 : http://localhost:8080/user/t2?username=xxx
处理方法 :
- @Controller
- @RequestMapping("/user")
- public class UserController {
-
- //localhost:8080/user/t2?username=xxx
- @RequestMapping("t2")
- public String test2(@RequestParam("username") String name, Model model) {
- //1.接收前端参数
- System.out.println("接收到的前端参数为:" + name);
- //2.将返回的结果传递给前端
- model.addAttribute("msg", name);
- //3.视图跳转
- return "test";
- }
-
- }
3、提交的是一个对象
要求提交的表单域和对象的属性名一致 , 参数使用对象即可
1、实体类
- @Data
- @AllArgsConstructor
- @NoArgsConstructor
- public class User {
- private int id;
- private String name;
- private int age;
- }
2、提交数据 : http://localhost:8080/user/t3?id=1&name=qinjiang&age=18
3、处理方法 :
- @Controller
- @RequestMapping("/user")
- public class UserController {
-
- //前端传递的是一个对象:id name age
- //http://localhost:8080/user/t3?id=1&name=qinjiang&age=18
- /*
- 1.接收前端传递的参数,判断参数的名字,假设名字直接在方法上,可以直接使用
- 2.假设传递的是一个对象,匹配对象中的字段名;如果字段匹配则OK;否则匹配不到
- */
- @RequestMapping("/t3")
- public String test3(User user) {
- System.out.println(user);
- return "test";
- }
- }
- public class ControllerTest1 implements Controller {
-
- public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
- //返回一个模型视图对象
- ModelAndView mv = new ModelAndView();
- mv.addObject("msg","ControllerTest1");
- mv.setViewName("test");
- return mv;
- }
- }
第二种 : 通过ModelMap
- @RequestMapping("/hello")
- public String hello(@RequestParam("username") String name, ModelMap model){
- //封装要显示到视图中的数据
- //相当于req.setAttribute("name",name);
- model.addAttribute("name",name);
- System.out.println(name);
- return "hello";
- }
第三种 : 通过Model
- @RequestMapping("/ct2/hello")
- public String hello(@RequestParam("username") String name, Model model){
- //封装要显示到视图中的数据
- //相当于req.setAttribute("name",name);
- model.addAttribute("msg",name);
- System.out.println(name);
- return "test";
- }
对比
就对于新手而言简单来说使用区别就是:
Model 只有寥寥几个方法只适合用于储存数据,简化了新手对于Model对象的操作和理解; ModelMap 继承了 LinkedMap ,除了实现了自身的一些方法,同样的继承 LinkedMap 的方法和特性; ModelAndView 可以在储存数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转。
当然更多的以后开发考虑的更多的是性能和优化,就不能单单仅限于此的了解。
1.编写一个提交表单
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>Titletitle>
- head>
- <body>
- <form action="/e/t1" method="post">
- <input type="text" name="name">
- <input type="submit">
- form>
- body>
- html>
2.后台编写对应处理类
- @Controller
- public class EncodingController {
- @PostMapping("/e/t1")
- public String test1(@RequestParam("name") String name, Model model) {
-
- model.addAttribute("msg", name);
- return "test";
- }
- }
3.输入中文测试,发现乱码
以前乱码问题通过过滤器解决 , 而SpringMVC给我们提供了一个过滤器 , 可以在web.xml中配置 .
-
-
- <filter>
- <filter-name>encodingfilter-name>
- <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
- <init-param>
- <param-name>encodingparam-name>
- <param-value>utf-8param-value>
- init-param>
- filter>
- <filter-mapping>
- <filter-name>encodingfilter-name>
- <url-pattern>/*url-pattern>
- filter-mapping>
JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式,目前使用特别广泛。
采用完全独立于编程语言的文本格式来存储和表示数据。
简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。
易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
在 JavaScript 语言中,一切都是对象。因此,任何JavaScript 支持的类型都可以通过 JSON 来表示,例如字符串、数字、对象、数组等。看看他的要求和语法格式:
对象表示为键值对,数据由逗号分隔
花括号{}保存对象
方括号[]保存数组
JSON 和 JavaScript 对象互转
JSON 是 JavaScript 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串。
要实现从JSON字符串转换为JavaScript 对象,使用 JSON.parse() 方法:
- var obj = JSON.parse('{"a": "Hello", "b": "World"}');
- //结果是 {a: 'Hello', b: 'World'}
要实现从JavaScript 对象转换为JSON字符串,使用 JSON.stringify() 方法:
- var json = JSON.stringify({a: 'Hello', b: 'World'});
- //结果是 '{"a": "Hello", "b": "World"}'
1、新建一个module ,springmvc-05-json , 添加web的支持
2、在web目录下新建一个 json-1.html , 编写测试内容
- html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Titletitle>
-
- <script type="text/javascript">
- //编写一个JavaScript
- var user = {
- name: "秦僵",
- age: 3,
- sex: "男"
- }
-
- // 将js对象转换为json对象
- var json = JSON.stringify(user);
- console.log(json)
- // 将json 对象转换为js对象
- var user = JSON.parse(json)
- console.log(user)
- script>
- head>
- <body>
-
- body>
- html>
3、在IDEA中使用浏览器打开,查看控制台输出!
Jackson应该是目前比较好的json解析工具了
当然工具不止这一个,比如还有阿里巴巴的 fastjson 等等。
我们这里使用Jackson,使用它需要导入它的jar包;
- <dependency>
- <groupId>com.fasterxml.jackson.coregroupId>
- <artifactId>jackson-databindartifactId>
- <version>2.13.4version>
- dependency>
配置SpringMVC需要的配置
web.xml
- "1.0" encoding="UTF-8"?>
- <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
- version="4.0">
-
- <servlet>
- <servlet-name>springmvcservlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
-
- <init-param>
- <param-name>contextConfigLocationparam-name>
- <param-value>classpath:springmvc-servlet.xmlparam-value>
- init-param>
- <load-on-startup>1load-on-startup>
- servlet>
-
- <servlet-mapping>
- <servlet-name>springmvcservlet-name>
- <url-pattern>/url-pattern>
- servlet-mapping>
-
-
- <filter>
- <filter-name>encodingfilter-name>
- <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
- <init-param>
- <param-name>encodingparam-name>
- <param-value>utf-8param-value>
- init-param>
- filter>
- <filter-mapping>
- <filter-name>encodingfilter-name>
- <url-pattern>/*url-pattern>
- filter-mapping>
-
- web-app>
springmvc-servlet.xml
- "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"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/context
- https://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/mvc
- https://www.springframework.org/schema/mvc/spring-mvc.xsd">
-
- <context:component-scan base-package="com.kuang.controller"/>
- <mvc:default-servlet-handler/>
- <mvc:annotation-driven/>
-
- <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
- <property name="prefix" value="/WEB-INF/jsp/"/>
- <property name="suffix" value=".jsp"/>
- bean>
-
- beans>
编写一个User的实体类,然后我们去编写我们的测试Controller;
这里我们需要两个新东西:
一个是@ResponseBody,表示当前方法不走视图解析器
一个是ObjectMapper对象,可以方便地将对象解析成json格式
- package com.kuang.controller;
-
- import com.fasterxml.jackson.core.JsonProcessingException;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import com.kuang.pojo.User;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.ResponseBody;
-
-
- @Controller
- public class UserController {
-
- @RequestMapping("/j1")
- @ResponseBody //不会走视图解析器,会直接返回一个字符串
- public String json1() throws JsonProcessingException {
-
- //jackson ObjectMapper
- ObjectMapper mapper = new ObjectMapper();
-
- //创建一个对象
- User user = new User("张三1号", 3, "男");
-
- String str = mapper.writeValueAsString(user);
-
- return str;
- }
- }
测试效果
出现了乱码,我们需要设置一下他的编码格式为utf-8,以及它返回的类型;
通过@RequestMapping的produces属性来实现,修改下代码
- //produces:指定响应体返回类型和编码
- @RequestMapping(value = "/j1",produces = "application/json;charset=utf-8")
再次测试,乱码解决
在类上直接使用 @RestController ,这样子,里面所有的方法都只会返回 json 字符串了,不用再每一个都添加@ResponseBody !我们在前后端分离开发中,一般都使用 @RestController ,十分便捷!
- @RestController //类下面的所有方法都不走视图解析器
- public class UserController {
-
- //produces:指定响应体返回类型和编码
- @RequestMapping(value = "/j1",produces = "application/json;charset=utf-8")
- public String json1() throws JsonProcessingException {
-
- //jackson ObjectMapper
- //创建一个jackson的对象映射器,用来解析数据
- ObjectMapper mapper = new ObjectMapper();
-
- //创建一个对象
- User user = new User("张三1号", 3, "男");
-
- //将我们的对象解析成为json格式
- String str = mapper.writeValueAsString(user);
-
- return str;
- }
- }
增加一个新的方法
- @RequestMapping(value = "j2",produces = "application/json;charset=utf-8")
- public String json2() throws JsonProcessingException {
- ObjectMapper map = new ObjectMapper();
-
- List
users = new ArrayList<>(); - users.add(new User("张三1号", 3, "男"));
- users.add(new User("张三2号", 3, "男"));
- users.add(new User("张三3号", 3, "男"));
- users.add(new User("张三4号", 3, "男"));
-
- String s = map.writeValueAsString(users);
- return s;
- }
测试成功
增加新方法
- @RequestMapping(value = "j3",produces = "application/json;charset=utf-8")
- public String json3() throws JsonProcessingException {
- ObjectMapper map = new ObjectMapper();
-
- Date date = new Date();
-
- String s = map.writeValueAsString(date);
- return s;
- }
运行结果:
解决方案:取消timestamps形式 , 自定义时间格式
- @RequestMapping(value = "j3",produces = "application/json;charset=utf-8")
- public String json3() throws JsonProcessingException {
- ObjectMapper map = new ObjectMapper();
- //不使用时间戳的方式
- map.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
- //自定义日期格式对象
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- //指定日期格式
- map.setDateFormat(sdf);
-
- Date date = new Date();
- String s = map.writeValueAsString(date);
- return s;
- }
如果要经常使用的话,这样是比较麻烦的,我们可以将这些代码封装到一个工具类中;我们去编写下
- package com.kuang.utils;
-
- import com.fasterxml.jackson.core.JsonProcessingException;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import com.fasterxml.jackson.databind.SerializationFeature;
-
- import java.text.SimpleDateFormat;
-
- public class JsonUtils {
-
- public static String getJson(Object object) {
- return getJson(object,"yyyy-MM-dd HH:mm:ss");
- }
-
- public static String getJson(Object object,String dateFormat) {
- ObjectMapper mapper = new ObjectMapper();
- //不使用时间差的方式
- mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
- //自定义日期格式对象
- SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
- //指定日期格式
- mapper.setDateFormat(sdf);
- try {
- return mapper.writeValueAsString(object);
- } catch (JsonProcessingException e) {
- e.printStackTrace();
- }
- return null;
- }
- }
代码更简洁
- @RequestMapping(value = "j4", produces = "application/json;charset=utf-8")
- public String json4() {
- Date date = new Date();
- String s = JsonUtils.getJson(date);
- return s;
- }
fastjson.jar是阿里开发的一款专门用于Java开发的包,可以方便的实现json对象与JavaBean对象的转换,实现JavaBean对象与json字符串的转换,实现json对象与json字符串的转换。实现json的转换方法很多,最后的实现结果都是一样的。
fastjson 的 pom依赖!
- <dependency>
- <groupId>com.alibabagroupId>
- <artifactId>fastjsonartifactId>
- <version>2.0.14version>
- dependency>
fastjson 三个主要的类:
JSONObject 代表 json 对象
JSONObject实现了Map接口, 猜想 JSONObject底层操作是由Map实现的。
JSONObject对应json对象,通过各种形式的get()方法可以获取json对象中的数据,也可利用诸如size(),isEmpty()等方法获取"键:值"对的个数和判断是否为空。其本质是通过实现Map接口并调用接口中的方法完成的。
JSONArray 代表 json 对象数组
JSON代表 JSONObject和JSONArray的转化
JSON类源码分析与使用
仔细观察这些方法,主要是实现json对象,json对象数组,javabean对象,json字符串之间的相互转化。
- package com.kuang.controller;
-
-
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONObject;
- import com.kuang.pojo.User;
-
- import java.util.ArrayList;
- import java.util.List;
-
- public class FastJsonDemo {
- public static void main(String[] args) {
- //创建一个对象
- User user1 = new User("秦疆1号", 3, "男");
- User user2 = new User("秦疆2号", 3, "男");
- User user3 = new User("秦疆3号", 3, "男");
- User user4 = new User("秦疆4号", 3, "男");
- List
list = new ArrayList(); - list.add(user1);
- list.add(user2);
- list.add(user3);
- list.add(user4);
-
- //java对象 ---> json字符串
- String s = JSON.toJSONString(list);
- System.out.println(s);
- String s2 = JSON.toJSONString(user1);
- System.out.println(s2);
-
- //json字符串 --> java对象
- User jp_user1 = JSON.parseObject(s2, User.class);
- System.out.println("JSON.parseObject(str2,User.class)==>"+jp_user1);
-
- //java对象 ---> json对象
- JSONObject jsonObject1 = (JSONObject) JSON.toJSON(user2);
- System.out.println("(JSONObject) JSON.toJSON(user2)==>"+jsonObject1.getString("name"));
-
- //json对象 ---> java对象
- System.out.println("\n****** JSON对象 转 Java对象 ******");
- User to_java_user = JSON.toJavaObject(jsonObject1, User.class);
- System.out.println("JSON.toJavaObject(jsonObject1, User.class)==>"+to_java_user);
-
-
- }
- }