Springboot笔记
Springboot结构理解
Controller层:
本层定义接口并调用service层接口方法完成业务逻辑。
功能:
接受前端请求,调用service,接受service返回的数据,之后响应给客户端。
Service层:
service层为业务服务,调用mapper层并提供给controller层使用,间接和数据库打交道。
项目结构包括两部分,接口文件和接口实现类文件,接口文件中定义在controller层中调用的service层方法;接口实现类文件中完成service层接口中定义的方法的实现。
注意:这里接口实现类中方法的实现是指业务逻辑的实现,可能有些方法并不能在实现类里完成真正意义上的实现,还需要在mapper层文件完成其真正意义上的实现(主要是和数据库交互)。
Mapper层:
mapper层为操作数据库的一层。
mapper层分为两部分,mapper接口层和mapper.xml层。
mapper接口层:
定义在service接口中没有完成真正实现,需要通过书写SQL语句才能完成其功能的方法。
mapper.xml层:
(1)配置通用查询映射结果:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.nayun.cultourism.mapper.CultureTourismSituationMapper"> <!-- 通用查询映射结果--> <resultMap id="cultureTourismResultMap" type="com.nayun.cultourism.entity.CultureTourismSituation"> <result column="id" property="id"/> <result column="name" property="name"/> <result column="annual_flow" property="annualFlow"/> <result column="position" property="position"/> <result column="illustration" property="illustration"/> <result column="pic_url" property="picUrl"/> <result column="creat_user" property="createUser"/> <result column="creat_dept" property="creatDept"/> <result column="creat_time" property="creatTime"/> <result column="update_user" property="updateUser"/> <result column="update_time" property="updateTime"/> <result column="status" property="status"/> <result column="is_deleted" property="isDeleted"/> <result column="address" property="address"/> </resultMap>
注意:
-
namespace 和 resultMap 的 type 要指向正确的地址,namespace指向mapper文件,type指向实体类。
-
column为数据库中的表字段,property为实体类中属性名(一一对应)。
关于column以及property命名:
- column为数据库表字段名,小写,各单词之间用下划线分割。
- property为实体类中属性名,命名一般符合驼峰形。
(2)完成mapper接口中方法的SQL语句实现:
在这个模块中就是书写具体的SQL语句了,将查询结果映射在方法中的resultMap中,id为在mapper接口中定义的方法名。
<!--查询所有景点数据--> <select id="findAll" resultMap="cultureTourismResultMap"> select * from cockpit_tourist_spots where is_deleted = 0 </select> <select id="getList" resultMap="cultureTourismResultMap"> select * from cockpit_tourist_spots where is_deleted = 0 <if test="cultureTourismSituation.name != null and cultureTourismSituation.name != ''"> and name LIKE CONCAT('%',#{cultureTourismSituation.name},'%') </if> </select>
Entity层:
也就是所谓的model,也称为pojo层,是数据库在项目中的类,该文件包含实体类的属性和对应属性的set、get方法。
实体类中属性同数据库表字段一一对应,对于相应的set、get方法一般不需要书写,实体类上引入@Data注解,会自动为实体类注入get、set以及toString方法,减少代码量。
VO层:
视图对象,用于展示层,把某个指定页面的所有数据封装起来,方便前端获取数据,后端将前端需要 的数据做整合,打包成一个类。
使用场景:
如果在前端页面需要展示经过某些数据库操作才能展示的特定数据,一般在vo层中把操作过程中涉及的数据进行封装,方便前端获取。并在controller层定义对应接口时把返回类型规定为vo类。
DTO层:
数据对象传输层,负责屏蔽后端实体层,将UI要的数据进行重新定义和封装。因为后端在实际业务场景中需要存储大量数据,而用户需要的数据只是一部分,为了快速获取用户需要的数据,应该把用户经常用到的数据在dto层中进行封装,在调用服务层时,只需要调用一次便可完成所有的逻辑操作。
运行流程:
- 控制层接收前端请求,调用对应的业务层接口方法
- 业务层实现类去实现业务层接口
- 业务层实现类的方法内调用数据层的接口
- 数据层实现文件(mapper.xml)实现数据层接口
- 然后处理结果层层返回
组合注解@Spring BootApplication 代替@EnableAutoConfiguration和@ComponentScan
@EnableAutoConfiguration @ComponentScan public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } } @Spring BootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
采用@RestController组合注解代替@Controller和@ResponseBody
@Controller public class BookController { @GetMapping("/book") @ResponseBody public Book book() { } } @RestController public class BookController { @GetMapping("/book") public Book book() { } }
基础配置
- Didiproperties.java
package com.didispace.chapter14; import lombok.Data; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; @Data @Configuration //@ConfigurationProperties(prefix= "con") public class DidiProperties { /** * 这是一个测试配置 */ @Value("${con.from}")// private String from; }
- application.yaml
con: from: demo
- HelloController.java
package com.didispace.chapter14; import lombok.Data; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @Data @RestController public class HelloController { @Autowired DidiProperties didiProperties; @RequestMapping("/hello") public String index() { return didiProperties.getFrom(); } }
maven中的parent、dependencyManager、dependency的用法和区别
一、parent一般使用场景:
比如有3个项目A、B和C,都要使用到某个相同的jar包,如果都单独引用,后期需要修改,不好维护,此时可以创建一个parent项目P,里面打包方式为pom,不需要编写任何代码,只需要管理jar包,在P项目中,引入公共的jar包,然后在A、B、C项目中,使用parent标签,引入P作为依赖,就可以使用P项目中所有引入的jar包了
二、dependencyManager使用场景:
比如有3个项目A、B和C,A项目使用a.jar,B项目使用b.jar,C 项目使用c.jar,此时用parent标签,会在ABC3个项目中,把3个jar包全部引入
该场景需要用dependencyManager标签,在P项目中,用dependencyManager来维护a,b,c3个jar包,并引入jar包的版本,ABC使用dependency来引入需要的jar包即可
form-data和x-www-form-urlencode区别
- form-data
就是http请求中的multipart/form-data,它会将表单的数据处理为一条消息,以标签为单元,用分隔符分开。既可以上传键值对,也可以上传文件。当上传的字段是文件时,会有Content-Type来表名文件类型;content-disposition,用来说明字段的一些信息;
由于有boundary隔离,所以multipart/form-data既可以上传文件,也可以上传键值对,它采用了键值对的方式,所以可以上传多个文件。
- x-www-form-urlencoded
就是application/x-www-from-urlencoded,会将表单内的数据转换为键值对,比如,name=java&age = 23
- multipart/form-data与x-www-form-urlencoded区别
multipart/form-data:既可以上传文件等二进制数据,也可以上传表单键值对,只是最后会转化为一条信息; x-www-form-urlencoded:只能上传键值对,并且键值对都是间隔分开的。
spring-servlet.multipart.max-file-size=10MB和spring-servlet.multipart.max-request-size=10MB区别
spring-servlet.multipart.max-file-size:代表单个文件最大大小
spring-servlet.multipart.max-request-size:代表单个请求所有文件最大大小
上传文件
@PostMapping("/uploadtest") private String uploadtest(MultipartFile file, HttpServletRequest request){ String name=file.getOriginalFilename(); //获取当前服务器运行路径,getRealpath为自定义路径,返回String类自定义路径 String path= request.getServletContext().getRealPath("/upload_resource/"); //创建file类实例用于测试对应路径文件是否存在 File dir=new File(path); if(!dir.exists()) dir.mkdir(); 创建file类实例 File final_file=new File(path+name); try { file.transferTo(final_file); } catch (IOException e) { throw new RuntimeException(e); } return path;
上传文件至项目文件地址:
@PostMapping("/uploadtest") private String uploadtest(MultipartFile file, HttpServletRequest request){ String name=file.getOriginalFilename(); //path="./xxx/"代表存放在当前目录下,path="/xxx/"代表存放在磁盘根目录下 String path="./upload_resourse/"; File dir=new File(path); if(!dir.exists()) dir.mkdir(); File final_file=new File(path+name); try { //参数为相对路径会自动匹配父路径,改为绝对路径方可 file.transferTo(final_file.getAbsoluteFile()); } catch (IOException e) { throw new RuntimeException(e); } }
Mybatis
-
配置
application.properties
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.url=jdbc:mysql://sh-cynosdbmysql-grp-ggs4362k.sql.tencentcdb.com:20105/Spring spring.datasource.username=root spring.datasource.password=aaa235112@ mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
-
Mapper注册
- Mapper注册
@Mapper //注解Mapper,springboot使用动态实现类自动实现接口中方法 public interface UserMapper { @Select("select * from user") public List<User> select(); }
- MapperScan注册
@SpringBootApplication @MapperScan("org.springdemo.mapper")//注册 进行扫描指定包路径 public class SpringdemoApplication { public static void main(String[] args) { SpringApplication.run(SpringdemoApplication.class, args); } }
- 实现
@RestController public class Usercontroller { //usermapper注入 @Autowired private UserMapper userMapper; @GetMapping("/user") private List<User> user(){ List<User> list=userMapper.select(); return list; } }
关于mybatis和mybatis-plus
- mybatis可以使用XML或者注解来配置和映射原生信息
- mybatis-plus在mybtis基础上做了增强,简化开发。实际以后期维护成本为代价换取前期貌似简便整洁的开发
- 建议:个人小型项目可用MP快速上手开发,大型项目及多表查询尽量使用MB
mybatis 多页查询
- User.java 实体类
package org.springdemo.entity; import java.util.List; @Data public class User { private int id; private String name; private int age; private String number; private List<Order> orders; }
- UserMapper.java 映射
package org.springdemo.mapper; import com.sun.org.glassfish.gmbal.IncludeSubclass; import org.apache.ibatis.annotations.*; import org.springdemo.entity.Order; import org.springdemo.entity.User; import org.springframework.web.bind.annotation.PathVariable; import java.util.List; @Mapper public interface UserMapper { //查询用户及对应的订单 @Select("select * from user") @Results({ @Result(column = "id",property = "id"), @Result(column = "name",property = "name"), @Result(column = "age",property = "age"), @Result(column = "number",property = "number"), @Result(column = "id",property ="orders",javaType = List.class,many = @Many(select = "org.springdemo.mapper.OrderMapper.selectByid")) }) public List<User> selectAllusersAndorders(); //提供查询订单及对应的用户接口 @Select("select * from user where id = #{id}") public User selectByid(@PathVariable int id); }
- Order.java 实体类
package org.springdemo.entity; @Data public class Order { private int id; private String name; private String price; private String remain; private User user; }
- OrderMapper.java 映射
package org.springdemo.mapper; import org.apache.ibatis.annotations.*; import org.springdemo.entity.Order; import org.springdemo.entity.User; import org.springframework.context.annotation.Bean; import org.springframework.web.bind.annotation.PathVariable; import java.util.List; @Mapper public interface OrderMapper { //查询订单及对应的用户 @Select("select * from `order`") @Results({ @Result(column = "id",property = "id"), @Result(column = "name",property = "name"), @Result(column = "price",property = "price"), @Result(column = "remain",property = "remain"), @Result(column = "id",property = "user",javaType = User.class,one = @One(select = "org.springdemo.mapper.UserMapper.selectByid")) }) public List<Order> selectAllorderAnduser(); //提供查询用户及对应的订单接口 @Select("select * from `order` where id = #{id}") public List<Order> selectByid(@PathVariable int id); }
- Controller.java 控制器
package org.springdemo.controller; import org.springdemo.entity.Order; import org.springdemo.entity.User; import org.springdemo.mapper.OrderMapper; import org.springdemo.mapper.UserMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController public class Usercontroller { //注入 @Autowired private UserMapper userMapper; @Autowired private OrderMapper orderMapper; @GetMapping("/findOrder") private List<Order> findOrder(){ return orderMapper.selectAllorderAnduser(); } @GetMapping("/findUser") private List<User> findUser(){ return userMapper.selectAllusersAndorders(); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!