目录
4.3、前后端关联,改造网页,在html网页超链接获取数据--View
2、改造CarController类,加一个跨域的注解@CrossOrigin
一、SpringMVC框架
1、概述
SpringMVC框架的核心作用:接收浏览器发来的请求,并给浏览器作出响应。
Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。
使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的SpringMVC框架或集成其他MVC开发框架,如Struts1(现在一 般不用),Struts2(一般老项目使用)都有安全问题。
SpringMVC就是基于MVC设计模式来实现的。
我们的POJO就是Model层,我们的JSP就是视图层,我们的Controller就是控制层。
现在主流基于SSM三大框架开发都是在MVC上继续演化,又分为持久层DAO,业务层Servie,控制层Controller。持久层用来和数据库读写ORM,业务层用来处理复杂的业务逻辑,控制层用来处理MVC的控制。
2、MVC模型
通用的软件编程思想, 在MVC设计模式中认为, 任何软件都可以分三层,
Model模型-存储、封装数据、
View视图-展示数据结果、
Controller控制层-接收请求、处理响应
代码分离结构清晰,各司其职,易于开发大型项目。
优点:MVC三部分相互独立,如果某一个模块发生变化,应该尽量做到不影响其他两个模块。提高代码的可读性,实现程序间的松耦合、提高代码复用性。
性能:简单易用
3、工作原理--面试题
1)更具体一些的描述:
1、用户发送请求至前端控制器DispatcherServlet。
2、DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找类和方法),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、DispatcherServlet调用HandlerAdapter处理器适配器。
5、HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6、Controller执行完成返回ModelAndView。
7、HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8、DispatcherServlet将ModelAndView传给ViewResolver视图解析器。
9、ViewResolver解析后返回具体View。
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、DispatcherServlet最后再响应给用户。
2)、主要操作器
1.前端控制器:DispatcherServlet,用来接受请求分发请求,servlet是java与前端页面进行数据交互的一种机制
2.处理器映射器:HandlerMapping,用来根据url找具体的类里的具体方法
http://localhost:8080/abc/hi
@RequestMapping(“abc”)public class HelloBoot {@RequestMapping(“hi”) public String hello(){ } }
3.处理器适配器:HandlerAdapter,用来执行方法里的代码
4.视图解析器:ViewResolver,定位页面的路径
5.视图:View,用来展示数据
3、MVC三层结构:
4 SpringMVC 参数取值详情说明
4.1 Servlet
Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。Servlet的生命周期可以分为四个阶段,即装载类及创建实例阶段、初始化阶段、服务阶段和实例销毁阶段.
狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。
总结: Servlet是java与前端页面进行数据交互的一种机制
核心对象:
1. request对象 封装用户请求的参数/请求头/请求全部内容
2. response对象 封装用户响应信息
4.2 Servlet获取参数规则
controller层:
/**
* 注意事项: 如果后端服务器没有匹配的方法,也会报跨域错误.
* URL:http://localhost:8090/getUserById?id=1&age=18
* 参数: id=1
* 返回值: User对象
* servlet特点:
* 1.获取的数据都是String类型
*/
@GetMapping("/getUserById")
public User getUserById(Integer id){
//1.SpringMVC框架通过Servlet中request对象,根据参数名称获取值
// String id = request.getParameter("age");
//2.SpringMVC根据已知的数据类型 自动的实现数据转化
return null;
}
/*@GetMapping("/getUserById")
public User getUserById(HttpServletRequest request,
HttpServletResponse response){
//1.参数获取 每个参数都需要手动获取
String id = request.getParameter("id");
String age = request.getParameter("age");
//2.数据类型转化
int intId = Integer.parseInt(id);
System.out.println("根据ID查询数据库~~~~~");
return null;
}*/
4.3 对象方式
1)页面对象封装
2)后端参数接收问题
/**
* URL: http://localhost:8090/getUserByUser
* 参数: user对象的数据
* 返回值: User
*/
@GetMapping("/getUserByUser")
public User getUserByUser(User user){
//1.SpringMVC如果解析到参数是对象 先获取其中的Get方法
// getId()/getName()......
//2.将方法get去除首字母小写~~~id1111/name/age/sex
//3.实例化一个User对象之后调用setxxx()方法实现赋值
//4.最终方法中获取一个实例化的User对象
//String id = request.getParameter("id");
return user;
}
二、入门案例:展示汽车数据
前提是在创建了Spring Boot工程下,再建SpringMVC的Module
1、需求
访问链接: http://localhost:8080/car/get
得到JSON数据: {"id":718,"name":"保时捷","type":"Cayman T","color":"红色","price":641000.0}
2、创建Module
3、创建启动类--Controller
注意:
1)启动类只会在创建project工程时会自动生成启动类,而在创建module项目时不会自动创建启动类,需要手动创建启动类
2)创建module后java文件不能创建class时,右键mark derictory--》source root
3)停掉Oracle
步骤:此电脑--》右键管理--》右键服务和应用程序--》双击服务--》找到OracleXETNSListener右键属性--启动类型改为禁用
整体需要的两个包,三个类:
package cn.tedu.controller;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Controller;
@SpringBootApplication
@Controller
public class RunApp {
public static void main(String[] args) {
SpringApplication.run(RunApp.class);
}
}
4、创建资源--Model
4.1、创建Car类
创建包:cn.tedu.pojo
创建类:Car
封装属性,设置set和get方法,重写toString()方法
package cn.tedu.pojo;
/*封装数据Model*/
public class Car {
/*1.为什么使用引用类型(包装类型)?因为使用基本类型会抛出异常,*/
//private int id;
private Integer id;
private String name;
private String type;
private String color;
//private double price;
private Double price;
/*4.Constructor默认存在无参构造,如有含参构造,需手动添加无参构造*/
public Car() {
}
/*5.全参构造,创建对象时可以直接给属性赋值*/
public Car(Integer id, String name, String type, String color, Double price) {
this.id = id;
this.name = name;
this.type = type;
this.color = color;
this.price = price;
}
/*3.toString()重写顶级父类,重写后打印的是具体内容*/
@Override
public String toString() {
return "Car{" +
"id=" + id +
", name='" + name + '\'' +
", type='" + type + '\'' +
", color='" + color + '\'' +
", price=" + price +
'}';
}
/*2.封装属性需要提供set/get方法*/
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
}
4.2、改造CarController
1、方式一:无参构造创建对象设置属性
作用:把资源发送到网页上
package cn.tedu.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController//接收请求
@RequestMapping("car")//规定了浏览器的访问这个类的方式
public class CarController {
@RequestMapping("get")//规定了浏览器访问这个方法
public Car get(){
//System.out.println(1000);控制台打印
//保时捷718 Cayman T,红色,641000元起
Car car = new Car();
car.setId(718);
car.setName("保时捷");
car.setType("Cayman T");
car.setColor("红色");
car.setPrice(641000.0);
return car;
}
}
1)网页访问地址:localhost:8080/car/get
2)网页显示结果:
{"id":718,"name":"保时捷","type":"Cayman T","color":"红色","price":641000.0}
2、方式二:全参构造创建对象直接属性赋值
package cn.tedu.controller;
import cn.tedu.pojo.Car;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("car")
public class CarController {
@RequestMapping("get")
public String get(){
return "一码一高度,巅峰不远处" ;
}
//提供汽车相关的数据
@RequestMapping("get2")
public Car get2(){
//http://localhost:8080/car/get2
// {"id":718,"name":"保时捷","type":"Cayman T","color":"红色","price":641000.0}
Car car=new Car(718,"保时捷","Cayman T","红色",641000.00 );
return car ;
}
}
4.3、前后端关联,改造网页,在html网页超链接获取数据--View
想要在HTML网页超链接绑定点开mvc数据:
1)在HTML超链接href绑定mvc固定地址格式:localhost:8080/car/get2
2)需要重启服务器tomcat
3)打开HTML网页点击指定链接名,即可跳出car类的信息(car对象)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>测试SpringMVC</title>
</head>
<body>
<a href="http://localhost:8080/car/get">点我发起请求</a>
<br>
<a href="http://localhost:8080/car/get2">点我发起汽车类请求</a>
</body>
</html>
三、利用SpringMVC解析请求参数
1、概述
当客户端打开浏览器要访问服务器时,可能会带着一些http请求参数过来.
这时,服务器需要获取http参数进行业务处理,如何处理http请求并获取参数呢?
总共有8种,重点时两种方式:GET方式和POST方式
2、浏览器提交请求数据的方式
get:把请求参数 在地址栏拼接http://localhost:8080/car/insert?id=1&name=张三&age=18
post:安全,数据不在地址栏展示
3、get方式解析请求参数
1)html修改网页:
2)idea修改controller:
注意:@RequestMapping注解的方法名不能相同,底层Map(k,v),要求无序无下标不能重复,其中k就是url,即localhost:8080/car/add1,如果最后方法名相同,导致程序不知道调用哪一个,给不到我们想要的类的属性。
package cn.tedu.controller;
import cn.tedu.pojo.Car;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("car")
public class CarController {
//1.框架解析请求参数http://localhost:8080/car/add?id=1
@RequestMapping("add")
public void add(int id){//把地址栏里的参数值交给局部变量id保存
System.out.println(id);
}
//2.框架解析请求参数http://localhost:8080/car/add1?id=1&name=张三
@RequestMapping("add1")
public void add1(int id ,String name){//把地址栏里的参数值交给局部变量id,name保存
System.out.println(id+name);
}
//3.SpringMVC解析汽车类请求多个参数
//http://localhost:8080/car/add2?id=718&name=保时捷&type=Cayman T&color=红色&price=641000.0
@RequestMapping("add2")
public Car add2(Car car){//把地址栏的参数值交给car类对应局部变量保存
System.out.println(car);//打印在控制台
return car;//内容返回到网页
}
}
四、SpringMVC常见问题解决
1、404-请求的url不存在
解决方案: java严格区分大小写,把地址改成:http://localhost:8080/car/get即可
2、500--请求的url未绑定参数
get3方法明显是需要参数的,那就请求时,必须传入参数,否则页面报错500,IDEA中抛出了IllegalStateException的异常。
解决方案:
可以将url改成:http://localhost:8080/car/get3?id=10 即可。给参数或者把基本类型改为引用类型
或者:把方法的参数改为引用类型,int改成Integer,即使请求时忘记传入参数,也不会抛出异常
3、400-url 的请求和服务器需要的参数类型不同
问题:需要int类型的参数哦却给了一个double类型的参数
解决方案:改变相应的基本类型或者参数哦
五、restful风格解析请求参数
1、项目结构
2、修改网页
3、修改car
package cn.tedu.pojo;
//Model
public class Car {
private Integer id ;
private String name ;
private String type ;
private String color ;
private Double price ;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
@Override
public String toString() {
return "Car{" +
"id=" + id +
", name='" + name + '\'' +
", type='" + type + '\'' +
", color='" + color + '\'' +
", price=" + price +
'}';
}
}
4、修改CarController
package cn.tedu.controller;
import cn.tedu.pojo.Car;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("car")
public class CarController {
//解析浏览器用get方式发来的汽车数据
@RequestMapping("get")
public Car get(){
Car c = new Car();
c.setId(100);
c.setPrice(19.9);
return c;
}
//普通get方式提交的数据:http://localhost:8080/car/add?id=10&name=BMW&price=9.9
@RequestMapping("add")
public String add(Integer id,String name,Double price){
return id+name+price ;
}
/**优化get提交数据的方式restful:http://localhost:8080/car/add2/10/BMW/9.9*/
@RequestMapping("add2/{id}/{y}/{x}")//{id}是占位符,表示这个参数的位置
public void add2(@PathVariable Integer id, //@PathVariabl用来获取{}中间的值
@PathVariable String y,
@PathVariable Double x){
System.out.println(id+y+x);
}
}
5、测试
六、ajax提交请求数据
1、创建新的网页html,添加ajax代码
注意点:
1)一定要导入jQuery包
2)严格填写标点符号,单词书写正确,否则就是语法错误
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="old/jquery-1.8.3.min.js"></script>
<script>
function a(){
$.ajax({
type: "get" ,//要使用的请求方式
url:"http://localhost:8080/car/get" , //要使用的请求路径
data: {//要拼接的数据---必须是JSON串
"id":"10",
"name":"BMW",
"price":"9.9"
},
success: function(data){ //成功时得到js对象
console.log(data);
console.log(data.id);//使用js方法获取想要的属性
alert(100);
}
})
}
</script>
</head>
<body>
<a onclick="a();" href="#">点我获取汽车数据</a>
</body>
</html>
2、改造CarController类,加一个跨域的注解@CrossOrigin
注意:ajax只能和get方法联用,不能和add、add2方法联用
package cn.tedu.controller;
import cn.tedu.pojo.Car;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("car")
@CrossOrigin //----解决跨域问题
public class CarController {
//解析浏览器用get方式发来的汽车数据
@RequestMapping("get")
public Car get(){
Car c = new Car();
c.setId(100);
c.setPrice(19.9);
return c;
}
//普通get方式提交的数据:http://localhost:8080/car/add?id=10&name=BMW&price=9.9
@RequestMapping("add")
public String add(Integer id,String name,Double price){
return id+name+price ;
}
//优化get提交数据的方式restful:http://localhost:8080/car/add2/10/BMW/9.9
@RequestMapping("add2/{id}/{y}/{x}")//{id}是占位符,表示这个参数的位置
public void add2(@PathVariable Integer id, //@PathVariabl用来获取{}中间的值
@PathVariable String y,
@PathVariable Double x){
System.out.println(id+y+x);
}
}
3、测试
七、SpringMVC常用的注解
@Controller 标识是一个Controller,Spring包扫描创建实例
@RequestMapping 请求后的映射路径
@PathVariable 标识接收单个参数
@ResponseBody 返回对象利用jackson工具类转换为json字符串
@RequestParam 参数名和请求参数名称不同时使用,可以设置默认值