川职院-课堂笔记(节节更新)
每日笔记整理:
目录- 每日笔记整理:
- 2022-05-18
- 2022-05-19:
- IOC容器的作用?
- 什么是控制反转?
- IOC容器的分类:
- 在Spring中配置bean的内容
- 2022-05-20
- 构造器注入方法
- 通过setter方法注入
- 集合类型输入
- bean自动装配
- 基于注解化的配置
- 1. 依赖注入的注解
- 2.bean 的生命周期函数注解
- 3.实现容器的配置注解(替代spring.xml的作用)
- 5.Bean的作用域配置
- 2022-05-21
- 问题:
- SpringJDBC
- 2022-05-22
- Spring包的自动扫描
- 总结:
- Lombok常用注解
- 2022-05-23
- 2022-05-24
- 登录-判断-页面跳转课程案例
- 2022-05-25
- 2022-05-26
- 2022-05-27
2022-05-18
2022-05-19:
IOC容器的作用?
什么是控制反转?
IOC容器的分类:
BeanFactory接口:
? xmlBeanFactory类实现
ApplicationContext接口:
? ClassPathXmlApplicationContext类实现
? FileSystemXmlApplicationContext类实现
? WebXmlApplicationContext类实现
在Spring中配置bean的内容
常用配置属性:(XML文件中bean标签的属性配置)
1.scope: 配置bean的作用域(默认是单例,singleton),其他属性值:prototype、request、session 和 global session
2.lazy-init:配置bean的实例加载的时间,值为true:在getbean或者需要实例的时候才被初始化
? 值为false:在容器加载的时候初始化
3.init-method:配置当bean初始化完成后的回调
4.destroy-method:配置当bean销毁后的回调
5.abstract:配置当前bean可以作为一个父元素让子元素bean实现属性的继承
6.parent:配置容器当中其中一个bean作为父元素,继承父元素中所有的属性值
接口化配置内容:
1.初始化接口:实现InitializingBean 接口,实现afterPropertiesSet方法 - 初始化
2.实现DisposableBean 接口,实现destroy方法 -销毁
前后置处理器
作用:能够重用两段代码,在bean的初始化完成之前和之后调用
public class InitHelloWorld implements BeanPostProcessor {
/*前置处理*/
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("前置处理器处理中!------>"+beanName);
return bean;
}
/*后置处理器*/
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("后置处理器处理中!------>"+beanName);
return bean;
}
}
bean的生命周期加载顺序图
2022-05-20
什么是依赖注入?(DI)
依赖注入的方法有哪些?该怎么写怎么配置?
构造器注入方法
1.通过构造器注入(引用实例)
2.通过构造器注入(内部bean注入)
通过setter方法注入
1.通过属性自动调用setter方法注入
2.setter内部bean注入
集合类型输入
1.List集合注入
2.Set集合注入
3.Map集合注入
4.Properties注入
集合中引用的注入
bean自动装配
在bean标签上设置autowire属性值
。。。
基于注解化的配置
1. 依赖注入的注解
@Autowired 注解
作用:默认是根据类型完成注入,可以放在setter方法、构造器、成员变量上,自动实现依赖注入
@Autowired(required = false )
代表当前注入的bean非必须,默认情况是必须要完成注入的
@Qualifier注解
配合@Autowired 注解,指定要注入的bean是谁,参数中填写bean的id值或name值
@Resource注解
默认是根据类型自动注入,但是注意idea不会出现错误提示,只有运行后不正确才会报错,@Autowired是会有错误注入提示的。
@Resource(name = "bean的id或name属性值")
@Resource(type = "类名.class")
2.bean 的生命周期函数注解
@PostConstruct :替代在xml中配置init-method 属性
@PreDestroy:替代在xml中配置destroy-method
3.实现容器的配置注解(替代spring.xml的作用)
@Configuration: 标识这是一个配置bean实例的类(放在类声明上)
@Bean: 标识一个返回实例对象的方法(放在方法声明上)
使用注解化容器配置,加载ioc容器方法就发生了改变
1.单个配置类的注册
2.注册多个配置类的方法
5.Bean的作用域配置
@Scope("prototype")
多实例,IOC容器启动创建的时候,并不会创建对象放在容器在容器当中,当你需要的时候,需要从容器当中取该对象的时候,就会创建。
@Scope("singleton")
单实例 IOC容器启动的时候就会调用方法创建对象,以后每次获取都是从容器当中拿同一个对象(map当中)。
@Scope("request")
同一个请求创建一个实例
@Scope("session")
同一个session创建一个实例
2022-05-21
问题:
** AOP是什么?AOP的作用是什么?**
** AOP的实现有几种方法?区别是什么? **
** Aop的术语 **
AOP 领域中的特性术语:
通知(Advice): AOP 框架中的增强处理。通知描述了切面何时执行以及如何执行增强处理。
连接点(join point): 连接点表示应用执行过程中能够插入切面的一个点,这个点可以是方法的调用、异常的抛出。在 Spring AOP 中,连接点总是方法的调用。
切点(PointCut): 可以插入增强处理的连接点。
切面(Aspect): 切面是通知和切点的结合。
引入(Introduction):引入允许我们向现有的类添加新的方法或者属性。
织入(Weaving): 将增强处理添加到目标对象中,并创建一个被增强的对象,这个过程就是织入。
** 通知的类型 **
前置通知 before 在一个方法执行之前,执行通知。
后置通知 after 在一个方法执行之后,不考虑其结果,执行通知。
返回后通知 after-returning 在一个方法执行之后,只有在方法成功完成时,才能执行通知。
抛出异常后通知 after-throwing 在一个方法执行之后,只有在方法退出抛出异常时,才能执行通知。
环绕通知 around 在建议方法调用之前和之后,执行通知。
** AOP必须要引入的包 **
org.aspectj
aspectjweaver
1.9.8.RC3
** 切点表达式写法 **
方法表达式以 * 号开始,标识我们不关心方法的返回值类型。然后我们指定了全限定类名和方法名。对于方法参数列表,我们使用 .. 标识切点选择任意的play方法,无论该方法的入参是什么。
** 各类通知的xml定义方法 **
...
...
** 理解通知中的作用 **
** demo案例 **
** 环绕通知 **
Spring AOP的环绕通知和前置、后置通知有着很大的区别,主要有两个重要的区别:
1)目标方法的调用由环绕通知决定,即你可以决定是否调用目标方法,而前置和后置通知是不能决定的,它们只是在方法的调用前后执行通知而已,即目标方法肯定是要执行的。joinPoint.proceed()就是执行目标方法的代码。
2)环绕通知可以控制返回对象,即可以返回一个与目标对象完全不同的返回值。虽然这很危险,但是却可以做到。
** ProceedingJoinPoint接口 **
(1)获取切入点方法的名字
getSignature());是获取到这样的信息 :返回值类型+ 包名+类名+方法名,
//获取方法名
String methodName = joinPoint.getSignature().getName()
(2)获取方法上的注解
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method != null)
{xxxxxx annoObj= method.getAnnotation(xxxxxx.class);}
return null;
(3)获取方法的参数
这里返回的是切入点方法的参数列表
Object[] args = joinPoint.getArgs();
(4)调用切入点的方法
有返回值则返回对象,没有返回值则为null
Object res = joinPoint.proceed();
SpringJDBC
Spring JDBC 框架负责所有的低层细节,从开始打开连接,准备和执行 SQL 语句,处理异常,处理事务,到最后关闭连接。
1.引入SpringJDBC依赖,以及mysql驱动依赖
org.springframework
spring-jdbc
5.3.15
mysql
mysql-connector-java
8.0.21
2.配置数据源(在Spring的配置文件中配置)
3.创建JdbcTemplate对象
//1.加载容器
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
//2.获取数据源对象
DriverManagerDataSource dataSource = (DriverManagerDataSource) context.getBean("dataSource");
//3.创建jdbcTemplate对象,构造器传入数据源对象加载
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
4.查询功能(单行和多行)
//查询数据,查询返回list集合
List
4.1 查询结果集合java实体(POJO类)字段自动映射
(1)编写一个mapper类实现RowMapper
作用:将结果集与实体类字段产生关联
public class UserMapper implements RowMapper {
@Override
public UserDto mapRow(ResultSet rs, int rowNum) throws SQLException {
UserDto dto = new UserDto();
dto.setCode(rs.getString("name"));
dto.setName(rs.getString("code"));
return dto;
}
}
(2)调用jdbcTemplate的查询结果集与字段映射实现功能
//只能查询结果集为一行的数据,并把结果集数据与实体字段映射封装返回
UserDto userDto = jdbcTemplate.queryForObject(sql, new UserMapper());
//查询多行数据,并把结果集数据与实体字段映射封装返回
List query = jdbcTemplate.query(sql2, new UserMapper());
2022-05-22
Spring包的自动扫描
1.开启以及配置包的自动扫描(在Spring.xml文件中)
填写要扫描的包结构
在xml配置了这个标签后,spring可以自动去扫描base-pack下面或者子包下面的java文件,如果扫描到有@Component @Controller@Service等这些注解的类,则把这些类注册为bean
另外http://localhost:8080/toUser/1 或 http://localhost:8080/toUser/hahaha 都能够正常访问
(2)path属性
path 属性和 value 属性都用来作为映射使用。即 @RequestMapping(value="toUser") 和 @RequestMapping(path="toUser") 都能访问 toUser() 方法。
(3)name属性
name属性相当于方法的注释,使方法更易理解。如 @RequestMapping(value = "toUser",name = "获取用户信息")。
(4)method属性
method 属性用于表示该方法支持哪些 HTTP 请求。如果省略 method 属性,则说明该方法支持全部的 HTTP 请求。
@RequestMapping(value = "toUser",method = RequestMethod.GET) 表示该方法只支持 GET 请求。也可指定多个 HTTP 请求,如 @RequestMapping(value = "toUser",method = {RequestMethod.GET,RequestMethod.POST}),说明该方法同时支持 GET 和 POST 请求。
(5)params属性
params 属性用于指定请求中规定的参数
以上代码表示请求中必须包含 type 参数时才能执行该请求。即 http://localhost:8080/toUser?type=xxx 能够正常访问 toUser() 方法,而 http://localhost:8080/toUser 则不能正常访问 toUser() 方法
以上代码表示请求中必须包含 type 参数,且 type 参数为 1 时才能够执行该请求。即 http://localhost:8080/toUser?type=1 能够正常访问 toUser() 方法,而 http://localhost:8080/toUser?type=2 则不能正常访问 toUser() 方法。
SpringMVC-controller方法接收请求参数的方法
(1)使用HttpServletRequest对象的getParameter方法接收
/**
* 页面跳转的开发 ( 当前请求只能通过post请求访问)
* @return
*/
@RequestMapping(value="/login",method = RequestMethod.GET)
public String toLogin(HttpServletRequest request) throws IOException {
System.out.println("跳转到登录页面的方法");
request.setCharacterEncoding("UTF-8");
//通过Servlet API的方法来获取请求的参数 getParameter
String name = request.getParameter("name");
System.out.println("name参数:"+name);
return "login";//逻辑视图名称 通过视图解析器自动拼接解析 /WEB-INF/views/login.jsp
}
SpringMVC-controller方法-返回数据集到视图层的方法
(1)使用SpringMVC的Model对象,调用addAttribute
@RequestMapping(value="/login",method = RequestMethod.GET)
public String toLogin(Model model) throws IOException {
System.out.println("跳转到登录页面的方法");
//设置返回前端的数据(键值对设置方法)
model.addAttribute("key","value"); // ${key}
//设置返回一个对象内容
Dog dog = new Dog();
dog.setName("哈哈");
dog.setType("金毛");
model.addAttribute(dog); // ${dog.name} 哈哈 {dog.type} 金毛
return "login";//逻辑视图名称 通过视图解析器自动拼接解析 /WEB-INF/views/login.jsp
}
jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
登录页面
欢迎来到登录页面
${dog.name}
${dog.type}
登录-判断-页面跳转课程案例
1.java代码-controller控制器代码
@Controller
@RequestMapping("/sys")
public class SysController {
/**
* 页面跳转的开发 ( 当前请求只能通过post请求访问)
* @return
*/
@RequestMapping(value="/login",method = RequestMethod.GET)
public String toLogin(Model model,HttpServletRequest request) throws IOException {
System.out.println("进行登录判断操作方法...");
String userNamer = request.getParameter("userNamer");
String pwd = request.getParameter("pwd");
String sys_userName = "root";
String sys_pwd = "123456";
if(sys_userName.equals(userNamer)&&sys_pwd.equals(pwd)){
//登录成功-》登录成功页面
model.addAttribute("userName",userNamer); //${userName}
return "ok";
}else{
//登录失败
return "notOk";
}
}
}
2.登录页面,编写在webapp根目录下的index.jsp页面,这样当项目启动时就可以访问登录页面
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
登录
3.成功页面,通过el表达式取出返回到视图层的数据
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
登录成功
欢迎进入系统!${userName}....
\
4.失败页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
登录失败
用户名或密码错误!....
SpringMVC参数的传递方式
(1)通过实体Bean接收请求参数
(2)通过处理方法的形参接收请求参数
通过处理方法的形参接收请求参数就是直接把表单参数写在控制器类相应方法的形参中,即形参名称与请求参数名称完全相同。该接收参数方式适用于 get 和 post 提交请求方式。
(3)通过HttpServletRequest接收请求参数
通过 HttpServletRequest 接收请求参数适用于 get 和 post 提交请求方式
(4)通过@PathVariable接收URL中的请求参数
通过 @PathVariable 获取 URL 中的参数
在访问“http://localhost:8080/springMVCDemo02/user/login/bianchengbang/123456”路径时,上述代码会自动将 URL 中的模板变量 {name} 和 {pwd} 绑定到通过 @PathVariable 注解的同名参数上,即 name=bianchengbang、pwd=123456。
(5)通过@RequestParam定义接收的请求参数
在方法入参处使用 @RequestParam 注解指定其对应的请求参数。@RequestParam 有以下三个参数:
value:参数名
required:是否必须,默认为 true,表示请求中必须包含对应的参数名,若不存在将抛出异常
defaultValue:参数默认值
通过 @RequestParam 接收请求参数适用于 get 和 post 提交请求方式
该方式与“通过处理方法的形参接收请求参数”部分的区别如下:当请求参数与接收参数名不一致时,“通过处理方法的形参接收请求参数”不会报 400错误,而“通过 @RequestParam 接收请求参数”会报 400 错误。
请求的重定向和请求的转发
Spring MVC 请求方式分为转发、重定向 2 种,分别使用 forward 和 redirect 关键字在 controller 层进行处理。
请求转发:
客户浏览器发送 http 请求,Web 服务器接受此请求,调用内部的一个方法在容器内部完成请求处理和转发动作,将目标资源发送给客户;在这里转发的路径必须是同一个 Web 容器下的 URL,其不能转向到其他的 Web 路径上,中间传递的是自己的容器内的 request。
请求重定向:
客户浏览器发送 http 请求,Web 服务器接受后发送 302 状态码响应及对应新的 location 给客户浏览器,客户浏览器发现是 302 响应,则自动再发送一个新的 http 请求,请求 URL 是新的 location 地址,服务器根据此请求寻找资源并发送给客户。
在这里 location 可以重定向到任意 URL,既然是浏览器重新发出了请求,那么就没有什么 request 传递的概念了。在客户浏览器的地址栏中显示的是其重定向的路径,客户可以观察到地址的变化。重定向行为是浏览器做了至少两次的访问请求。
转发重定向到非视图解析器资源时
配置静态资源目录,一定要在webapp根目录
在dispacther-servlet.xml配置文件中配置:
SpringMVC标准开发模式
1.分层架构,controller层处理请求和响应,service以及serviceimpl层作为业务的接口和业务的实现层
优点:分层架构的模式可以让我们的代码解耦,让代码更优雅,且内聚少低耦合。
案例演示:
(1)控制器层
/**
* 用户管理-控制器层
*/
@Controller
@RequestMapping("/user")
public class UserController {
//注入接口实现
@Resource(name = "oracleUserService")
private UserService userService;
/**
* 查询用户信息
* @return
*/
@RequestMapping(value = "/getUser",method = RequestMethod.GET)
public String getUserData(){
userService.getUserData();
return null;
}
}
(2)接口层
/**
* 用户管理-业务-接口层
* 2022/5/24
*/
public interface UserService {
String getUserData();
}
(3)接口实现层
实现类1
@Service
public class UserServiceImpl implements UserService {
@Override
public String getUserData() {
System.out.println("UserServiceImpl-实现");
return null;
}
}
实现类2
@Service
public class OracleUserService implements UserService {
@Override
public String getUserData() {
System.out.println("OracleUserService实现");
return null;
}
}
2022-05-25
类型转换器
Spring MVC 框架的 Converter<S,T> 是一个可以将一种数据类型转换成另一种数据类型的接口,这里 S 表示源类型,T 表示目标类型。开发者在实际应用中使用框架内置的类型转换器基本上就够了,但有时需要编写具有特定功能的类型转换器。
类型转换器的工作时机
类型转换是在视图与控制器相互传递数据时发生的。Spring MVC 框架对于基本类型(例如 int、long、float、double、boolean 以及 char 等)已经做好了基本类型转换。
注意:在使用内置类型转换器时,请求参数输入值与接收参数类型要兼容,否则会报 400 错误。
SpringMVC内置转换器
自定义类型转换器
例如需要用户在页面表单中输入信息来创建商品信息。当输入“gaojingbo,27,2.3”时表示在程序中自动创建一个 new User,并将“gaojingbo”值自动赋给 name 属性,将“27”值自动赋给 age 属性,将“2.3”值自动赋给 height 属性。
如果想实现上述应用,需要做以下 5 件事:
- ? 创建实体类。
- ? 创建控制器类。
- ? 创建自定义类型转换器类。
- ? 注册类型转换器。
(1)创建实体类(UserDto)
import lombok.Data;
/**
* 转换的目标实体 UserDto
* 2022/5/25
*/
@Data
public class UserDto {
private String name;
private Integer age;
private Double height;
}
(2) 创建自定义转换类
/**
* String 转换为 UserDto的转换器
* 2022/5/25
*/
@Component
public class String2UserDtoConvter implements Converter {
/**
* 手动编写转换
* @param s 源数据
* @return 返回转换的数据
*/
@Override
public UserDto convert(String s) { //name,age,height
UserDto dto = new UserDto();
String[] split = s.split(","); //[name,age,height];
if(split.length!=3){
throw new IllegalArgumentException("String2UserDtoConvter类型转换错误,源数据类型必须是:name,age,height");
}else{
dto.setName(split[0]);
dto.setAge(Integer.valueOf(split[1]));
dto.setHeight(Double.valueOf(split[2]));
return dto;
}
}
}
(3)注册类型转换器 (在springMVC视图解析器配置文件中)
(4)编写控制器层代码,定义接收参数
@RequestMapping("/s2user")
public String StringToUserTest(@RequestParam("user") Date date){
System.out.println("测试转换:String-》LocalDate");
System.out.println(date);
return "ok";
}
数据格式化(Formatter)
Spring MVC 框架的 Formatter
与 Converter 一样,也是一个可以将一种数据类型转换成另一种数据类型的接口。不同的是,Formatter 的源类型必须是 String 类型,而 Converter 的源类型可以是任意数据类型。Formatter 更适合 Web 层,而 Converter 可以在任意层中。所以对于需要转换表单中的用户输入的情况,应该选择 Formatter,而不是 Converter。在 Web 应用中由 HTTP 发送的请求数据到控制器中都是以 String 类型获取,因此在 Web 应用中选择 Formatter
比选择 Converter 更加合理。
Spring MVC 提供了几个内置的格式化转换器
? NumberFormatter:实现 Number 与 String 之间的解析与格式化。
? CurrencyFormatter:实现 Number 与 String 之间的解析与格式化(带货币符号)。
? PercentFormatter:实现 Number 与 String 之间的解析与格式化(带百分数符号)。
? DateFormatter:实现 Date 与 String 之间的解析与格式化。
自定义格式化转换器就是编写一个实现 org.springframework.format.Formatter 接口的 Java 类。
这里的 T 表示由字符串转换的目标数据类型。该接口有 parse 和 print 两个接口方法,自定义格式化转换器类必须覆盖它们。
(1)parse 方法:
的功能是利用指定的 Locale 将一个 String 类型转换成目标类型,
(2)print 方法:
与之相反,用于返回目标对象的字符串表示。
案例,实现实体中Date字段与String字段转换
(1)编写实体类
/**
* 转换的目标实体 UserDto
* 2022/5/25
*/
@Data
public class UserDto {
private String name;
private Integer age;
private Double height;
private Date time;
}
(2)编写formatter类
/**
* String -> Date格式化类
* 2022/5/25
*/
public class String2DateFormatter implements Formatter {
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
/**
* String -> 目标
* @param s
* @param locale
* @return
* @throws ParseException
*/
@Override
public Date parse(String s, Locale locale) throws ParseException {
return sdf.parse(s);
}
/**
* 目标 -》 String
* @param date
* @param locale
* @return
*/
@Override
public String print(Date date, Locale locale) {
return sdf.format(date);
}
}
(3)注册formatter类
(4)控制器层当出现参数传递,自动实现转换
@RequestMapping("/s2user")
public String StringToUserTest(UserDto dto){
System.out.println("测试转换:String-》UserDto");
System.out.println(dto);
return "ok";
}
2022-05-26
JavaScript中json对象与字符串的相互转换方法
//js对象
var obj = {
name:"张三",
age:18,
sons:["老大","老二","老六"]
};
console.dir(obj);
//对象 -》 json字符串
let jsonStr = JSON.stringify(obj);
console.dir(jsonStr);
//json字符串变为json对象或js对象
var parse = JSON.parse(jsonStr);
console.dir(parse);
JQuery-ajax写法
$.ajax({
url:"${pageContext.request.contextPath}/sys/getUser",
method:"GET",//请求方法
async:false,// 异步参数值为true时:接口请求是异步执行的,为false是同步执行的
data:{name:"张三",age:18},//传递json字符串
contentType:"application/json",//请求报文内容是json
dataType:"JSON",//数据传递的内容都是json(请求和响应)
success:function(data){//如果请求成功,执行success回调,data就是后端返回到前端的数据(一般就是json数据)
console.dir(data);
console.dir("2.成功");
},
error:function(err){//如果请求失败,error回调,err是后端系统异常抛出的数据
console.dir(err);
}
});
Web开发中json的数据传递内容
(1)前端发送json数据到后端
1.post请求类型情况
post的要求:
(1)请求的参数是保存在请求体中的;
(2)想要发送json数据时,请求参数必须是json字符串(使用JSON.stringify方法把json对象变成json字符串)
(3)后端controller方法中接收参数的javabean必须要添加@RequestBody注解
前端ajax代码:
$.ajax({
url:"${pageContext.request.contextPath}/sys/getUser",
method:"POST",//请求方法
async:false,// 异步参数值为true时:接口请求是异步执行的,为false是同步执行的
data:JSON.stringify({name:"张三",age:18}),//传递json字符串
contentType:"application/json",//请求报文内容是json
dataType:"JSON",//数据传递的内容都是json(请求和响应)
success:function(data){//如果请求成功,执行success回调,data就是后端返回到前端的数据(一般就是json数据)
console.dir(data);
console.dir("2.成功");
},
error:function(err){//如果请求失败,error回调,err是后端系统异常抛出的数据
console.dir(err);
}
});
后端实体类
/**
* 转换的目标实体 UserDto
* 2022/5/25
*/
@Data
public class UserDto {
private String name;
private Integer age;
private Double height;
private Date time;
}
后端controller
@RequestMapping(value = "/getUser",method = RequestMethod.POST)
@ResponseBody
public UserDto getUser(@RequestBody UserDto dto2) throws InterruptedException {
System.out.println("调用到方法!");
Thread.sleep(10000);
System.out.println(dto2);
return dto2;//@ResponseBody 让返回的java对象变成一段json
}
2.get请求类型情况
GET请求不能发送JSON数据
GET请求只能发送普通表单数据
前端ajax代码
$.ajax({
url:"${pageContext.request.contextPath}/sys/getUser",
method:"GET",//请求方法
async:false,// 异步参数值为true时:接口请求是异步执行的,为false是同步执行的
data:{name:"张三",age:18},//传递json字符串
contentType:"application/json",//请求报文内容是json
dataType:"JSON",//数据传递的内容都是json(请求和响应)
success:function(data){//如果请求成功,执行success回调,data就是后端返回到前端的数据(一般就是json数据)
console.dir(data);
console.dir("2.成功");
},
error:function(err){//如果请求失败,error回调,err是后端系统异常抛出的数据
console.dir(err);
}
});
后端controller代码
@RequestMapping(value = "/getUser",method = RequestMethod.GET)
@ResponseBody
public UserDto getUser(UserDto dto2) throws InterruptedException {
System.out.println("调用到方法!");
Thread.sleep(10000);
System.out.println(dto2);
return dto2;//@ResponseBody 让返回的java对象变成一段json
}
SpringMVC数据校验问题
1.需要引入数据校验相关包
javax.validation
validation-api
1.1.0.Final
org.jboss.logging
jboss-logging
3.1.0.CR2
org.hibernate
hibernate-validator
5.1.0.Final
2.在controller方法接收参数实体中添加校验注解
/**
* 转换的目标实体 UserDto
* 2022/5/25
*/
@Data
public class UserDto {
@NotNull(message = "用户名不能为空")
private String name;
private Integer age;
private Double height;
private Date time;
}
3.在controller方法参数前添加@Valid注解
当前端请求进来时,就会自动完成数据校验
@RequestMapping(value = "/getUser",method = RequestMethod.GET)
@ResponseBody
public UserDto getUser(@Valid UserDto dto2, BindingResult result) throws InterruptedException {
System.out.println("调用到方法!");
if(result.hasErrors()){//返回true说明校验出现错误
//获取异常信息的列表
List allErrors = result.getAllErrors();
//遍历输出错误信息
for(ObjectError err: allErrors){
System.out.println(err.getDefaultMessage());
}
}
return dto2;//@ResponseBody 让返回的java对象变成一段json
}
}
SpringMVC配置REST接口风格
Spring REST 风格可以简单理解为:使用 URL 表示资源时,每个资源都用一个独一无二的 URL 来表示,并使用 HTTP 方法表示操作,即准确描述服务器对资源的处理动作(GET、POST、PUT、DELETE),实现资源的增删改查
GET:表示获取资源(查询)
POST:表示新建资源(保存数据、登录、文件上传、下载)
PUT:表示更新资源(修改数据)
DELETE:表示删除资源(删除资源数据)
1.引入jackson依赖(确定是否引入)
com.fasterxml.jackson.core
jackson-core
2.12.3
com.fasterxml.jackson.core
jackson-databind
2.12.3
2.配置一个过滤器
作用:由于 HTTP 不支持 PUT 和 DELETE 请求,所以需要将 DELETE 和 PUT 请求转换成 POST 请求,在 web.xml 中配置过滤器 HiddenHttpMethodFilter。
配置在web.xml文件中
hiddenHttpMethodFilter
org.springframework.web.filter.HiddenHttpMethodFilter
hiddenHttpMethodFilter
/*
注意:如果你的webapp标签报错,web-app开始标签替换成以下内容:
测试一个DELETE请求
1.ajax代码
$.ajax({
url:"${pageContext.request.contextPath}/sys/test1",
method:"DELETE",//请求方法
async:false,// 异步参数值为true时:接口请求是异步执行的,为false是同步执行的
data:null,//传递json字符串
dataType:"JSON",//数据传递的内容都是json(请求和响应)
success:function(data){//如果请求成功,执行success回调,data就是后端返回到前端的数据(一般就是json数据)
console.dir(data);
console.dir("2.成功");
},
error:function(err){//如果请求失败,error回调,err是后端系统异常抛出的数据
console.dir(err);
}
});
2.controller代码
@RequestMapping(value = "/test1",method = RequestMethod.DELETE)
@ResponseBody
public Map testMethod(){
System.out.println("请求put类型接口");
return null;
}
上午作业案例:
1.定义一个注册页面,有表单项目用户名、密码、生日(日期选择器)
2.提交表单的方法使用JavaScript实现绑定,当点击提交按钮的时候触发ajax提交后端接口
3.后端是post请求,前端要发送一个json字符串如何发送
4.后端接收请求成功后,将接收的参数封装成json返回前端
5.返回前端后前端ajax接收后端返回的数据,将数据输出到一个自定义的div中,用span或者其他文字标签展示内容
代码案例:
(1)controller代码
package com.huawei.sys.controller;
import com.huawei.sys.dto.RegisterDto;
import com.huawei.sys.service.UserService;
import com.huawei.sys.service.impl.OracleUserService;
import com.huawei.sys.service.impl.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
/**
* 用户管理-控制器层
*/
@Controller
@RequestMapping("/user")
public class UserController {
/**
* 首先得有方法跳转到注册页面才能进行注册操作
* 注意:方法返回值类型为String,返回逻辑视图名
* 因为是页面的跳转所以不要添加@ResponseBody注解
* @return
*/
@RequestMapping(value = "/toRegister",method = RequestMethod.GET)
public String toRegister(){
System.out.println("跳转到注册页面!");
return "register";//返回注册页面的逻辑视图名称
}
/**
* 注册用户的方法
* 注意:因为会出现数据的保存操作,所以建议使用post请求,而且加上要传递json数据所以必须使用post请求
* @ResponseBody 注解:让返回数据封装为json数据发送到前端
* @RequestBody 注解:从请求体中取出数据和RegisterDto类属性字段值映射保存
* @param dto
* @return
*/
@RequestMapping(value = "/toAddUser",method = RequestMethod.POST)
@ResponseBody
public RegisterDto toRegister(@RequestBody RegisterDto dto){
System.out.println("用户注册");
System.out.println(dto);
return dto;
}
}
(2)参数实体代码
package com.huawei.sys.dto;
import lombok.Data;
import java.util.Date;
/**
* 用户注册实体
* 2022/5/26
*/
@Data
public class RegisterDto {
private String userName;//用户名
private String pwd;//密码
/**
* 注意生日是java.util.Date类型数据,想要实现参数String转Date要编写数据格式化类(Formatter)或者类型转换器(Convrter)
*/
private Date birthday;//生日
}
(3)注册jsp页面
<%--
Created by IntelliJ IDEA.
User: 高
Date: 2022/5/26
Time: 11:18
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<script type="text/javascript" src="${pageContext.request.contextPath}/static/js/jquery-3.6.0.min.js"></script>
注册页面
<script type="text/javascript">
//定义当点击保存时触发的方法
function toAddUser(){
//创建一个数据对象保存表单中的数据
var formData = {
//使用jQuery的方法获取表单元素的值
userName:$("#userName").val(),
pwd:$("#pwd").val(),
birthday:$("#birthday").val()
}
//输出结果观察
console.dir(formData);
//方法触发后执行ajax代码,提交数据到后端接口中
$.ajax({
url:"${pageContext.request.contextPath}/user/toAddUser",
method:"POST",//请求方法
async:false,// 异步参数值为true时:接口请求是异步执行的,为false是同步执行的
data:JSON.stringify(formData),//传递json字符串
contentType:"application/json",
dataType:"JSON",//数据传递的内容都是json(请求和响应)
success:function(data){//如果请求成功,执行success回调,data就是后端返回到前端的数据(一般就是json数据)
console.dir(data);
},
error:function(err){//如果请求失败,error回调,err是后端系统异常抛出的数据
console.dir(err);
}
});
}
</script>
2022-05-27
过滤器
依赖于servlet容器。在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。
使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数据,比如:在过滤器中修改字符编码;在过滤器中修改HttpServletRequest的一些参数,包括:过滤低俗文字、危险字符等
总之过滤器实际上就是对所有请求进行过滤操作,获取请求携带的数据或者修改请求的某些参数。
Spring-字符编码过滤器配置
characterEncodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
forceEncoding
true
characterEncodingFilter
/*
自定义过滤器
(1)创建一个自定义过滤器类,实现Filter接口
package com.huawei.sys.filter;
import javax.servlet.*;
import java.io.IOException;
/**
* 测试过滤器类
* 2022/5/27
*/
public class MyFilter implements Filter {
/**
* init 方法
* 过滤器初始化的回调方法
* 当容器初始化,过滤器也初始化,且只会初始化一次
* @param filterConfig
* @throws ServletException
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("MyFilter-初始化!");
}
/**
* doFilter 方法,拦截到请求后会执行的方法(每次请求一旦被拦截都会被调用)
* @param servletRequest 网络io请求流
* @param servletResponse 网络io响应流
* @param filterChain filterChain.doFilter();//让过滤器通过拦截,放行请求
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("过滤器被调用!");
filterChain.doFilter(servletRequest,servletResponse);//放行请求
}
/**
* destroy 过滤器销毁的回调
* 当容器销毁,过滤器就随之销毁
*/
@Override
public void destroy() {
System.out.println("过滤器-销毁!");
}
}
demo:拦截请求返回html代码
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("过滤器被调用!");
PrintWriter writer = servletResponse.getWriter();
servletResponse.setCharacterEncoding("UTF-8");
String html = "" +
"" +
"" +
"" +
"请求被过滤器阻止!";
writer.println(html);
//filterChain.doFilter(servletRequest,servletResponse);//放行请求
}
(2)在web.xml文件中配置过滤器
myFilter
com.huawei.sys.filter.MyFilter
myFilter
/user/*
SpringMVC拦截器
是基于Java的jdk动态代实现的,实现HandlerInterceptor接口。不依赖于servlet容器,拦截器针对于contraller方法,并且能获取到所有的类,对类里面所有的方法实现拦截,粒度更小,拦截器中>可以注入service,也可以调用业务逻辑。
自定义拦截器方法
(1)定义一个类实现HandlerInterceptor接口
package com.huawei.sys.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 自定义拦截器
* 2022/5/27
*/
public class MyInterceptor implements HandlerInterceptor {
/**
* 在controller方法调用之前回调
* @param request Http请求对象
* @param response Http响应对象
* @param handler 当前拦截器对象的实例
* @return 需要返回一个布尔值:
* true -》 拦截器放行
* false -》 拦截器阻止通行
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("1.在controller方法调用之前回调");
return true;
}
/**
* 在调用完成controller方法之后返回数据之前回调
* @param request Http请求对象
* @param response Http响应对象
* @param handler 当前拦截器对象的实例
* @param modelAndView 视图解析器需要接收的对象,可以定义要跳转的逻辑视图名以及包含要传送的数据
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("2.在调用完成controller方法之后返回数据之前回调");
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
/**
* 当整个controller方法执行完成,且视图或者数据成功返回后回调
* @param request Http请求对象
* @param response Http响应对象
* @param handler 当前拦截器对象的实例
* @param ex 整个方法结束执行后可能没有成功会抛出异常,返回的异常对象
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("3.当整个controller方法执行完成,且视图或者数据成功返回后回调");
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
(2)dispacther-servlet.xml配置文件中配置拦截器