Spring框架

发布于:2025-07-27 ⋅ 阅读:(15) ⋅ 点赞:(0)

 概论:这一部分主要是讲解当前公司中所使用的技术、框架.

为什么要学习框架,举个例子:走一条道我们走山路是1个小时到达,但是走高速公路就是20分钟到达.走两条路所要花销都是一致的,而且走高速公路还可以使用公路的配套设施(比如服务站加油站之类的,而走山路只能走自己的路),此时我们大多数人都会选择走高速公路.

分析一下servlet的痛点:

1. 添加外部的jar不方便,容易出错,比如添加了一个不匹配的外部的jar版本.

2. 运行和调试的时候需要配套tomcat不方便.

3. 发布不方便servlet项目必须依靠外置的tomcat(外置的web容器)运行.

4. 路由器配置不方便,一个访问地址对应一个servlet类

所以此处我们就使用当前全球最为流行的spring框架进行servlet的替代,让编程能够更加的高效,简单,且能够实现更多的功能.

spring的定义:包含了众多工具的IoC容器.

什么是Ioc:

IoC就是(控制反转)

比如制造一辆汽车,

车 -> 车身 -> 框架 -> 轮胎/发动机

车的制作的每一步流程都是依托于前一步流程的,不可分开.

但是这样制造汽车会影响开发速率,并且流程中的耦合性太高,如果前一步出错(如框架有问题),之后的流程就都会收到影响.

而如今生产汽车引入了流水线,分别制造各个组件.就节省了生产成本,与开发时间.

并且汽车各个部分的组件也可以进行客制化定制.(想要怎样的零件就生产怎样的零件)

ioc其实就相当于现在流水线.不在关注该类的依赖,而是把自己这个类的生命周期交给别的流程让其控制.就相当于将我们每个类的生命周期交给spring,让spring去控制依赖这样可以极大程度上的解耦合.

所以说IoC不是一个具体的技术,是一个思想(就是相当于把自己类的生命周期交给别的类来使用的一种思想)

 怎么理解spring的定义:包含了众多工具的IoC容器.

spring既然是一个容器,故定然有两个功能:

1.存对象

2.取对象

所以说我们要学习的东西也就明确是:存对象和取对象

Spring IoC 优点:

1. 解耦

2. 使用更加方便了(不需要手动进行创建,和关注这个对象背后的关系了)

3. 更加高效

DI的概念:

DI就是(依赖注入)

IoC和DI是一对cp,一般都是同时出现且存在的.

DI(依赖注入)就是在IoC过程中,将依赖的某个对象动态注入(动态拿到当前类当中)的这个行为.

所以说DI就是在主动获取对象.(主要实现方式其实就是一个注解)

所以说IoC( 思想 ) / Spring IoC( 框架 ) / DI( 技术 )

一、安装spring boot 简单方式:

首先寻找一份免费的和你idea版本对应的intellij-spring-assistant-2022.1.2.zip

然后这样添加:

寻找安装包:

然后重启idea就安装好了:

创建项目:

主要就是改一下maven

选择maven版本

添加javaweb:

这样就创建成功了:

另外创建的目录都是这个意思:

二、spring的创建和使用:

1. spring 项目的创建

创建一个Spring(Core):

a.创建一个maven项目

此时就已经初始化好了!!!

b.添加Spring依赖 

添加依赖最终要的一部就是设置国内源(配置国内源的目的是让maven不再从国际上的服务器进行配置提高成功率和速度)

maven helper(控制依赖的插件)

在idea中有两个配置文件的设置:

 然后在相关目录中添加setting.xml文件

三个√需要进行更改. 而且注意路径不要有中文

然后根据上面的路径进入settings.xml

 在这个setting 文件中,有一段镜像的国内源的url:

有了这个进行依赖将会从阿里的服务器进行获取,而不是国外的maven仓库了.

然后重新下载jar包:

为了保证所有jar包走的都是国内源,我们要清空本地所有的jar包,然后再重新下载.

jar包保存在这里 .

另外,还有可能有其他的问题:

比如说运营商问题之类的,这个问题可以换一个网络如:联通移动之类的.

然后添加spring框架的依赖:

<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.20</version>
        </dependency>

c.创建启动类 

2.将 bean 存储 Spring ( 容器 )

首先是创建一个文件:

然后将这段配置文件复制到上面:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:content="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
</beans>

 在这个文件中就可以自己写bean对象.

如果目录是这样子的结构的:

 我们的bean标签中就需要这样进行规定:

3.从 Spring 中获取 bean[ DI ]

首先是得到Spring (上下文) 对象.

第一种方法:

使用ApplicationContext类进行对象的创建(注意要填写正确的配置文件)

然后从spring容器中获取我们的bean:

注意此时的getbean括号内存储的是这个id,怎么存所以怎么取 

 然后就是使用bean

 注意:在代码编写的时候需要注意路径与id:

这个代码编写的目的在于:

没new对象却实现了类里的方法的调用.

第二种方法:

跟第一种方法类似,但是这种方法其实就是ApplicationContext类的一个"替代",类似古代的"钦差"之类的,"见钦差如见皇帝"这个意思.

这两种方法的区别:

首先准备两个构造方法和普通方法

 分别运行两种方法:

 当使用的是ApplicationContext的时候,运行到

        ApplicationContext context=new ClassPathXmlApplicationContext("spring-config.xml");

的时候会将所有的bean对象初始化.

而BeanFactory是当你执行到

Student student=(Student) beanFactory.getBean("student");

时,才会初始化指定的bean对象初始化.

所以说,ApplicationContext比较占用内存,但是效率高调用快;但是BeanFactory比较省内存,但是调用慢,效率低.

从继承和功能的角度:ApplicationContext是BeanFactory的子类,所以它除了有BeanFactory的全部功能,还有一些它独特的功能.(对国际化支持,资源访问支持,时间传播)

获取Bean的三种方式:

1.通过名称进行获取

2.通过类型进行获取 

但是这种获取的方式只能让这一个类型在spring 存一次,如果在bean中存储同一个类型进行多次获取,就会报错. 

3.类型和名称一块获取

其实每一个人工创建的bean,spring都会单独创建一块区域来进行存储,所以算输出的结果相同,但不是同一个bean也是不一样的.

 比如说此时student和stu所打印的内容都是一样的.

 此时打印的结果是:

三、Spring中的简单的读取对象(使用类注解)

注解:可以开启提交和回滚事务(一种是在编译器的环境下直接加代码,一种是通过拦截然后开启事务的方式实现)

之前其实是:

在beans中添加bean,这种方式其实比new更复杂.

此时如果有一种方法,使用注解直接充当sping 的入口. 

五大类注解:

1. @Controller

控制器:验证用户请求的数据正确性.(相当于安保系统)

2. @Service

服务:编排和调度具体执行方法的.(客服中心)

3. @Repository

持久层:和数据库进行交互.(执行者)

另外,我们平时所说的DAO层,DAO(Data Access Object)数据访问层,而@Repository就是其中的一种实现

4. @Component

组件:(工具类)

5.  @Configuration

配置类: (项目中的一些配置)

使用五大注释:

首先创建一个spring项目:

引入依赖等和上面一致.

另外,在使用注释之前还需要做一些准备:

 

在resources目录底下设置配置文件. 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:content="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <content:component-scan base-package="com.bit.service"></content:component-scan>
</beans>

 注意此处的红框中是指定的文件夹,就是让spring指定的去扫描文件,这样可以让程序运行的效率更上一层楼.

设置一个类,调用里面的方法,此时这个注释就是充当了之前bean标签的作用.

 

之后编写主类,跟之前的一致:

只不过这里的id变为了类名的小驼峰形式.

所以要记住是使用:小驼峰进行访问 

Springboot使用方式:

首先这里修改了端口号

写了一个接口返回hello spring,并设定了url

调用了这个url,成功访问:

四、什么是MVC:

就像面试一样,我去面试的话HR来接待,但相应的面试需要公司负责人进行接触,公司具体项目负责人去找人充当面试官

HR -> view

公司具体项目负责人 -> controller

面试官 -> model

也就是一个接待用户,一个找具体谁来干活,一个干活

五、什么是springMVC:

spring结合自身的特点也创造了一款独特的MVC,符合自身特点的:

这个也就是,面试人直接去找部门负责人,然后部门负责人去找相对应面试官安排面试,然后面试通过后部门负责人告诉HR面试人面试通过了,让HR给这个人发offer,HR再和面试人交接

六、SpringBoot常用方法:

建立连接

@RequestMapping-类路径

@RestController-spring标识,告诉spring这个是个需要考虑的类

@RequestMapping制造url,我们要想访问对应页面需要再html页面中填入对应url即可成功进行交互

另外@RequestMapping可以设定接收信息的方法是get还是post

也有@GetMapping只能接受get方法:

也有@PostMapping

另外还有前后端传参:

也可以传两个参数

servlet和springboot的区别:

前后端传递多个参数:

现在企业中通常传递多个对象的方式是这样的:

首先封装对象:
package com.example.demo;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 86139
 * Date: 2025-07-21
 * Time: 21:33
 */
public class User {
    private String name;
    private Integer age;
    private Integer gender;

    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;
    }

    public Integer getGender() {
        return gender;
    }

    public void setGender(Integer gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender=" + gender +
                '}';
    }
}
然后直接打印对象: 
    @RequestMapping("/p1")
    public String test(User user){
        return "user:"+user
    }

如果前端想要传的'name'与后端传的这个'username'不一样,也就是后端不想要用前端传输的这个name进行存储:

    @RequestMapping("/p2")
    public String test2(@RequestParam("userName") String name){
        return "name:"+name;
    }

但如果设定了这个参数绑定@RequestParam后再传之前的变量名,则显示报错400

但是这样太绝对了,如果收到不一致的值直接报错,会导致程序结束,我们想要收到不一致的值返回false怎么办呢?

如果不写这个required的话就默认是value.

    @RequestMapping("/p2")
    public String test2(@RequestParam(value="userName",required = false) String name){
        return "name:"+name;
    }

这样就可以了

通过数组传参:
    @RequestMapping("/p3")
    public String test3(String[] arr){
        return "name:"+ Arrays.toString(arr);
    }

也可以这样:

当前端没有指定数据进行传参时,我们后端可以手动参数绑定将其设置为数组:
    @RequestMapping("/p4")
    public String test4(@RequestParam List<String> list){
        return "name:"+ list;
    }

idea中对象转JSON格式:

public class test {
    public static void main(String[] args) throws JsonProcessingException {
        ObjectMapper objectMapper=new ObjectMapper();
        User user=new User();
        user.setName("zhangsan");
        user.setAge(20);
        user.setGender(1);
        String s=objectMapper.writeValueAsString(user);
        System.out.println(s);
    }

}

idea中Json转对象:

public class test {
    public static void main(String[] args) throws JsonProcessingException {
        ObjectMapper objectMapper=new ObjectMapper();
        User user=new User();
        user.setName("zhangsan");
        user.setAge(20);
        user.setGender(1);
        String s=objectMapper.writeValueAsString(user);
//        System.out.println(s);

        User user1=objectMapper.readValue(s,User.class);
        System.out.println(user1);
    }

}

前端传递JSON和传递对象的区别:

而我们在场景中经常遇到的是接收JSON数据,如何更加简单的接收Json格式数据将其转化为对象呢?

转化Json格式为对象:

    @RequestMapping("/p5")
    public String tset5(@RequestBody User user){
        return "user:"+user;
    }

获取url中id:

    @RequestMapping("/p6/{id}")
    public String test6(@PathVariable("id")String id){
        return "id:"+id;
    }

也可以获取多个参数:

    @RequestMapping("/p6/{id}/{name}")
    public String test6(@PathVariable("id")String id,@PathVariable("name")String name){
        return "id,name:"+id+name;
    }

上传文件及其重命名:

七、cookie:

八、session:

九、Cookie和Session 的区别:

如何获取cookie值:

    @RequestMapping("/helloCookie")
    public String Cookie(HttpServletRequest httpServletRequest){
        Cookie[] cookies=httpServletRequest.getCookies();
        for(Cookie cookie:cookies){
            if(cookie != null) {
                System.out.println(cookie.getName()+":"+cookie.getValue());
            }else{
                break;
            }
        }
        return "cookie获取成功!!!";
    }

我们可以看到在服务器控制台是可以正常打印cookie值的:

另外还有一种获取cookie值的方法:

直接将cookie名写入代码:

    @RequestMapping("/helloCookie2")
    public String Cookie2(@CookieValue("test")String test){
        return "test:"+test;
    }

set以及get session:

    @RequestMapping("/setSeesion")
    public String Session2(HttpServletRequest httpServletRequest){
        HttpSession session=httpServletRequest.getSession();
        session.setAttribute("userName","zhangsan");
        session.setAttribute("age",15);
        return "设置session成功";
    }
    @RequestMapping("/getSeesion")
    public String Session1(HttpServletRequest httpServletRequest){
        HttpSession session=httpServletRequest.getSession();
        String userName=(String)session.getAttribute("userName");
        System.out.println(session.getAttribute("age"));
        return "从cookie中获取值,session:"+userName;
    }

首先模拟客户端建立cookie输入userName与age,然后生成了session

然后再重session中重新获取组成session的cookie:

这样获取session也行:

优化一下:

获取session有三种方式,可以根据应用场景进行选择.

User-Agent:

User-Agent是跟着一个session走的,后台需要知道这个人的喜好以及很多个人信息,就存储在User-Agent中,而想要获取User-Agent也有两种方法:

    @RequestMapping("/User-Agent1")
    public String agent1(HttpServletRequest httpServletRequest) {
        String user = httpServletRequest.getHeader("User-Agent");
        return "User-Agent:" + user;
    }
    @RequestMapping("/User-Agent2")
    public String agent2(@RequestHeader("User-Agent")String user) {
    return "User-Agent:"+user;
    }

上面应用的几乎都是spring 中request的功能,接下来我们要研究的就是response的功能了:

十、response

如果想要直接通过后端代码进行前端的页面跳转应该怎么办呢?

@Controller
@RequestMapping("/response")
public class send {
        @RequestMapping("/hello")
        public String send(){
            return "/hello.html";
        }
}

此处用的标签是@controller而不是@Restcontroller,它俩的关系是@Restcontrollers是在@controller的基础上完善的:

所以说返回数据 -> @ResponseBody

返回页面 -> @Controller

        @ResponseBody
        @RequestMapping("/this is data")
        public String data(){
            return "data.html";
        }

返回Json:

    @ResponseBody
    @RequestMapping("/returnJson")
    public User returnJson(){
        User user=new User();
        user.setName("zhangsan");
        user.setAge(20);
        user.setGender(1);
        return user;
    }

设置状态码:

    @ResponseBody
    @RequestMapping("/returnJson")
    public User returnJson(HttpServletResponse httpServletResponse){
        User user=new User();
        user.setName("zhangsan");
        user.setAge(20);
        user.setGender(1);
        httpServletResponse.setStatus(500);
        return user;
    }

虽然程序不会结束,但是会返回一个500的状态码

设置Header:

这个主要就是能改变header中的传输的信息的类型:

    @ResponseBody
    @RequestMapping(value="/setHeader",produces = "application/json")
    public String setHeader(){
        return "{\"name\":\"zhangsan\",\"age\":20,\"gender\":1}";
    }

也可以这样设置:

    @ResponseBody
    @RequestMapping("setHeader2")
    public void setHeader2(HttpServletResponse response){
        response.setHeader("test","myTest");
        
    }

十一、MVC与三层架构:

三层架构是现在开发中常用的设计模式:表现层、业务逻辑层、数据访问层

MVC强调数据和视图分离,将数据展示和数据处理分开,通过控制器对二者进行组合

三层架构强调不同维度数据处理的高内聚低耦合,将交互页面,业务处理和数据库操作分开

总结:


网站公告

今日签到

点亮在社区的每一天
去签到