控制层框架SpringMVC
1. 初识SpringMVC
-
springmvc框架是由模块组成的,每个模块用了最好的技术。
- Springmvc有对象转json模块(控制器controller返回json),以前用过fastjson,gson,现在用的是jackson。
- Mybatis的连接池用过c3p0,现在用的是hikari连接池
-
作用:
- 接收参数
- 返回数据
2. 后端相关
2.1 接收参数
springmvc框架会自动把url中数据赋值给对应的参数,实现url映射。
2.2 request,response对象
- request:用来接收数据 ,是服务器对浏览器请求的封装
eg: register(String username) 框架底层用的是request
相当于request.getParameter(“username”) - response:是服务器对服务器响应的封装
eg: register(){return }框架的底层用的是response
package com.tedu.springmvc01_request.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
//相当于servlet
@RestController
public class UserController {
@RequestMapping("/register1")
//以前通过request.getParameter("username")来接收
//springmvc内部使用request来接收username
public String register(String username,String password) {
return "服务器收到了"+username+","+password;
}
@RequestMapping("/register2")
//通过一个对象来接收数据
public String register2(User user) {
return "服务器收到了"+user.getUsername()+","+user.getPassword();
}
@RequestMapping("/delete1")
public String delete1(Integer id) {
return "id="+id;
}
//通过request.getParameter(id) 得到的是null
//把null转成int,浏览器显示500
//接收参数时要用引用类型
//controller是单例,每次请求用的是同一个对象
@RequestMapping("/delete2")
public String delete2(int id) {
String objectInfo = this.toString();
return "id="+id+"对象="+objectInfo;
}
}
测试结果:
- 接收参数时要用引用类型
public String delete1(Integer id){}
public String delete2(int id){}
当没有传id的值时,通过request.getParameter(id) 得到的是null,把null转成int时,浏览器显示500,所以接收参数时要用引用类型
测试结果:
- controller是单例,每次请求用的是同一个对象
2.3 注解和反射
2.3.1 注解
需求:
框架自动创建对象
注解:
- @Target(ElementType.TYPE) 指定注解的使用范围(注解可以用在什么地方)
ElementType的常用取值:- TYPE:类, 接口 (包括注解类型), 或 枚举声明
- FIELD:字段声明(包括枚举常量)
- METHOD:用于描述方法
- PACKAGE:用于描述包
- CONSTRUCTOR:构造函数声明
- LOCAL_VARIABLE:局部变量声明
- PARAMETER:用于描述参数
- @Retention(RetentionPolicy.RUNTIME) 指定注解保留多久
RetentionPolicy的取值:- RUNTIME:在运行时有效
- CLASS:在class文件中有效
- SOURCE:在源文件中有效
代码实现:
- 定义注解
package org.springmvc;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//定义注解
@Target(ElementType.TYPE)//指定注解加在类上
@Retention(RetentionPolicy.RUNTIME)//在运行时有效
//指定注解的作用域
public @interface RestController {
}
- 处理注解
package org.springmvc;
//处理注解
//springmvc框架启动时执行
public class SpringMVCMain {
public static void main(String[] args) throws Throwable {
//判断类有没有加@RestController注解
//1.通过类名得到类对象
Class clazz=UserController.class;
//2.通过类对象能创建对象,得到类的方法、类的属性
RestController restController = (RestController) clazz.getAnnotation(RestController.class);
if (restController!=null) {
//3.如果加了注解,自动创建对象
UserController userController=(UserController) clazz.newInstance();
System.out.println(userController.toString());
}
}
}
- 使用注解
package com.tedu;
import org.springmvc.RestController;
//项目中的类,使用注解
@RestController
public class UserController {
}
2.3.2 反射
需求:
创建很多对象,给私有属性赋值
代码实现:
package com.tedu;
public class UserController {
//统计访问数量
private int accessCount=0;
@Override
public String toString() {
return "UserController [accessCount=" + accessCount + "]";
}
}
package com.tedu;
public class OrderController {
//统计访问数量
private int accessCount=0;
@Override
public String toString() {
return "OrderController [accessCount=" + accessCount + "]";
}
}
package org.springmvc;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class SpringMvcMain {
public static void main(String[] args) throws Throwable{
//利用反射给所有的controller的私有属性赋值
String[] classNames = {"com.tedu.OrderController","com.tedu.UserController"};
for (String className : classNames) {
//根据字符串创建对象,(即反射)
//clazz是个类对象
Class clazz = Class.forName(className);
//通过类对象创建对象
Object object = clazz.newInstance();
//通过反射得到所有的属性
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
//用反射给private属性赋值
field.setAccessible(true);//true相当于把private变为public
field.set(object, 800);
}
//用反射调用方法
//以前是用object.method()
//1.得到所有的方法
Method[] methods = clazz.getDeclaredMethods();
//2.遍历所有方法
for (Method method : methods) {
//3.通过method.invoke去执行方法
System.out.println(className);
System.out.println(" "+method.getName());
System.out.println(method.invoke(object));
}
}
}
}
测试结果:
2.4 SpringMVC框架原理
loadObject(); 把所有的方法放到urlMapping
- 把文件名转成类名controllerNames
- 遍历所有的类,判断类有没有加@RestController注解
- 如果加了@RestController注解,通过反射得到类的所有方法
- 遍历类的所有方法,判断方法有没有加@requestMapping注解
- 如果加了@requestMapping注解,得到requestMapping的value属性(赋值给url)
- 得到方法名methodName
- 创建controllerdefinition对象 ControllerDefinition(controllerName, methodName)
- 把url,controllerdefinition放到urlMapping
processRequest("/login"); 浏览器发过来请求,找到方法去处理
- 根据url从urlMapping中找到controllerDefinition
- 得到controllerName,methodName
- 用反射根据类名得到类对象
- 用类对象创建实例对象
- 得到Method对象
- method.invoke(object)
- 打印结果
代码实现:
- 定义RequestMapping注解,加上这个注解的方法,可以通过浏览器执行执行
- 定义RestController,注解加上这个注解spingmvc会自动创建对象
- 封装类名和方法名
- controller层,使用注解
- SpringMvc框架入口类
2.5 Cookie和Session
Cookie:
作用:识别用户
- 设置Cookie
- 读取Cookie
补充:不登录设置cookie
需求:用户不登录情况下,记录用户访问了那些网页。
Session:
与cookie的关系:
- Session的数据是存在服务器内存中,服务器重启数据就没了
- Session是用临时cookie实现的,浏览器一关数据就没有了
- Cookie的数据是存在浏览器中的
禁用cookie后,如何使用session?
- URL重写(把session id直接附加在URL路径的后面)
- 添加一个表单隐藏字段,在表单提交时能够把session id传递回服务器
2.6 拦截器
拦截器配置
常用场景:
- 统计controller执行时间
- 完成身份验证
2.7 跳转
- redirect 重定向
重定向浏览器地址栏显示新的地址,重定向可以重定向别的网站 - forward 转发
转发地址栏不变,转发只能转发到本网站中的方法