Spring基础——使用注解开发SpringMVC

目录

  • 配置SpringMVC的初始化信息
    • 配置ServletWebApplicationContext
    • 配置RootWebApplicationContext
    • 配置ServletContext
  • 创建Controller控制器
    • 配置Controller响应路径
    • 接收用户传递参数
      • 接收JSON数据
      • 接收简单类型
        • 对象封装参数
      • 接收数组类型
  • Restful

文章源码仓库:Spring Learn Repo

配置SpringMVC的初始化信息

  • 之前说过,SpringMVC中使用两个WebApplicationContext:ServletWebApplicationContext和RootWebApplicationContext对Web上下文环境进行分层管理。
    • ServletWebApplicationContext:用于管理Servlet相关的Bean,如控制器,视图解析器等,每个Servlet(通常是DispatcherServlet)都有自己的ServletWebApplicationContext;并且Scope与Servlet相对应
    • RootWebApplicationContext:是整个Web应用的上下文,用于管理应用程序级别的Bean,如Service,Repositories等,RootWebApplicationContext可以被多个Servlet共享,且Scope与整个Web应用相同。
      SpringMVC

配置ServletWebApplicationContext

  • 上文提到过每个DispatcherServlet都有一个ServletWebApplicationContext用于存储Servlet的相关Bean,因此我们需要扫描Controller注解标记的Bean
  • @EnableWebMvc:值得注意的是,这里还需要Spring MVC开启基于注解的基础功能以及一些默认配置。
    • 通过此注解SpringMVC会自动注册包括DefaultAnnotationHandlerMapping,AnnotationMethodHandlerAdapter等用于处理注解映射和处理方法的适配器。
    • 并且允许在Controller标记类的类和方法上使用@RequestMapping,@RequestParam等HTTP请求与响应方面的注解驱动如果你发现RequestParam没法使用的话可以查看是否开启了此注解
    • 而且此注解还提供了一些常见的用于处理请求参数的类型转换,如字符串转数字,json格式之间的转换等
@Configuration
@ComponentScan({"com.nobugnolife.controller"})
@EnableWebMvc
public class SpringMvcConfig {
}

配置RootWebApplicationContext

  • 上文说过RootWebApplicationContext里面是Web用于管理应用程序级别的Bean,如Service,Repositories等,而我们这里只是演示SpringMVC的功能,所以就不配置持久层了
@Configuration
@ComponentScan({"com.nobugnolife.service"})
public class SpringConfig {
}

配置ServletContext

  • Spring提供了WebApplicationInitializer接口可以让我们注册并初始化DispatcherServlet
public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) {

        // 加载ServletWebApplicationContext配置信息
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        // 注册SpringMVC的配置类
        context.register(SpringMvcConfig.class);

        // 创建并注册DispatcherServlet
        DispatcherServlet servlet = new DispatcherServlet(context);
        ServletRegistration.Dynamic registration = servletContext.addServlet("app", servlet);
        registration.setLoadOnStartup(1);
        registration.addMapping("/");
    }
}
  • 官方文档里提供了一个简化的创建方案通过继承 AbstractAnnotationConfigDispatcherServletInitializer 并覆写特定的方法,用以简化配置开发
public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    /*
    * 过滤器
    * */
}

创建Controller控制器

  • 在控制层Controller中我们需要运用到如下这些注解:
    • @Controller:Controller Bean注解,用于标记controller中的类
    • @RequestMapping:在之前的文章中说过SpringMVC对用户发出的请求会有HandlerMapping解析路由选择对应处理器进行处理,因此我们在创建处理器Controller的时候也需要提供处理器对应的URL路径,通过 @RequestMapping,如果不提供默认为当前上下文的根路径
      • @PostMapping:@RequestMapping(value=“”, method = ReuqestMethod.POST)简化写法
      • @PutMapping:@RequestMapping(value=“”, method = ReuqestMethod.PUT)简化写法
      • @DeleteMapping:@RequestMapping(value=“”, method = ReuqestMethod.DELETE)简化写法
      • @GetMapping:@RequestMapping(value=“”, method = ReuqestMethod.GET)简化写法
    • @RequestParam:通过路径传参,允许接受用户从URL路径中传入的参数,并写入到形参中如:https://www.baidu.com/search?context=csdn,那么这里传入了个参数名为context,内容为csdn的信息,并且在SpringMVC中会自动转化成形参类型
    • @RequestBody:通过请求体传参,允许接受用户将信息写入请求体中,可以避免直接从URL中暴露参数信息,但一般接收的时候会通过post方式进行接收
    • @PathVariable:URL模板变量,属于简化了URL路径传参的方式,允许用户通过URL路径解析的格式将参数动态传入,但需要指明传入参数的位置如:https://www.baidu.com/search/{context},这里用户传入参数只需要在search/csdn,SpringMVC会自动将{context}路径对应的csdn解析到context参数中
    • @ResponseBody:将返回数据直接作为响应参数进行返回,之前文章说过,在SpringMVC中,DispatcherServlet会将我们最终处理完的数据注入到视图模型中并返回给用户,因此正常来说Controller的返回数据会被当成URL路径解析,而如果我们不想返回视图,只想返回我们的处理数据的话则需要用到这个注解
    • @RestController:将@ResponseBody与@Controller进行合并,用于简化开发代码

配置Controller响应路径

  • 通过@RequestMapping配置URL的解析路径(从SpringMCV的ServletContext配置的根路径开始解析),@RequestMapping可以作用到类上(作用到类上代表当前Controller类中所有的方法都会通过此路径),也可以作用到方法上(方法上的路径会自动配置到类的路径后边)
  • 比如这里我们配置一个WebController,通过访问/index/hello资源路径让服务器返回跳转到index.jsp
@Controller
@RequestMapping("/index")
public class WebController {

    /*
    * 如果没有添加RequestBody则会把返回字符串当成路径访问服务器文件
    * */
    @RequestMapping("/hello")
    public String toIndex(){
        System.out.println("跳转到index.jsp");
        return "index.jsp";
    }
}

接收用户传递参数

接收JSON数据

  • JSON是一种轻量级的数据交换格式,基于JavaScript语法的子集,但如今是可独立于JavaScript使用,通常用于Web应用程序中的数据交换和存储,包括Restful中的数据传输,Ajax请求的数据格式,配置文件等,因为其简洁性和可读性,也被广泛用于日志,数据序列化等领域
    • 简洁性:JSON使用简洁的文本格式表示数据
    • 可读性:JSON数据格式有良好的可读性,易于被理解
    • 自我描述性:JSON支持多种数据类型,包括数字,字符串,数组,对象等,可以表示丰富的数据结构
    • 易于解析:JSON数据可以通过大多数编程语言的解析器轻松解析为内部数据结构
  • JSON的数据由键值对组成,其中键(Key)为字符串,值(Value)为表示的数据,一个完整的JSON对象使用{}表示,键值对之间使用:分割,JSON中数组使用[]表示,不同元素之间使用,分割,以下为JSON的简单示例:
{
  "name": "John",
  "age": 30,
  "isStudent": false,
  "friends": ["Alice", "Bob", "Charlie"],
  "address": {
    "city": "New York",
    "zipcode": "10001"
  }
}
  • 在SpingMVC中要想接收JSON数,官方文档给出Spring提供支持Jackson Json的依赖但是功能比较简单,不具备Jackson库提供的一些高级特性,同样SpringMVC也可以使用其他JSON转化库如:
    • Gson:Goolge提供的JSON转化,功能齐全,转化方便
    • FastJson:阿里提供的高性能JSON转化,转化非常快,但转化复杂类型的对象容易出错,可以用Gson将Bean转为Json保证数据正确,用FastJson将Json转Bean提高性能
    • Jackson Json:Jackson是一个成熟的,广泛使用的JSON处理库,其中提供了丰富的功能机制,也支持各种高级特性,在性能上处理大量JSON数据格式会比Gson更快,在支持性与功能性上又比FastJson更多
  • 这里我们导入Jackson库
<properties>
    <jackson.version>2.15.2</jackson.version>
</properties>

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${jackson.version}</version>
</dependency>
  • SpringMVC使用@RequestBody会自动将传入的Json数据转化成对象,并且会对有@ResponseBody的方法返回值自动转化成Json数据返回
@Data
public class Product {
    private String productName;
    private Integer productId;
    private Double value;
}
@PostMapping
public String addProduct(@RequestBody Product product) {
    System.out.println("请求访问商品添加接口,当前商品信息为:" + product);
    return "商品信息添加成功";
}
  • 测试数据
    test_json
    test_json_result

接收简单类型

  • 对于从URL传入的参数,SpringMVC能自动传入到对应的参数名中同时也可以使用@RequestParam对传入的参数名与形参名进行映射
@RequestMapping("/login")
@ResponseBody
public String userLogin(@RequestParam("username") String username, String password) {
    if (Objects.equals(password, "123")) {
        System.out.println(username + "登录成功");
    }else {
        System.out.println("用户密码错误");
    }
    return username;
}
  • 测试输出
    attribute
    arrtribute_test
对象封装参数
  • SpringMVC同时也支持将多个参数封装进类中(需类提供set方法),并将传入数据自动配置到类的属性中
@RequestMapping("/account/login")
@ResponseBody
public String accountLogin(Account account){
    System.out.println(account.getUserName()+
            "\n用户密码:"+account.getPassword());
    return "登录成功";
}
  • 测试输出
    objectobject_test

接收数组类型

  • 数组类型发送方式为:参数1=xxx&参数1=xxx参数1=xxx,SpringMVC会自动将参数1的数据转化为参数1数组中,数组可以是List也可以是数组[]
@RequestMapping("/cart")
@ResponseBody
public String addToCart(@RequestParam List<Integer> productIds){
    System.out.println(productIds);
    return productIds.toString();
}

list
list_test

Restful

  • Restful(Representational State Transfer) 是一种软件架构风格,用于设计网络应用程序,本身是基于一组原则和约束,用于提高系统的可伸缩性,简化通信,提高可见性并降低应用复杂性。其中Restful架构包含的关键约束有:

    • 无状态性(Statelessness):客户端每个请求都必须包含服务器处理所需的所有信息,服务器不应保存客户端的状态,每个请求都必须是独立的。
    • 基于资源(Resource):资源是Restful架构的核心,资源是应用程序中的实体或服务,如用户,订单,产品等,每个资源都应该有唯一的资源路径定位符(URL)
    • 表现层状态转化(Representational State Transfer):表现层是资源(数据或功能)当前状态的表现形式,客户端通过与资源的表现层交互来实现资源的状态转化,通常使用Json或XML作为表现层(简单点说就是使用Json数据与服务端进行交互通信)。
    • 统一接口(Uniform Interface):Restful应该有一个统一的接口,一提高系统的可见性。
    操作对应接口
    通过xx获取指定数据GET
    获取全部数据GET
    添加数据POST
    修改数据PUT
    删除数据DELETE
    • 按需可缓存性:Restful服务能够使用缓存来提高性能,服务器与客户端之间的通信应该标识哪些信息是可以缓存的,并在适当的时候使用缓存
    • 分层系统:构建Restful服务时使用分层系统,每层都提供特定的功能,每个层都只知道与其直接相邻的层的信息,从而提高了系统的可伸缩性(SpringMVC本身就是一个分层架构
  • 以下为Restful风格样例,@RestController里包含@RequestBody与@Controller,并且product有属于自己的资源访问路径/products,客户端与服务端交互使用json数据格式

@RestController
@RequestMapping("/products")
public class ProductController {
    @Autowired
    private ProductService productService;

    @PostMapping
    public Result saveProduct(@RequestBody Product product) {
        boolean flag = productService.saveProduct(product);
        return new Result(flag ? Code.SAVE_OK.getCode() : Code.SAVE_ERROR.getCode(), flag);
    }

    @PutMapping
    public Result updateProduct(@RequestBody Product product) {
        boolean flag = productService.updateProduct(product);
        return new Result(flag ? Code.UPDATE_OK.getCode() : Code.UPDATE_ERROR.getCode(), flag);
    }

    @DeleteMapping("/{id}")
    public Result deleteProduct(@PathVariable Integer id) {
        boolean flag = productService.deleteProductById(id);
        return new Result(flag ? Code.DELETE_OK.getCode() : Code.DELETE_ERROR.getCode(), flag);
    }

    @GetMapping("/{id}")
    public Result getProduct(@PathVariable Integer id) {
        Product product = productService.getProductById(id);
        boolean flag = (product != null);
        String msg = flag ? "数据查询成功" : "数据查询失败,请重试!";
        return new Result(flag ? Code.GET_OK.getCode() : Code.GET_ERROR.getCode(), product, msg);
    }

    @GetMapping
    public Result getAll() {
        List<Product> list = productService.getAllProducts();
        boolean flag = (list != null);
        String msg = flag ? "数据查询成功" : "数据查询失败,请重试!";
        return new Result(flag ? Code.GET_OK.getCode() : Code.GET_ERROR.getCode(), list, msg);
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/457359.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

bootstrap企业网站前端模板

介绍 企业网站前端模板 软件架构 前端所用技术html/css/js/jquery 前端框架bootstrap 安装教程 浏览器本地路径访问发布到服务器比如&#xff08;tomcat/nginx等&#xff09;云服务器/虚拟机 网站效果图 网站预览 点击预览 源码地址 https://gitee.com/taisan/company…

【镜像转存】利用交互式学习平台killercoda转存K8S镜像至Docker私人仓库

文章目录 1. 镜像转存需求2. 注册并登陆 killercoda URL3. 打开playground4. 在线拉取K8S镜像并打上标签5. 推送K8S镜像到Docker私有仓库6. 登陆Docker私有仓库查看 1. 镜像转存需求 因K8S镜像在不开代理的情况下&#xff0c;拉取超时、下载缓慢&#xff0c;导致镜像拉取不下来…

【分布式websocket】群聊中的各种难点以及解决推拉结合【第16期】

前言 群聊中未读消息如何设计&#xff0c;以及是推消息还是拉去消息如何选择是需要讨论的。推送消息是推送全量消息还是推送信号消息让客户端再去拉取。其中方案如何选型会比较纠结。 首先基本的推拉结合思路是在线用户推送消息。用户离线的话上线去拉取消息。这是简单的推拉结…

WPF —— TabControl、StackPanel 控件详解

1 TabControl简介 表示包含多个项的控件&#xff0c;这些项共享屏幕上的同一空间。 TabControl有助于最大程度地减少屏幕空间使用量&#xff0c;同时允许应用程序公开大量数据。 TabControl包含共享同一屏幕空间的多个 TabItem 对象。一次只能看到 TabControl 中的一个 Ta…

交换机/路由器的存储介质-华三

交换机/路由器的存储介质-华三 本文主要介绍网络设备的存储介质组成。 ROM(read-only memory&#xff0c;只读存储器) 用于存储 BootROM程序。BootROM程序是一个微缩的引导程序&#xff0c;主要任务是查找应用程序文件并引导到操作系统&#xff0c;在应用程序文件或配置文件出…

AJAX 01 AJAX 概念和 axios 使用

2.27 AJAX 学习 AJAX 1 入门01 AJAX 概念和 axios 使用axios 使用案例 02 认识 URLURL组成 03 URL 查询参数axios&#xff0d;查询参数案例 &#xff1a;地区查询 04 常用请求方法和数据提交axios 请求配置axios 错误处理 05 HTTP协议-报文① 请求报文作用&#xff1a;错误排查…

uniapp微信小程序_自定义交费逻辑编写

一、首先看最终效果 先说下整体逻辑,选中状态为淡紫色,点击哪个金额,充值页面上就显示多少金额 二、代码 <view class"addMoney"><view class"addMoneyTittle">充值金额</view><view class"selfaddmoney" :class"{…

力扣日记3.14-【贪心算法篇】376. 摆动序列

力扣日记&#xff1a;【贪心算法篇】376. 摆动序列 日期&#xff1a;2024.3.14 参考&#xff1a;代码随想录、力扣 376. 摆动序列 题目描述 难度&#xff1a;中等 如果连续数字之间的差严格地在正数和负数之间交替&#xff0c;则数字序列称为 摆动序列 。第一个差&#xff08;…

【总结】服务器无法连接外网,设置http代理解决

问题 某天想要在服务器上下载编译github上某开源项目&#xff0c;结果发现访问不了外网。 于是找运维&#xff0c;运维给了个http代理服务器地址。简单操作后&#xff0c;就可以访问外网了。 解决 在需要访问外网的机器上&#xff0c;执行以下命令&#xff1a;http_proxyhtt…

rust学习(简单链表)

编写一个简单链表&#xff0c;主要遇到的问题就是next指针&#xff08;按照C的写法&#xff09;的数据如何定义。按照网上的建议&#xff0c;一般定义如下&#xff1a; struct Node {pub value:u32,pub next:Option<Rc<RefCell<Node>>>, //1 }1.用Option主要…

GoLang:云原生时代致力于构建高性能服务器的后端语言

Go语言的介绍 概念 Golang&#xff08;也被称为Go&#xff09;是一种编程语言&#xff0c;由Google于2007年开始设计和开发&#xff0c;并于2009年首次公开发布。Golang是一种静态类型、编译型的语言&#xff0c;旨在提供高效和可靠的软件开发体验。它具有简洁的语法、高效的编…

外卖小程序-购物车模块表结构设计和后端代码

表结构设计 添加购物车代码 Service public class ShoppingCartServiceImpl implements ShoppingCartService {Autowiredprivate ShoppingCartMapper shoppingCartMapper;Autowiredprivate DishMapper dishMapper;Autowiredprivate SetmealMapper setmealMapper;/*** 添加购物…

在浏览器的控制台定义变量,清除后还是报错变量已声明

报错&#xff1a;Uncaught SyntaxError: Identifier words has already been declared 在浏览器的控制台&#xff08;Console&#xff09;中定义的变量是全局变量&#xff0c;它们会保留在当前的浏览器窗口或标签页的生命周期中。即使你清除了控制台的内容&#xff08;例如通过…

[云原生] Prometheus自动服务发现部署

一、部署服务发现 1.1 基于文件的服务发现 基于文件的服务发现是仅仅略优于静态配置的服务发现方式&#xff0c;它不依赖于任何平台或第三方服务&#xff0c;因而也是最为简单和通用的实现方式。 Prometheus Server 会定期从文件中加载 Target 信息&#xff0c;文件可使用 YAM…

基于Java的海南旅游景点推荐系统(Vue.js+SpringBoot)

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用户端2.2 管理员端 三、系统展示四、核心代码4.1 随机景点推荐4.2 景点评价4.3 协同推荐算法4.4 网站登录4.5 查询景点美食 五、免责说明 一、摘要 1.1 项目介绍 基于VueSpringBootMySQL的海南旅游推荐系统&#xff…

使用stream流合并多个List(根据实体类特定属性合并)

开发情景 现有多个List集合,其中都是一样的实体类,这里我想根据实体类的特定属性将它们合并在一起,形成一个最终的List集合。 这里主要用到了Stream流的flatMap方法与reduce方法。 flatMap:可以将多个Stream流合并在一起,形成一个Stream流。 reduce:可以将Stram流中的元…

Oracle登录错误ERROR: ORA-01031: insufficient privileges解决办法

这个问题困扰了我三个星期&#xff0c;我在网上找的解决办法&#xff1a; 1.控制面板->管理工具->计算机管理->系统工具->本地用户和组->ORA_DBA组。 但我电脑上根本找不到。 2.在oracle安装目录下找到oradba.exe运行。 最开始我都不到这个oradba.exe文件在哪…

Java基于微信小程序的校园订餐小程序的研究与实现,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

Linux本地部署开源AI的PDF工具—Stirling PDF并实现公网随时访问

文章目录 1. 安装Docker2. 本地安装部署StirlingPDF3. Stirling-PDF功能介绍4. 安装cpolar内网穿透5. 固定Stirling-PDF公网地址 本篇文章我们将在Linux上使用Docker在本地部署一个开源的PDF工具——Stirling PDF&#xff0c;并且结合cpolar的内网穿透实现公网随时随地访问。 S…

PBKDF2算法:保障密码安全的利器

title: PBKDF2算法&#xff1a;保障密码安全的利器 date: 2024/3/14 16:40:05 updated: 2024/3/14 16:40:05 tags: PBKDF2算法密码安全性迭代盐值密钥 PBKDF2算法起源&#xff1a; PBKDF2&#xff08;Password-Based Key Derivation Function 2&#xff09;算法是一种基于密码…