从Andorid攻城狮转Java后端开发(2)

发布时间:2026/10/21 20:40:28

从Andorid攻城狮转Java后端开发(2) 前言SpringBoot的项目结构上一篇已经讲了如何创建一个SpringBoot项目。我们回忆一下它的项目结构resources文件夹中目录结构static保存所有的静态资源js ,css, imagetemplates:保存所有的模板页面。SpringBoot默认jar包使用嵌入式的tomcat,默认不支持JSP页面可以使用模板引擎freemarker,thymeleafapplication.yamlSpringBoot应用的配置文件可以修改一些默认值配置文件的值最终都是会绑定到某个类上这个类会在容器中创建对象.一、配置文件yaml的使用1组件的绑定理解这句话application.yaml——SpringBoot应用的配置文件可以修改一些默认值配置文件的值最终都是会绑定到某个类上这个类会在容器中创建对象.我们打开一个新项目application.yaml中会有这么一段配置可以看到这是配置ApplicationId属性的。如果我们想改端口号怎么做加入下面这段话到yaml文件中server: port: 8000当我们点击port进入到源码时可以看到这个属性也是赋值到了ServerProperties类中的port属性上。所以说配置文件的值最终都是会绑定到某个类上这个类会在容器中创建对象。2yaml语法学习1、单个的不可再分的值K: V2、对象键值对的集合。行内写法: K: {K1: v1,K2: v2,K3: v3} 或者 K: K1: v1 K2: v2 K3: v3需要注意yaml文件中大小写敏感的。3、数组一组按次序排列的值行内写法 k: [v1,v2,v3] 或者 k: - v1 - v2 - v3示例注意每个冒号后需要跟一个空格每一个“-”后面也需要跟着一个空格。3配置文件与类的绑定在SpringBoot中我们使用Component ConfigurationProperties注解的方式让配置文件yaml中的属性与类属性一一对应并赋值上去。ConfigurationProperties(prefix person) Component public class Person { private String name; private int age; private Boolean boss; private Date birthday; private String[] interests; private ListString animal; private MapString,Object score; private Pet pet; private SetDouble salarys; private MapString, ListPet pets; ... 下面是所有属性的get和set方法这就不写出来了 ... }Component ConfigurationProperties告诉springBoot将本类中的所有属性和配置文件中相关的配置进行绑定。prefix person指定使用yaml文件中的person属性来和本类进行绑定。1、ConfigurationProperties的两种联合使用ComponentConfigurationProperties只有这个组件是容器中的组件才能使用容器中提供的ConfigurationProperties功能。所以加上Component注解EnableConfigurationProperties ConfigurationProperties可以在注入Person类的目标类上写EnableConfigurationProperties(Person.class)这代表开启Person类的属性配置功能且把这个Person组件自动注册到容器中ConfigurationProperties报错编译不通过只写它是不行的因为没有把组件注册到容器中。Component与EnableConfigurationProperties都是来干把Person类注册到容器这件事的。2、yaml文件的代码提示在yaml文件中书写类中的属性时是没有代码提示的如果想要在配置文件中有对应类的属性代码提示可以加下面这个依赖即可。!--导入配置文件处理器配置文件进行绑定就会有提示-- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-configuration-processor/artifactId optionaltrue/optional /dependency !--打包成jar包时记得去掉这个只是方便我们开发的打包进去反而扩大了jar的体积-- build plugins plugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId configuration excludes exclude groupIdorg.springframework.boot/groupId artifactIdspring-boot-configuration-processor/artifactId /exclude /excludes /configuration /plugin /plugins /build4Value注解Value是注解在单个属性上的ConfigurationProperties是注解在类名上的运行后请求接口看输出Value与ConfigurationProperties的区别1、在功能上ConfigurationProperties是批量注入属性Value是一个个指定2、在语法上ConfigurationProperties支持松散语法绑定例如lastName与last-namelast_name代表一个意思大小写不敏感Value不行必须按照配置文件中的名字来写大小写敏感3、在表达式方面ConfigurationProperties不支持表达式Value是可以的#{11*2}可以支持表达式语言4、在JSR303数据校验上ConfigurationProperties支持Value不支持5、在复杂类型封装ConfigurationProperties支持Value不支持————例如获取配置文件中的maps值Value不支持第五点Value在书写代码提示里也可以看到他把所有的数组都是获取单个数据并不会返回整个数组对象。所以Value只适合基础数据类型的属性。ConfigurationProperties与Value的优先级ConfigurationProperties会覆盖Value的值但若配置文件中没有对应值那么Value赋的值就会得以保留所以不是ConfigurationProperties 全盘接管而是逐字段、有值才覆盖官方推荐使用ConfigurationProperties代替Value使用。但当我们只需要获取一个基础属性时可以直接使用Value。5Validated注解在JSR303数据校验上ConfigurationProperties支持Value不支持在使用JSR303数据校验时需要在pom.xml文件中导入以下依赖Spring Boot 2.3 以后校验依赖不再随 web 启动器一起带出来必须手动加pom.xml文件 !--JSR-303 / Jakarta Bean Validation 校验启动器Email、NotNull、Valid 等都靠它 注意Spring Boot 2.3 以后校验依赖不再随 web 启动器一起带出来必须手动加-- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-validation/artifactId /dependency Person.class文件 ConfigurationProperties(prefix person) Component Validated public class Person { Email private String name; private int age; private Boolean boss; private Date birthday; private String[] interests; private ListString animal; private MapString,Object score; private Pet pet; private SetDouble salarys; private MapString, ListPet pets; ... }运行服务器时就会报错因为name在application.yaml中是非邮箱形式所以报错如下Validated注解——它告诉 Spring「这个类/这个方法的参数请帮我跑 Bean Validation 校验」真正的一堆校验注解NotNull、Email 这些是被Validated这个开关触发。空值类Null/NotNull是否为 nullNotBlank非空且去空格后长度 0只用于字符串最常用NotEmpty非空且长度/个数 0String、Collection、Map、数组都能用长度/大小类Size(min, max)长度/元素个数区间String、集合、Map、数组Min(value)/Max(value)数值下限/上限int/long 等整数型不含 double/floatDecimalMin/DecimalMax同上但支持小数inclusive控制是否含边界数值正负类Hibernate Validator 提供的额外约束Positive/PositiveOrZero/Negative/NegativeOrZeroDigits(integer, fraction)整数位和小数位位数限制格式类Email邮箱格式可加regexp自定义Pattern(regexp ...)正则匹配手机号、身份证号都靠它URLHibernate 扩展日期类Past/PastOrPresent必须是过去/过去或今天Future/FutureOrPresent必须是未来布尔类AssertTrue/AssertFalse必须为 true/false比如是否同意协议1、Validated与Valid联合使用达到级联效果Valid是 Java 官方标准注解Validated是 Spring 自己造的。日常用Validated但嵌套对象校验必须靠ValidRestController Validated // ① 类上开启方法级校验RequestParam 上的约束归它管 public class HelloController { PostMapping(/users) // ② 参数上 Valid跑 User 内部 级联钻进 Address public String create( Valid RequestBody User user) { return ok; } GetMapping(/hello) // ③ 方法参数的约束靠类上的 Validated 触发 public String hello(NotBlank RequestParam String name) { return hi; } } public class User { NotBlank private String name; // 注意这里如果没标 Valid下面 Address 类内部的约束根本不会跑 Valid private Address address; } public class Address { NotBlank(message 城市必填) private String city; }标了Valid→ 校验User时会自动钻进address把Address.city的NotBlank也跑了。漏了Valid→User.name会校验但Address.city被跳过。Validated在类上→ 负责方法参数如RequestParam的校验Valid在RequestBody参数上→ 负责请求体对象 钻进它嵌套的子对象。2、进阶分组 级联一起上public interface Add {} // 新增场景 public interface Update {} // 修改场景 public class User { NotNull(groups Update.class) private Long id; NotBlank(groups Add.class) private String name; Valid // 级联 private Address address; } public class Address { NotBlank(groups Add.class) private String city; // 分组会传到这里 } PostMapping(/users) public String add(Validated(Add.class) Valid RequestBody User u) {...} // 会走Add组name city 都校验Validated(组)决定跑哪组规则Valid决定规则要不要往子对象里传。6PropertySource注解思考ConfigurationProperties是默认加载在application.yaml中写的配置信息。如果整个项目所有的配置信息都写在application.yaml中那么这个文件会非常的庞大。这就产生了一个需求生成多个配置文件每个配置文件管理不一样的配置信息。PropertySource加载指定的配置文件。当我们绑定的配置信息不在默认的application.yaml文件中则需要写这个注解来指定目标配置文件。注意PropertySource(value {classpath:person.properties})这里配置的文件是xxx.properties结尾的文件。如果新建的配置文件想要使用xxx.yaml那么这里会报错。PropertySource注解只适用于properties结尾的配置文件。自定义的yaml文件想要生效可以这样做application.yaml文件下 spring: application: name: moxiaoting01 config: import: - classpath:/my_config/person.yaml person.yaml文件下 Person: name: ssss boss: true birthday: 2019/12/09 age: 18 # interests: [篮球,足球] interests: - 篮球 - 足球 - 111 # animal: [狗狗,猫咪] animal: - 狗狗 - 猫咪 # score: {english: 80,math: 90} score: english: 80 math: 90 salarys: - 99.99 - 23.4 pet: name: 小李 weight: 99.99 pets: sick: - {name: 阿狗,weight: 30} - name: 阿猫 weight: 99.99 - name: 奥冲 weight: 77.77 health: - {name: 阿花,weight: 30} - {name: 阿1,weight: 30} Configuration ConfigurationProperties(prefix person) public class Person { private String name; private int age; private Boolean boss; private Date birthday; private String[] interests; private ListString animal; private MapString,Object score; private Pet pet; private SetDouble salarys; private MapString, ListPet pets; ... }自定义的yaml文件想要生效有2种方式在默认配置文件下导入其他配置文件路径在application.yaml里加一行spring.config.import: classpath:person.yamlSpring Boot 2.4 原生支持依旧使用PropertySource注解PropertySource 自定义 factory的方式也是可以的。yaml 文件必须显式指定 factory 。/** * 让 PropertySource 能够读取 .yaml / .yml 文件。 * * pPropertySource 默认使用的工厂是 * {link org.springframework.core.io.support.DefaultPropertySourceFactory} * 它内部走的是 {code ResourcePropertySource}只按 .properties 的语法逐行解析。 * 把一个 yaml 文件丢给它嵌套结构会全部塌平成一层 key * 也拿不到 {code person.name} 这样的前缀因此 ConfigurationProperties 一个字段都绑不上。 */ public class YamlPropertySourceFactory implements PropertySourceFactory { private static final YamlPropertySourceLoader LOADER new YamlPropertySourceLoader(); Override public PropertySource? createPropertySource(String name, EncodedResource resource) throws IOException { String sourceName (name ! null) ? name : resource.getResource().getFilename(); ListPropertySource? sources LOADER.load(sourceName, resource.getResource()); if (sources.isEmpty()) { return new PropertiesPropertySource(sourceName ! null ? sourceName : yaml, new Properties()); } return sources.get(0); } } PropertySource(value {classpath:/my_config/person.yaml}, factory YamlPropertySourceFactory.class) Configuration ConfigurationProperties(prefix person) public class Person { private String name; private int age; private Boolean boss; private Date birthday; private String[] interests; private ListString animal; private MapString,Object score; private Pet pet; private SetDouble salarys; private MapString, ListPet pets; ... }7配置文件占位符#配置文件占位符 #可以在配置文件中引用前面配置过的属性优先级前面配置过的这里都能用 # ${app.name:默认值}来指定找不到属性时的默认值注意冒号前后不能有空格 # ${random.value}、${random.int}、${random.long}、${random.int(10)}配置文件中可以使用随机数 Person: boss: true birthday: 2019/12/09 age: ${random.int} interests: - ${person.name:xiaoting} 结果 Person{namenull, age-2135055719, bosstrue, birthdayMon Dec 09 00:00:00 CST 2019, interests[xiaoting], animalnull, scorenull, petnull, salarysnull, petsnull}8Lombok的使用这是一个简化JavaBean的工具。第一步工程里导入依赖dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId version1.18.46/version /dependency第二步安装Lombok插件并重启IDEA第三步使用注意只提供了全参与无参构造器方法如果需要非全参构造器就跟以前一样自己代码写就好了。二、SpringBoot的常用注解(1).主项目的自动配置原理SpringBootApplication 三注解合成SpringBootApplication SpringBootConfiguration EnableAutoConfiguration ComponentScanSpringBootApplication其实就是这三个注解的合成。1、SpringBootConfiguration这个是用来表示这个类是Springboot的配置类即可以理解为以前的配置文件2、EnableAutoConfiguration1、AutoConfigurationPackage 将本项目的主配置类被SpringBootApplication标记的类的所在包以及下面所有子包里面的所有组件扫描到spring容器中。如果想改动扫描路径SpringBootApplicationscanBasePackages org.example或者ComponentScan(org.example)指定扫描路径2、Import(AutoConfigurationImportSelector.class)会给容器中导入非常多的自动配置类xxxxAutoConfiguration就是给容器中导入这个场景所需要的全部组件并配置好这些组件。3、ComponentScan包扫描注解只要标注了Controller、service、Repository、component都会自动扫描是一个可以在同一个类上多次重复用的标注。ComponentScan(value org.example, includeFilters { ComponentScan.Filter(type FilterType.ANNOTATION, classes {Controller.class, Service.class}), ComponentScan.Filter(type FilterType.CUSTOM, classes {MyTypeFilter.class}) },useDefaultFilters false)value指定扫描的路径是包名为org.example下的所有包以及其子包。includeFilters指定扫描的时候只需要包含哪些组件。需要注意要让includeFilters生效需要禁用默认的配置规则————userDefaultFiltersfalseComponentScan(value org.example, excludeFilters { ComponentScan.Filter(type FilterType.ANNOTATION, classes {Controller.class, Service.class}), })excludeFilters指定扫描的时候按照什么规则排除那些组件如上是指定排除Controller标注的组件。type的值有FilterType.ANNOTATION 注解FilterType.ASSIGNABLE_TYPE 类FilterType.ASPECTJ 按ASPECTJ表达式FilterType.REGEX 按正则表达式FilterType.CUSTOM 使用自定义规则必须是TypeFilter的实现类public class MyTypeFilter implements TypeFilter { /** * 每扫描到一个组件都会走这个方法去判断是否符合匹配条件若符合则加入容器不符合则过滤掉 * 匹配成功返回true即加入容器中失败返回false即过滤掉 * * param metadataReader 读取到的当前正在扫描的类的信息 * 注意这是指当前正在扫描的类而不是当前是它注解的类这是一个自定义规则而非自定义注解它不可以当成一个注解用 * * param metadataReaderFactory 可以获取到其他任何类的信息 */ Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { //获取当前类注解的信息 AnnotationMetadata annotationMetadata metadataReader.getAnnotationMetadata(); //获取当前正在扫描的类的类信息 ClassMetadata classMetadata metadataReader.getClassMetadata(); //获取当前类资源类的路径 Resource resource metadataReader.getResource(); return false; } } 使用如下 ComponentScan(value org.example, includeFilters { ComponentScan.Filter(type FilterType.CUSTOM, classes {MyTypeFilter.class}) },useDefaultFilters false)(2).给容器中加入组件的相关注解1、ImportResourceConfiguration导入Spring的配置文件指xml文件让配置文件里面的内容生效。当第三方框架或者很老的项目就是使用的xml定义的组件我们一个一个转成注解形式太麻烦不转springBoot不认识。则可以使用该注解去申明目标xml让目标xml中的所有组件都注入到容器中。注意该注解需要写在配置类上即Configuration上。新建bean.xml代码如下 ?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beans xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd bean iduser01 classcom.example.moxiaoting01.User/bean /beans 新建一个user类代码如下 public class User { private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age age; } } 在HelloController类中自动注入user自动注入的前提是user得是一个组件 RestController public class HelloController { Autowired User user;发现编译器爆红指向user RequestMapping(/person) public String person() { return ; } }也就是说spring的xml文件方式注入组件在springboot中是无法识别的。那一些老项目xml配置文件中的组件很多很多拆解很麻烦ImportResource注解就能解决这个麻烦。在随便一个配置类上写SpringBootApplication ImportResource(value {classpath:bean.xml}) //写上这句话以后就不会爆红了user就是组件了 public class Moxiaoting01Application { public static void main(String[] args) { SpringApplication.run(Moxiaoting01Application.class, args); } }2、Configuration Bean在springBoot中创建一个组件已经不用xml方式了。使用的是Configuration Bean的方式。A1、Configuration告诉SpringBoot这是一个配置类 以前的.xml配置文件要注意的是配置类也是一个组件。Target(ElementType.TYPE) Retention(RetentionPolicy.RUNTIME) Documented Component public interface Configuration {...}需要关注的是Configuration注解里有一个属性proxyBeanMethods在springBoot2.0以上配置类有一个默认属性proxyBeanMethods它默认是trueproxyBeanMethods代理bean的方法Full(proxyBeanMethods true 全量级模式Lite(proxyBeanMethods false 轻量级模式配置类可以使用Bean标注在方法上给容器注册组件默认注册的组件是单实例的就是因为属性proxyBeanMethods它默认是true也就是全量级模式。如果改为false那么注册的组件就不是单例的这就是轻量级模式。User类 public class User { private String name; private Integer age; public User(String name, Integer age) { this.name name; this.age age; } public String getName() { return name; } public void setName(String name) { this.name name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age age; } } MyComponent类 Configuration(proxyBeanMethods false) public class MyComponent { Bean public User user01(){ User user new User(zhangshan , 18); return user; } } 项目启动类 SpringBootApplication public class Moxiaoting01Application { public static void main(String[] args) { //将SpringBoot的应用启动起来 //这里返回的是IOC容器 ConfigurableApplicationContext run SpringApplication.run(Moxiaoting01Application.class, args); /** * Configuration(proxyBeanMethodstrue)时获取到的是代理对象调用方法springBoot总会检查这个组件是否在容器中有有就不会创建保持组件单实例 * Configuration(proxyBeanMethodsfalse)时获取到的就不是代理对象那么通过这个对象调用方法时就是直接走方法而非去容器中拿组件。 */ MyComponent lookComponent run.getBean(MyComponent.class); User user1 lookComponent.user01(); User user02 lookComponent.user01(); System.out.println(组件 (user1 user02)); } }proxyBeanMethodsfalse有一个好处就是SpringBoot会跳过检查容器中是否含有该实例所以加载就会更快一些。那么推荐当我们只是单纯的定义一个组件别人并不会用到它——我的理解就是这个组件可以不是单例可以多个实例那么我们可以设置为false提高项目性能A2、Configuration BeanConfiguration public class MyComponent { Bean public User user01(){ User user new User(zhangshan , 18); return user; } }上面这段代码的含义将方法的返回值添加到容器中。以方法名作为这个组件的id/名字。方法返回的值就是组件在容器中的实例。默认情况下外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象。Configuration public class MyComponent { Bean public User user01(){ User user new User(zhangshan , 18); return user; } Bean(tom) //组件名就不是方法名了就叫tom了 public User user02(){ return new User(moxiaoting , 20); } }使用Bean(tom)能修改组件的名字。介绍以下相关组件的查询方法SpringBootApplication public class Moxiaoting01Application { public static void main(String[] args) { //将SpringBoot的应用启动起来 //这里返回的是IOC容器 ConfigurableApplicationContext run SpringApplication.run(Moxiaoting01Application.class, args); //查看容器里面的所有组件 String[] name run.getBeanDefinitionNames(); for (String name1 : name) { System.out.println(name1); } //从容器中获取对应组件名字叫user01,类形式User.class的 User user run.getBean(user01, User.class); User user01 run.getBean(user01, User.class); System.out.println(组件 (user user01)); //搜索指定类User.class的所有组件 String[] beanNamesForType run.getBeanNamesForType(User.class); for (String beanName : beanNamesForType) { System.out.println(beanName); } //用来判断容器中是否含有name叫user01的组件 返回true就是有false就是没有 boolean user0 run.containsBean(user01); System.out.println(user0); } }3、Conditional条件装配条件装配满足Conditional指定的条件则进行组件注入。它有很派生注解常用的ConditionalOnBean/ConditionalOnClass——当容器中存在指定Bean/class时则干xxx事情ConditionalMissingBean/ConditionalMissingClass——当容器中不存在指定Bean/class时则干xxx事情ConditionalOnResource——当容器中存在指定资源时则干xxx事情ConditionalOnJava——当容器中存在指定java版本号时则干xxx事情ConditionalOnWebApplication——当我们的应用是一个web应用时则干xxx事情ConditionalOnNotWebApplication——当我们的应用不是一个web应用时则干xxx事情Configuration public class LookComponent { //只有当容器中包含有pet01组件才把user01组件注入容器 ConditionalOnBean(name pet01) Bean public User user01(){ User user new User(zhangshan , 18); user.setPet(pet01()); return user; } Bean public Pet pet01(){ return new Pet(cat); } }ConditionalOnBean这个可以作用于一个方法则只对这一个方法有条件注入。若写在类名处即配置类上则对该配置类下的所有方法都有这个条件注入。重点注意上面这段代码看似是没有问题但是运行后你会发现依旧没有user01组件。因为ConditionalOnBean 对 Bean 方法的声明顺序敏感评估 user01 时 pet01 还不存在条件不满足于是 user01 被跳过。你把 pet01() 挪到 user01() 前面就能解决。4、Import注解Import({User.class , DefaultShutdownHook.class}) Configuration(proxyBeanMethods true) public class LookComponent {...}给容器中自动创建出这两个类型的组件调用对应类的无参构造器创建组件名字为全类名。这个适用于我们给第三方sdk中的某个类注册为组件因为第三方sdk中的类有些我们可能无法手动new其对象出来。注意Import注解必须写在某个组件上随便找个组件的类上就可以。(3).RestController注解RestController Controller ResponseBodyController表现层 / Web 层是接收 HTTP 请求、路由、返回响应。Spring MVC 会专门扫描它把里面的RequestMapping注册成路由。ResponseBody标注在类名上则代表整个类下的所有方法返回值都直接写给客户端如果是对象则直接返回json串若标注在方法名上则代表该方法返回值都直接写给客户端如果是对象则直接返回json串。A1、Component、Controller、Service、Repository的理解注解属于哪一层干什么有什么特殊待遇Component通用哪层都能用最基础的组件给任意类贴无特殊处理就是注册进容器Controller表现层 / Web 层接收 HTTP 请求、路由、返回响应Spring MVC 会专门扫描它把里面的RequestMapping注册成路由Service业务层写业务逻辑判断、计算、组装纯语义标签——功能上和Component一模一样Repository数据访问层跟数据库打交道增删改查把数据库抛的原始异常自动翻译成 Spring 的统一异常DataAccessException换数据库时上层代码不用改它们四个本质是同一个东西Spring 组件/Bean只是贴了不同角色标签。Controller、Service、Repository三个注解的源码里都包着Component。// ① Repository只管数据存取就是你 demo 里那个 users 列表下一步换成 MySQL Repository public class UserRepository { private final ListUser users new ArrayList(); // 模拟数据库 public User findById(String id) { return users.stream() .filter(u - id.equals(u.id)) .findFirst().orElse(null); } } // ② Service只管业务逻辑判断能不能查、查完要补什么 Service public class UserService { Autowired private UserRepository userRepository; // Spring 自动注入 public User getById(String id) { if (id null || id.trim().isEmpty()) { // ← 业务规则在这层 throw new IllegalArgumentException(id 不能为空); } return userRepository.findById(id); // 不自己查库交给 Repository } } // ③ RestController只管收发请求 RestController public class UserController { Autowired private UserService userService; GetMapping(/user/{id}) public User getUser(PathVariable String id) { return userService.getById(id); // 返回值自动转 JSON不用再 String.format 了 } }这就是项目中的三层架构。稍大点的项目都这么分的表现层、业务层、数据访问层。这里需要和spring MVC的概念区分一下。MVC 模式三层架构管多大范围只管表现层这一层管整个应用角色/分层Model、View、Controller表现层、业务层、数据访问层解决什么问题请求进来后怎么组织、数据怎么展示代码按职责分工方便维护和替换对应注解只有Controller它就是 CControllerServiceRepository什么时候需要做 Web 页面/接口才需要稍大点的项目都这么分Service和Repository压根不在 MVC 里——MVC 是个表现层内部的设计模式管不到业务层和数据层去。补充Spring MVC 里 M 和 V 具体是啥CController​ Controller/RestController—— 你写UserController的那个MModel​ 要交给视图去渲染的数据。用RestController时M就是你的返回值对象比如UserVView​ 视图。老式是 JSP/Thymeleaf 页面返回 JSON 时V退化成 Jackson 的序列化就是你 A3 卡里那句原生得手拼 JSON被框架接管的地方A2、GetMapping、PostMapping、 PutMapping、DeleteMapping注解GetMapping(/hello) 就是 RequestMapping(value /hello , method RequestMethod.GET)PostMapping、 PutMapping、DeleteMapping和GetMapping是一样的。都是RequestMapping(value xxxx , method RequestMethod.xxx)RestController public class HelloController { RequestMapping(/person) public String person() { return aaaa; } GetMapping(/hello) public String hello() { return hello; } }A3、 PathVariable获取接口的路径变量值A4、RequestHeader获取接口请求头参数A5、RequestParam 获取接口的请求参数写在url?后面的参数注意接口的地址不需要写明参数GetMapping(xxxx/xxxx/xxx) 就可以了不需要写成 GetMapping(xxxx/xxxx/xxx?参数1{变量}参数2{变量})A6、PostMapping 获取接口的请求体这个只有post方法才有请求体请求体可以是一个表单结果也可以是json串。取决于content-type的值A7、CookieValue 获取接口的Cookie参数
延伸阅读

更多相关文章

2026/10/21 20:40:28

SatDump 快速入门:如何接住你的第一颗气象卫星

SatDump 快速入门:如何接住你的第一颗气象卫星 【免费下载链接】SatDump A generic satellite data processing software. 项目地址: https://gitcode.com/GitHub_Trending/sa/SatDump SatDump 是一款开源的卫星信号解码软件,能把卫星发来的无线电…

2026/10/21 21:56:00

用数据化方法管理个人技能:从量化模型到轻量级系统搭建

「skills」,就一个孤零零的英文单词,连副标题都没有。我第一次拿到这个项目名的时候,第一反应是:这八成又是一个想做个人技能管理、却不知道从哪下手的实战项目。把它翻译成需求,其实就是一句话——把一个人脑子里乱七…

2026/10/21 21:56:00

技能盘点与拆解:构建个人技能树的项目式学习指南

1. 技能盘点:先搞清自己手里到底有什么牌 1.1 为什么大多数人的技能清单是废的 我做技术这些年,面试过不少人,也带过不少新人。每次问“你会什么”,得到的回答基本是“我会Python”“我熟悉Linux”“我懂点前端”。这种回答我一听…

2026/10/21 21:56:00

场景级伪造检测:BR-Gen数据集与NFA-ViT网络实战解析

说实话,我第一次看到“BR-Gen数据集NFA-ViT”这个组合时,第一反应是:又来了一个刷数据的方案。但仔细往里看,这个工作要解决的根本不是“某个榜单上再涨零点几个点”的事,而是整个深度伪造检测领域一直没趟过去的坎——…

2026/10/21 21:56:00

C语言标准库源码深度解析:从printf到malloc的实现与二次开发

简介:这份C语言标准库源代码压缩包面向希望深入理解C语言底层实现的学习者与开发者,尤其适合已掌握基础语法、想进一步探究标准库内部机制的中级程序员。包内共1267个文件,以559个.c源文件、412个.obj目标文件、85个.h头文件为主,…

2026/10/21 21:56:00

lingbot-map:面向语义对齐的轻量级跨语言映射范式

1. “lingbot-map”不是某个现成工具,而是一类需求的命名共识最近在几个技术社区和跨领域协作群里,频繁看到“lingbot-map”这个组合词被提及。它不像“React”或“TensorFlow”那样有明确的官网、文档或GitHub仓库,也不指向某家公司的产品。…

2026/10/21 21:50:57

基于深度学习YOLOv8的智能车牌识别系统设计与实现

车牌识别这个题目,几乎每年都是计算机视觉方向毕设的热门选项。我做这个《基于深度学习YOLOv8的智能车牌识别系统设计》项目时,踩过的坑和最终跑通的方案,应该能帮不少正在纠结选题和实现的同学少走弯路。这套项目包含了完整的设计源文件、万…

2026/10/21 4:53:08

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

2026/10/21 0:00:35

交通流仿真实战:IDM跟驰与MOBIL换道模型参数调优与避坑指南

简介:这份资源是面向交通工程学习者与Python开发者的微观交通流仿真项目,核心实现智能驾驶模型(IDM)下的车辆跟驰与换道行为,可用于理解速度、密度与流量之间的动态关系,适合具备Python基础、希望深入交通模…

2026/10/21 0:00:35

揭穿智能体表面顺从:用追踪代码重建任务执行确定性

1. 表面顺从不是智能体的“礼貌”,而是任务执行链路上的隐性断点最近在调试一个跨平台长周期任务调度系统时,我反复遇到一种令人困惑的现象:智能体在用户指令发出后,几乎秒级响应“已收到”“正在处理”“请稍候”,UI上…

2026/10/21 0:00:35

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

这段时间硬件圈和AI圈都在传一个事:AMD锐龙AI Max PRO 400系列把最高192GB统一内存搬进了PC形态的产品里,按宣传口径,本地跑320B参数的大家伙不再是纸面概念。我第一反应倒不是“内存真大”,而是这话背后的含金量——它把过去只能…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑