创建SpringBoot项目工程
idea中新建项目,选择springboot,类型选择 maven , 依赖项选择web/spring web
项目目录结构和maven的差别:
resources文件中多了 applecation.properties Spring boot配置文件
测试
在 com.zpero文件中创建 controller软件包,添加HelloTest文件
@RestController
public class HelloController {
@RequestMapping("/hello")
public String Hello(){
System.out.println("hello world");
return "hello world";
}
}
由于创建的web app , 在浏览器中 打开 localhost:8080/hello
如果8080打不开,那么看看是不是没有把启动文件放在父级包下:
如图,启动文件应该在controller的父级包下,而不是同级包或子包
端口号看tomcat容器给的端口
@RestController
spring boot 用于创建RESTful Web服务, 标记当前类是一个控制器 , 并且所有方法返回的对象会自动化序列为JSON 或 xML , 直接作为 HTTP响应体返回
@RequestMapping
Spring框架最基础最常用的注解之一 , 将HTTP请求映射到某个控制器后方法上 , 定义了前端请求的"入口地址"
@RequestParam注解
- 方法形参名称与请求参数名称不匹配,通过注解完成映射
- 该注解的required属性默认是true,代表请求参数必须传递
HTTP请求基本知识见 JavaWeb考试知识点速通
请求响应
前端请求传参
//HttpServletRequest 原始方法
@RequestMapping("/simpleParam")
public String simpleParam(HttpServletRequest request) {
String name = request.getParameter("name");
String ageStr = request.getParameter("age");
int age = Integer.parseInt(ageStr);
System.out.println(name + " " + age);
return "ok" ;
}
// @RequestParam 注解映射
@RequestMapping("/simpleParam1")
public String simpleParam(@RequestParam(name = "name" , required = false) String usrname , Integer age){
System.out.println(usrname + " " + age);
return "get";
}
使用HttpServletRequest
使用原始 Servlet API获取参数
需要手动处理参数的转换
age 参数如果缺失会抛出 NumberFormatException错误
java.lang.NumberFormatException: Cannot parse null string] with root cause使用Spring注解
@RequestParam(name = "name" , required = false)指定前端参数名必须为 "name" , 把name绑定到 usernamerequired 参数决定参数是否必须 , 如果为true 时没有传入 name , 则会抛出错误
MissingServletRequestParameterExceptionSpring 会自动进行类型转换 , 将 String (text) 类型的传入参数 age 转换为 Integer
传递嵌套实体参数
@RequestMapping("/getUserPojo")
public String simplePojo(@ModelAttribute User user){
System.out.println(user);
return "get user "+ user.toString();
}
//pojo文件夹中
public class Account {
private String id;
private String price;
}
//添加getter setter tostring
public class User {
private String name;
private int age;
private Account ac;
}
postman信息:
类名.属性 给嵌套pojo属性传递参数
请求参数名和形参对象的属性名相同,按照对象层次结构关系既可以接收嵌套Pojo属性参数
@ModelAttribute 注解
将请求中的参数自动封装到一个 pojo 对象中 , 并将该对象添加到Spring 的Model中
可以不写 , 但是方便后期视图
传入数组
@RequestMapping("/arrayParam")
public String arrayParam(String[] form){
System.out.println(Arrays.toString(form));
return "form data received " ;
}
@RequestMapping("listParam")
public String listParam(@RequestParam List<String> form){
System.out.println(form);
return "received list of form";
}
把发送的参数传入 form 数组中
传入日期
@RequestMapping("dateParam")
public String dateParam(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")LocalDateTime date){
System.out.println(date);
return "date = " + date;
}

传入Json参数
@RequestMapping("jsonParam")
public String JsonParam(@RequestBody User user){
System.out.println(user);
return "Josn" + user ;
}
{
"name" : "张三",
"age" : 22,
"ac" : {
"id" : "漆黑烈焰使" ,
"price" : 8888
}
}
json数据键名应该与形参对象的属性名相同, 需要@RequestBody标识 ,不然无法传入数据
路径参数
@RequestMapping("/simpleParam2/{id}")
public String simpleParam(@PathVariable String id){
return "userid" + id;
}
响应请求
统一响应结果
//创建pojo/Result.java
public class Result {
private Integer code;
private String msg;
private Object data;
}
//添加getter setter 构造器
//创建ResponseController.java
@RestController
public class ResponseController {
@RequestMapping("/RespUserPojo")
public Result simplePojo(@ModelAttribute User user){
System.out.println(user);
return new Result(1,"success",user);
}
}
localhost:8080/RespUserPojo?name=dfdfdfdfdfsssd&age=22&ac.id=dfdfdfdfdfdfdf&ac.price=1222
案例
//添加文件
resources
├── static
│ ├── element-ui
│ ├── js
│ └── emp.html
├── templates
├── application.properties
└── emp.xml
com
└── zpero
├── controller
│ ├── EmpController
│ ├── HelloController
│ ├── RequestController
│ └── ResponseController
├── dao
│ ├── EmpDao
│ └── impl
│ └── EmpDaoImpl
├── pojo
│ ├── Account
│ ├── Emp
│ ├── Result
│ └── User
├── service
│ ├── EmpService
│ └── impl
│ └── EmpServiceImpl
└── Utils
└── XmlParserUtils
链接: JavaWeb 提取码: 4ati
添加接口和实现类
public class EmpDaoImpl implements EmpDao {
@Override
@RequestMapping("/listEmp")
public List<Emp> list() {
String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
System.out.println(file);
List<Emp> empsList = XmlParserUtils.parse(file, Emp.class);
return empsList;
}
}
public class EmpServiceImpl implements EmpService {
private EmpDao dao = new EmpDaoImpl();
@Override
public List<Emp> listEmp() {
List<Emp> empsList = dao.list();
empsList.stream().forEach(
emp -> {
String gender = emp.getGender();
if("1".equals(gender)){
emp.setGender("男");
}else if("2".equals(gender)){
emp.setGender("女");
}
String job = emp.getJob();
if("1".equals(job)){
emp.setJob("讲师");
}else if("2".equals(job)){
emp.setJob("班主任");
}
else if("3".equals(job)){
emp.setJob("就业指导");
}
});
return empsList;
}
}
@RestController
public class EmpController {
private EmpService empService = new EmpServiceImpl();
@RequestMapping("/listEmp")
public Result list(){
List<Emp> empsList = empService.listEmp();
return Result.success(empsList);
}
}
分层解耦设计方式
分层
三层架构
Controller : 控制层, 接收前端发送的请求,对请求进行处理 ,并且响应数据
Service : 业务逻辑层 , 处理具体的业务逻辑
Dao : 数据访问层 , 负责数据访问操作 , 包括数据的增删改查
案例中,EmpDao封装了获取文件的数据访问逻辑, EmpService封装了对获取到的数据的处理逻辑, EmpController封装了EmpService 并将处理后的数据 统一化 成Result , 是起点也是终点
解耦
什么是耦合?
耦合指的是系统的模块之间的依赖关系
以上述案例为例, Controller层 保存了Service 层的对象 , 并且new了一个实现方式EmpServiceImpl , 如果把这个new出来的对象换成另一个,那么Controller层的代码需要改动,也就是说Controller 和 Service还有 耦合
控制反转(IOC)
对象的创建控制权由程序自身转移到外部容器
依赖注入
Spring 会自动查找容器中类型匹配的 Bean并注入
Bean对象
IOC容器中创建,管理的对象成为Bean
@Component
将当前类交给IOC容器管理,并成为IOC的Bean
衍生注解
- @Controller
- @Service
- @Repository(Dao层)
用法
- @注解("Bean名字") , 默认是类名首字母小写
- 除了控制器必须要用@Controller ,其他的既可以用同层次的注解,也可以用@Component
@Autowired
IOC 自动将匹配的bean注入到当前类中需要的地方
- ***默认按类型匹配(byType):***如果有多个相同类型的 Bean,可能会报错。
- 可以使用@Primary 注解到需要的类
- 可以搭配
@Qualifier指定注入的 Bean 名称
@Qualifier("EmpDaoImpl")- 可选注入:
- 使用
required = false,表示没有也不报错
bean组件扫描
Spring 启动时会扫描带有
@Component,@Service,@Repository等注解的类,并将它们注册为 Bean。默认扫描范围是启动类所在的包及其子包
案例而言, 启动类SpringWebQucikstartApplication 在com.zpero中,扫描范围就是com.zpero所有的文件
但是当文件被移动后(从zpero中移入了com),脱离了扫描范围,再像要被管理就要 重新定义扫描范围
@@ComponentScan({ "com.dao" , "com.zpero" })