目录
【概述】
- MVC是模型(Model)、视图(View)、控制器(Controller)
- springMVC是什么?
Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架。
Spring MVC框架像许多其他MVC框架一样, 以请求为驱动 , 围绕一个中心Servlet分派请求及提供其他功能,DispatcherServlet是一个实际的Servlet (它继承自HttpServlet 基类)。
一 初识springMVC
1.1 第一个springMVC
1)新建一个Moudle,并添加web支持
2)导入springMVC依赖,配置打包
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*</include>
</includes>
</resource>
</resources>
</build>
3)配置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">
<!--1.注册DispatcherServlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--关联一个springmvc的配置文件:【servlet-name】-servlet.xml-->
<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>
4)配置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
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--处理器映射器-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--处理器适配器-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!--视图解析器:DispatcherServlet给他的ModelAndView-->
<!--1.获取ModelAndView中的数据 2.解析ModelAndView名字 3.拼接视图名-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<!--前缀--><property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀--><property name="suffix" value=".jsp"/>
</bean>
<!--Handler-->
<bean id="/hello" class="com.zheng.controller.HelloController"/>
</beans>
5)编写控制类HelloController
public class HelloController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
//ModelAndView 模型和视图
ModelAndView mv = new ModelAndView();
String method=request.getParameter("method");
//封装对象,放在ModelAndView中
if (method.equals("aa123")){
mv.addObject("msg","HelloSpringMVC");
}else {
mv.addObject("msg","other");
}
//封装要跳转的视图,放在ModelAndView中
mv.setViewName("hello"); //等价于: /WEB-INF/jsp/hello.jsp
return mv;
}
}
6)在WEB-INF下添加 /jsp/hello.jsp
<body>
<h1>hello spring-MVC</h1>
<h4>${msg}</h4>
</body>
可能遇到的问题:访问出现404
文件》项目结构》工作》查看是否确实 lib 包
如果缺少 lib 包则手动加上,并添加依赖
1.2 原理概述
用户发送请求:http://localhost:8080/SpringMVC/hello
【根据url解析处理器】
- 处理url,如:域名
http://localhost:8080
、站名SpringMVC
、控制器hello
- DS 调用处理器映射,根据 url 查找到 Handel(处理器)
- 将解析的控制器信息返回到 DS
【控制器具体操作】
- 处理器按照规则执行 Handel,查找控制器类(实现 Controller 的类)
- 具体的 Controller 执行
- Controller返回执行结果(ModelAndView)
- 将视图逻辑名或模型传递给 DS
【解析视图名,返回视图】
- 调用视图解析器来解析 HandlerAdapter 传递的逻辑名,拼接
- 将解析名返回给 DS
- DS根据视图名查找视图
- 将视图返回给用户
1.3 注解实现
0)准备工作
- 类似于配置实现的方式,需要在项目结构中手动添加lib包
- 配置pom.xml
2)配置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">
<!--1.注册servlet-->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--通过初始化参数指定SpringMVC配置文件的位置,进行关联-->
<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拦截 -->
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
3)添加配置文件 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"
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">
<!-- 资源过滤:让Spring MVC不处理静态资源 -->
<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>
<!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
<context:component-scan base-package="com.zheng.controller"/>
</beans>
4)编写一个控制类 HelloController.java
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/HelloController")//可选项
public class HelloController {
@RequestMapping("")//实际访问地址 /HelloController
public String sayHello0(Model model){
//向模型中添加属性msg与值,可以在JSP页面中取出并渲染
model.addAttribute("msg","hello SpringMVC 000");
return "hello"; //WEB-INF/jsp/hello.jsp
}
@RequestMapping("/h1")//实际访问地址 /HelloController/h1
public String sayHello1(Model model){
model.addAttribute("msg","hello SpringMVC 111");
return "hello";
}
}
归结起来就是四个东西。
- @Controller注解类型用于声明Spring类的实例是一个控制器,并使用扫描机制来找到应用程序中所有基于注解的控制器类
- @RequestMapping注解用于映射url到控制器类或一个特定的处理程序方法。可用于类或方法上
- @PostMapping只能接收Post方式的请求
- @GetMapping只能接收Get方式的请求
- Model
- return 返回一个视图名,通过视图解析器会自动拼接
5)在WEB-INF下添加 /jsp/hello.jsp 略
二 RestFul 风格
概念:
- RestFul就是一个资源定位及资源操作的风格。
- 不是标准也不是,只是一种风格。
- 基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
2.1 @PathVariable
@PathVariable 注解,让方法参数的值对应绑定到一个URI模板变量上
- 原来url格式:xxx/add?a=1&b=2
- RestFul格式:xxx/add2/1/2
@Controller
@RequestMapping("/count")
public class Count {
//http://localhost:8080/mvc04/count/add?a=1&b=2
@RequestMapping("/add")
public String add(int a, int b, Model m){
int res = a+b;
m.addAttribute("msg","计算结果:"+res);
return "hello";
}
//http://localhost:8080/mvc04/count/add2/1/2
@RequestMapping("/add2/{a}/{b}")
public String add2(@PathVariable int a,@PathVariable int b, Model m){
int res = a+b;
m.addAttribute("msg","计算结果:"+res);
return "hello";
}
}
2.2 小结
Spring MVC 的 @RequestMapping 注解能够处理 HTTP 请求的方法, 比如 GET, PUT, POST, DELETE
所有的地址栏请求默认都会是 HTTP GET 类型
方法级别的注解变体有如下几个
- @GetMapping
- @PostMapping
- @PutMapping
- @DeleteMapping 等等…
特点:简洁、高效、安全
三 转发重定向和数据处理
3.1 ServletAPI
@RequestMapping("/servletAPI")
public void text(HttpServletRequest req, HttpServletResponse resp){
try {
System.out.println("session:"+req.getSession().getId());
resp.getWriter().println("hello SrpingMVC servletAPI");
} catch (IOException e) {
System.out.println(e);
}
}
可直接设置形参获取输入输出数据,可用以控制转发和重定向
3.2 springMVC实现
- 转发不改变地址栏,重定向地址栏会变化
- 添加
redirect:
关键字,可实现重定向,会跳过视图解析器
//转发 http://localhost:8080/mvc04/count/add?a=1&b=2
@RequestMapping("/add")
public String add(int a, int b, Model m){
int res = a+b;
m.addAttribute("msg","计算结果:"+res);
return "hello";
}
//重定向
@RequestMapping("/sub")
public String sub(){
return "redirect:/index.jsp";
}
3.3 处理接收数据
//接收普通参数 localhost:8080/mvc04/user/d1?username=zheng
@RequestMapping("/d1")
public String data01(@RequestParam("username") String name, Model m){
System.out.println("获取前端传递参数:"+name);
m.addAttribute("msg","name="+name);
return "hello";
}
//接收对象参数 localhost:8080/mvc04/user/d2?name=zheng&age=18&id=001
@RequestMapping("/d2")
public String data02(User user, Model m){
System.out.println("获取前端传递参数:"+user.toString());
m.addAttribute("msg","name="+user);
return "hello";
}
说明:如果使用对象的话,前端传递的参数名和对象名必须一致,否则就是null。
如:
输入:localhost:8080/mvc04/user/d2?name=zheng&age=18
输出:User{id=‘null’, name=‘zheng’, age=18}
3.4 乱码问题
使用pos提交数据时,提交中文会产生乱码
配置文件 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>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
四 JOSN
json是一种轻量级的数据交换格式,采用文本格式来存储和表示数据,其实就是java中的字符串。
JavaScript 实现 JSON 和字符串的转换
字符串转JSON:
var obj = JSON.parse('{"a": "Hello", "b": "World"}'); //结果是 {a: 'Hello', b: 'World'}
JSON转字符串:
var json = JSON.stringify({a: 'Hello', b: 'World'}); //结果是 '{"a": "Hello", "b": "World"}'
4.1 jackson
【实现】
导包:
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0</version>
</dependency>
- 将返回的信息封装成对象,再将对象转变成 JSON 格式
- @ResponseBody:阻止视图解析器,返回一个字符串
@RequestMapping(value = "/j1",produces = "application/json;charset=utf-8")
@ResponseBody
public String json1(Model m) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
User u = new User("小郑同学", "001", 18);
//将对象转为JSON
String s = mapper.writeValueAsString(u);
return s;
}
注:RequestMapping 中加上 produces = “application/json;charset=utf-8” 是手动解决乱码问题。统一配置后可不加!
【乱码统一解决】
springmvc-servlet.xml
<mvc:annotation-driven>
<!-- JSON乱码问题配置 -->
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
【拓展】
- @RestController:代替Controller,表示该类下的方法都阻止视图解析器,返回字符串
@RestController
@RequestMapping("/json")
public class UserCon {
@RequestMapping(value = "/j1")
public String json1(Model m) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
User u = new User("小郑同学", "001", 18);
//将对象转为JSON
String s = mapper.writeValueAsString(u);
return s;
}
}
- 时间戳自定义时间格式输出
@RequestMapping("/j3")
public String json3() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
//不使用时间戳格式
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
//自定义格式,并使用
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
Date date = new Date();
return mapper.writeValueAsString(date);
}
- 封装工具类
public class JsonUtils {
//默认开启时间戳格式转换 getJson(obj);
public static String getJson(Object o){
return getJson(o,"yyyy-MM-dd HH:mm:ss",true);
}
//自定义时间格式 getJson(obj,"MM-dd HH:mm:ss");
public static String getJson(Object o,String diyData){
return getJson(o,diyData,true);
}
//关闭时间戳 getJson(obj,false);
public static String getJson(Object o,Boolean b){
if (b){
return getJson(o,"yyyy-MM-dd HH:mm:ss",true);
}else{
return getJson(o,"",false);
}
}
//重写方法
public static String getJson(Object o,String diyData,Boolean b){
ObjectMapper mapper = new ObjectMapper();
if(b){
//不使用时间戳格式
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
//自定义格式,并使用
mapper.setDateFormat(new SimpleDateFormat(diyData));
}
try {
return mapper.writeValueAsString(o);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
}
4.2 Fastjson
导包:
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.78</version>
</dependency>
使用
System.out.println("*******Java对象 转 JSON字符串*******");
String str1 = JSON.toJSONString(list);
System.out.println("\n****** JSON字符串 转 Java对象*******");
User jp_user1=JSON.parseObject(str2,User.class);
System.out.println("\n****** Java对象 转 JSON对象 ******");
JSONObject jsonObject1 = (JSONObject) JSON.toJSON(user2);
System.out.println("\n****** JSON对象 转 Java对象 ******");
User to_java_user = JSON.toJavaObject(jsonObject1, User.class);