1、SpringMVC
什么是springmvc?
之前我们在学servlet的时候,有了解过mvc设计模式:
-
M: model,对应着dao、service层
-
V:view,对应着jsp层
-
C:controller,对应着servlet层
Spring 框架提供了构建 web应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的Spring MVC框架或集成其他MVC开发框架
2、回顾servlet(简单回顾)
-
导入依赖包
- 父工程
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.ryan</groupId> <artifactId>SpringMVC-study</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <modules> <module>springmvc-servlet</module> </modules> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.6.RELEASE</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> </dependencies> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!--修改Language level--> <maven.compiler.source>11</maven.compiler.source> <!--修改Java Compiler--> <maven.compiler.target>11</maven.compiler.target> </properties> </project>
- 子模块
<dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> </dependency> </dependencies>
-
配置web.xml
<?xml version="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>hello</servlet-name> <servlet-class>com.ryan.controller.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> </web-app>
-
编写model层:略
-
编写view层:
-
表单
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <form action="/hello" method="post"> <input type="text" name="method"> <input type="submit" value="提交"> </form> </body> </html>
-
界面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>hello</title> </head> <body> ${msg} </body> </html>
-
-
编写controller层
package com.ryan.controller; import java.io.IOException; public class HelloServlet extends javax.servlet.http.HttpServlet { protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { String method = request.getParameter("method"); if(method.equals("add")){ request.setAttribute("msg", "执行了" + method + "方法"); } if (method.equals("delete")){ request.setAttribute("msg", "执行了" + method + "方法"); } request.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(request, response); } protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { this.doPost(request,response); } }
小结:mvc框架要做哪些事情
- 将url映射到java类或java类的方法
- 封装用户提交的数据
- 处理请求-调用相关的业务处理-封装响应数据
- 将响应的数据进行渲染.jsp/html等表示层数据
3、HelloSpringMVC
方式一:原生态,原理讲解
-
新建一个module,导入依赖
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.6.RELEASE</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> </dependency> </dependencies>
-
配置web.xml,配置DispatcherServlet,并关联spring配置文件
<?xml version="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"> <!--配置dispatcherServlet:这个时springmvc的核心:请求分发器,前端控制器--> <servlet> <servlet-name>SpringMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--DispatcherServlet要绑定那个spring配置文件--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-servlet.xml</param-value> </init-param> <!--启动等级--> <load-on-startup>1</load-on-startup> </servlet> <!--springmvc中的/和/* /:只匹配所有的请求,不会去匹配jsp页面 /*:匹配所有的请求,包括jsp页面 这样所有的请求都会走上面的servlet --> <servlet-mapping> <servlet-name>SpringMVC</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
-
编写SpringMVC的配置文件:springmvc-servlet.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" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <!--Dispatcher处理器映射器--> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <!--处理器适配器--> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/> <!--view视图解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"> <!--前缀--> <property name="prefix" value="/WEB-INF/jsp/"/> <!--后缀--> <property name="suffix" value=".jsp"/> </bean> <!--这里的id就相当于虚拟路径+跳转页面名称了--> <bean id="/hello" class="com.ryan.controller"/> </beans>
-
编写controller实体类,需继承Controller,最后注入到spring容器中
package com.ryan; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class controller implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception { ModelAndView mv = new ModelAndView(); //业务逻辑 String msg = "HelloSpringMVC"; mv.addObject("msg",msg); //视图跳转 mv.setViewName("hello"); return mv; } }
-
启动tomcat,跳转到hello页面
测试前请注意两点:
- 确保依赖已导入
- 确保lib已经导入相关jar包(可能会出现这样的问题)
总结:
- 首先用户发起请求,通过DispatcherServlet
- BeanNameUrlHandlerMapping处理器找到url的id(/hello),并返回给DispatcherServlet
- DispatcherServlet携带结果通过适配器找到相对应的Controller(com.ryan.controller)
- com.ryan.controller执行相关业务操作后,最终将视图返回给DispatcherServlet
- DispatcherServlet再通过视图解析器跳转到客户请求的页面
以上可以参考下面的流程图来看, 总共可以分为处理器、适配器、解析器三部分
当然这里只是为了理解其中的原理,实际开发不会这么复杂的
方式二:注解+配置,简化代码
-
新建一个module,确保依赖和lib目录都已经导入
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.ryan</groupId> <artifactId>SpringMVC-study</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <modules> <module>springmvc-servlet</module> <module>spring-01-hellomvc</module> <module>spring-02-HelloSpringMVC</module> </modules> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.6.RELEASE</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> </dependency> </dependencies> <build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> <include>**/*.properties</include> </includes> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.xml</include> <include>**/*.properties</include> </includes> </resource> </resources> </build> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!--修改Language level--> <maven.compiler.source>11</maven.compiler.source> <!--修改Java Compiler--> <maven.compiler.target>11</maven.compiler.target> </properties> </project>
-
配置web.xml文件
- 注册DispatcherServlet
- 关联SpringMVC配置文件
- 设置启动等级为1
- 配置映射路径
<?xml version="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"> <!--注册DispatcherServlet--> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!--配置映射路径--> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
-
配置SpringMVC的配置文件,对比前面的,处理器映射器和Controller适配器都不需要写了,都交给controller类中使用注解配置
- 让IOC的注解生效(component-scan)
- 让SpringMVC不处理静态资源(譬如js css html等资源)
- MVC的注解驱动
- 配置视图解析器
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans https://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"> <!--自动扫描,让指定包下的注解生效,并由IOC容器统一管理--> <context:component-scan base-package="com.ryan.controller"/> <!--过滤静态资源--> <mvc:default-servlet-handler/> <!--mvc注解驱动,替代了之前的处理器和适配器--> <mvc:annotation-driven/> <!--视图解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"> <!--前缀--> <property name="prefix" value="/WEB-INF/jsp/"/> <!--后缀--> <property name="suffix" value=".jsp"/> </bean> </beans>
-
编写controller类,类上注解@Controller,方法上注解@RequestMapping(“访问路径”)
package com.ryan.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller//相当于之前的实现Controller接口,且等价于component public class HelloController { @RequestMapping("/hello")//真实访问路径,比如这里写/hi,那么在地址栏上输入/hi public String hello(Model model){ model.addAttribute("msg", "HelloSpringMVC"); return "hello"; } }
-
最后开启tomcat,测试执行
注意:
- springmvc配置文件中开启了component扫描,@controller等价于@component(不同的层名字不同)
- mvc:annotation-driven/这个会自动开启映射器处理器和controller适配器
- @Controller相当于实现Controller接口
- @RequestMapping("/hello"),是映射客户访问的真实路径
@Controller详解
- 使用它标记的类就是一个SpringMVC Controller 对象
- 分发处理器将会扫描使用了该注解的类的方法,并检测该方法是否使用了@RequestMapping 注解。
- @Controller 只是定义了一个控制器类,而使用@RequestMapping 注解的方法才是真正处理请求的处理器
@RequestMapping详解
-
该注解用于映射url到控制器类或一个特定的处理程序方法,可用于类或方法上,用于类上,表示类中的所有响应请求的方法都是以该地址为父路径,例如
@Controller @RequestMapping("/admin") public class HelloController { @RequestMapping("/hello") public String hello(Model model){ model.addAttribute("msg", "HelloSpringMVC"); return "hello"; } } //则如果你想要访问到hello,路径是这样的:localhost:8080/admin/hello
总结:
- 相比servlet,代码精简了非常多
- 如果想要跳转多个页面,在controller类中多写几个方法并配置对应的访问路径即可,一个视图可以得到复用,不需要像以前那样写多个servlet,这种非常简单的操作,有点接近于实际开发中的操作了
- 操作简单了,但是你要知道他底层的实现原理,这是面试过程中和hr的谈资
4、RestFul风格
什么是restful风格?
RestFul就是一个资源定位及资源操作的风格,不是标准也不是协议,只是一种风格,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制
功能
- 资源:互联网所有的事物都可以被抽象为资源
- 资源操作:使用POST 、DELETE、PUT、GET,使用不同的方法对资源进行操作
- 分别对应添加、删除、修改、查询,用得比较多的都是post和get
传统方式操作资源:通过不同的参数来实现不同的效果,方法单一
使用RestFul操作资源:可以通过不同的请求方式来实现不同的效果,甚至请求地址完全一样,也可以实现不同的功能
使用:
-
创建一个模块,确保依赖和lib已经导入
-
配置web.xml和springmvc-servlet.xml
-
编写controller类,使用注解
package com.ryan.RestFulController; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class RestFulController { @RequestMapping("/test") public String test1(Model model){ model.addAttribute("msg", "restful"); return "test"; } /* 在传统的传参风格中是这样的:localhost:8080/test?a=1&b=2 而我们经常看到的大多是这样的:localhost:8080/test/1/2,这种就是restful风格的,具体怎么实现呢? 在参数添加@PathVariable,然后再从映射路径中接收参数 我们还可以改变注解规定其访问提交数据的方式 */ //@RequestMapping("/test/{a}/{b}") @GetMapping("/test/{a}/{b}")//此时通过post方式是访问不到这个的 public String test2(@PathVariable int a, @PathVariable int b, Model model){ int res = a + b; model.addAttribute("msg", "get结果=" + res); return "test"; } @PostMapping("/test/{a}/{b}")//只有通过Post方式才能访问到 public String test3(@PathVariable int a, @PathVariable int b, Model model){ int res = a + b; model.addAttribute("msg", "post结果=" + res); return "test"; } /* 此时你会发现当test2和test3的访问路径可以完全一样:http://localhost:8080/test/1/2 但是通过不同的访问方式,会有不同的结果 通过get方式:get结果=3 通过post方式:post结果=3 */ /* 还有一个情况说明一下,当controller中存在两个完全一样的访问路径(提交方式也一样),会报一个错 错误中有一个关键字:Ambiguous mapping,也就是模棱两可的,客户端也不知道访问哪个 */ }
5、转发和重定向
package com.ryan.RestFulController;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ControllerTest01 {
@RequestMapping("/t1")
public String test01(Model model){
model.addAttribute("msg", "springmvc");
//有视图解析器的情况下,return "test"默认就是转发
//return "test";
//如果想要重定向的话,需要在前面加一个redirect:的前缀
return "redirect:/index.jsp";
}
//上面的是在有视图解析器的情况下,如果没有视图解析器的话会怎么样呢?
@RequestMapping("/t2")
public String test02(Model model){
model.addAttribute("msg", "你好");
//如果没有视图解析器,转发也要加上前缀才行
return "forward:/WEB-INF/jsp/test.jsp";
}
//总结:即使没有视图解析器,我们也可以完成转发和重定向的功能
//但是在实际开发中,没什么事不会这么做的,一般都是有视图解析器的
}
6、springmvc处理数据
处理提交数据,分为三种情况
- 提交的域名称和处理方法的参数名一致
- 可以直接接受
- 提交的域名称和处理方法的参数名不一致
- 需要在参数前添加注解
- 提交的数据是一个对象
- 自定义一个对象,属性和提交的数据名一样即可
package com.ryan.RestFulController;
import com.ryan.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class DataController {
//用户提交数据名称为name
//当提交数据名称和处理方法参数名称一致
@GetMapping("/t1")
public String test1(String name, Model model){
model.addAttribute("msg", name);
return "test";
}
//如果不一致,需要添加注解使其一致
@GetMapping("/t2")
public String test2(@RequestParam("name") String username, Model model){
model.addAttribute("msg", "kobe");
return "test";
}
//如果前端传的是一个User对象:id=1&name=ryan&age=18
//自定一个类,并作为处理方法的参数
@GetMapping("/t3")
public String test3(User user, Model model){
model.addAttribute("msg", user.toString());
return "test";
}
/*
注意:
前两种情况,无论名称是否一直,都建议把@RequestParam注解加上,知道是要从前端接收数据的
第三种情况,对象的属性名称要保持一致, 如果不一致的话,对应的属性就是null
*/
}
补充:除了用Model之外,我们还可以使用ModelMap,但在使用上,本质上一样的
对比:
Model:只有寥寥几个方法,适合存储数据,简化了新手对Model对象的操作和理解
ModelMap:继承了LinkedMap,除了实现自身的一些方法,同样继承了LinkedMap的方法和特性
ModelAndView:可以在存储数据的同时,进行设置返回的逻辑和视图,进行控制展示层的跳转
当然以后开发考虑更多的是性能和优化,就不能单单仅限于此的了解
建议:请使用80%的时间打好扎实的基础,剩下18%的时间研究框架,2%的时间去学习英语,框架的官方文档永远是最好的教程。
7、乱码问题
在前端提交中文数据的时候,可能会产生乱码的问题,这时候我们该怎么解决呢?
springmvc提供了一个一套解决方案,在web.xml中配置好过滤器就行:
<!--解决中文乱码问题-->
<filter>
<filter-name>encoding</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>
<!--注意这里要写/*,不然会过掉jsp页面-->
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
8、json使用
现在都流行前后端分离,有时候前端返回一些json对象给我们,我们要会解析,同样的,我们最后也需要将数据转化为json格式返回给前端,这就要求我们要使用相关工具类了,主要有两个:
方式一:jackson
jackson是目前比较好的json解析器了,当然工具不止这个,比如还有阿里巴巴的fastjson,等会再讲
使用:
-
确保导入依赖包和lib
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.10.2</version> </dependency>
-
编写配置文件,并解决乱码 问题
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans https://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.ryan.controller"/> <!--当我们在实体类都用注解的话,下面这两个也可以省去了--> <!--<mvc:default-servlet-handler/> <mvc:annotation-driven/>--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> <!--解决json数据中文乱码问题--> <mvc:annotation-driven> <mvc:message-converters register-defaults="true"> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8</value> <value>application/json;charset=UTF-8</value> </list> </property> </bean> </mvc:message-converters> </mvc:annotation-driven> </beans>
-
编写实体类测试
package com.ryan.controller; import com.alibaba.fastjson.JSON; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.ryan.pojo.User; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import java.util.ArrayList; import java.util.List; @Controller public class JsonController { //如果添加一个@ResponseBody注解,返回结果就不会走解析器了,直接返回字符串 @RequestMapping("/j1") @ResponseBody public String test() throws JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); User user = new User(1, "甘志鹏", 20); String str = mapper.writeValueAsString(user); return str;//{"id":1,"name":"???","age":20} //springmvc可以帮我们解决乱码问题,在spring中配置就好 } //java对象转换为json数据 @RequestMapping("/j2") @ResponseBody public String tes2() throws JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); List<User> users = new ArrayList<>(); User user1 = new User(1, "甘志鹏1号", 20); User user2 = new User(2, "甘志鹏2号", 20); User user3 = new User(3, "甘志鹏3号", 20); User user4 = new User(4, "甘志鹏4号", 20); users.add(user1); users.add(user2); users.add(user3); users.add(user4); String str = mapper.writeValueAsString(users); return str; /* [{"id":1,"name":"甘志鹏1号","age":20}, {"id":2,"name":"甘志鹏2号","age":20}, {"id":3,"name":"甘志鹏3号","age":20}, {"id":4,"name":"甘志鹏4号","age":20}] */ } }
方式二:FastJson(阿里巴巴的)
-
导入依赖
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.68</version> </dependency>
-
编写实体类测试
package com.ryan.controller; import com.alibaba.fastjson.JSON; import com.ryan.pojo.User; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import java.util.ArrayList; import java.util.List; @Controller public class FastJson { @ResponseBody @RequestMapping("/f1") public String test1(){ List<User> users = new ArrayList<>(); User user1 = new User(1, "甘志鹏1号", 20); User user2 = new User(2, "甘志鹏2号", 20); User user3 = new User(3, "甘志鹏3号", 20); User user4 = new User(4, "甘志鹏4号", 20); users.add(user1); users.add(user2); users.add(user3); users.add(user4); String str = JSON.toJSONString(users); return str; /* [{"age":20,"id":1,"name":"甘志鹏1号"}, {"age":20,"id":2,"name":"甘志鹏2号"}, {"age":20,"id":3,"name":"甘志鹏3号"}, {"age":20,"id":4,"name":"甘志鹏4号"}] */ } }
9、ajax
略
10、拦截器
10.1、概述:
- SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理,开发者可以自己定义一些拦截器来实现特定的功能
- 过滤器与拦截器的区别:拦截器是AOP思想的具体应用
过滤器:
- servlet规范中的一部分,任何javaweb工程都可以使用
- 在url-pattern中配置了/*之后,可以对所有要访问的资源进行拦截
拦截器:
- 拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用
- 拦截器只会拦截访问的控制器方法,如果访问的是jsp/html/css/image/js是不会进行拦截的
10.2、自定义拦截器
那如何实现拦截器呢?
想要自定义拦截器,必须实现HandlerInterceptor接口
-
新建一个Module,添加web支持
-
配置web.xml和springmvc-servlet.xml文件
<?xml version="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>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!--解决中文乱码问题--> <filter> <filter-name>encoding</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>encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans https://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.ryan.controller"/> <mvc:default-servlet-handler/> <mvc:annotation-driven/> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> <!--解决json数据中文乱码问题--> <mvc:annotation-driven> <mvc:message-converters register-defaults="true"> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8</value> <value>application/json;charset=UTF-8</value> </list> </property> </bean> </mvc:message-converters> </mvc:annotation-driven> <!--拦截器--> <mvc:interceptors> <mvc:interceptor> <!--拦截哪些请求,/**表示拦截所有请求,我们这里拦截首页的访问请求--> <mvc:mapping path="/home"/> <!--拦截器在哪--> <bean class="com.ryan.interceptor.MyInterceptor"/> </mvc:interceptor> </mvc:interceptors> </beans>
-
编写一个拦截器
package com.ryan.interceptor; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; //实现HandlerInterceptor接口 public class MyInterceptor implements HandlerInterceptor { //手动重写方法,然后需要到springmvc配置文件中配置拦截信息 //一般只需要preHandle方法就行 //从以下三个方法中可以看到和aop非常相似,其实这就是aop思想的一个应用,在访问某个路径时,可以在preHandle方法上增添附属功能 //可使用request实现转发或者重定向等等 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { /*System.out.println("=========处理前=========="); //返回false表示拦截,返回true表示放行 return false;*/ //那么利用这个拦截器我们做一个真实的案例,譬如没有登陆前不能访问首页,即没登陆的话需要拦截并跳转到登陆页面 //客户端访问home==>判断是否已经登陆==>,如已登录==>放行,如未登陆==>转发至登陆页面 HttpSession session = request.getSession(); String user = (String) session.getAttribute("user"); if (user != null){ return true; } request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response); return false; } //后面的两个方法一般没多大用处,需要的话可以作为日志使用 /*@Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("=========处理后=========="); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("=========清理=========="); }*/ }
package com.ryan.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; @Controller public class Test { @RequestMapping("/home") public String home(){ return "home"; } @RequestMapping("/toLogin") public String toLogin(){ return "login"; } @RequestMapping("/login") public String login(HttpServletRequest request, String username, String password){ //通常我们会使用session来判断用户是否已经登陆,所以登陆时应该存一个session HttpSession session = request.getSession(); //当然这里规范的应该要新建一个user类的,这里只是为了测试就不建了 session.setAttribute("user",username); return "redirect:/home"; } }
-
测试
学习来源:B站up主:狂神说,有兴趣的同学可以关注学习一波,感觉还不错