Spring Boot 消息队列与异步通信

Spring Boot 消息队列与异步通信

Spring Boot 消息队列与异步通信

在这里插入图片描述
21.1 学习目标与重点提示

学习目标:掌握Spring Boot消息队列与异步通信的核心概念与使用方法,包括消息队列的定义与特点、Spring Boot与ActiveMQ的集成、Spring Boot与RabbitMQ的集成、Spring Boot与Kafka的集成、Spring Boot异步通信的基本方法、Spring Boot的实际应用场景,学会在实际开发中处理消息队列与异步通信问题。
重点:消息队列的定义与特点Spring Boot与ActiveMQ的集成Spring Boot与RabbitMQ的集成Spring Boot与Kafka的集成Spring Boot异步通信的基本方法Spring Boot的实际应用场景

21.2 消息队列概述

消息队列是Java开发中的重要组件。

21.2.1 消息队列的定义

定义:消息队列是一种异步通信机制,用于在应用程序之间传递消息。
作用

  • 实现应用程序之间的异步通信。
  • 实现应用程序之间的解耦。
  • 提高应用程序的性能。

常见的消息队列

  • ActiveMQ:Apache ActiveMQ是一款开源的消息队列。
  • RabbitMQ:RabbitMQ是一款开源的消息队列。
  • Kafka:Apache Kafka是一款开源的消息队列。

✅ 结论:消息队列是一种异步通信机制,作用是实现应用程序之间的异步通信、解耦、提高应用程序的性能。

21.2.2 消息队列的特点

定义:消息队列的特点是指消息队列的特性。
特点

  • 异步通信:消息发送者不需要等待消息接收者的响应。
  • 解耦:消息发送者与消息接收者之间不需要直接通信。
  • 可靠性:消息队列提供消息的可靠传输。
  • 可扩展性:消息队列可以扩展到多个应用程序之间的通信。

✅ 结论:消息队列的特点包括异步通信、解耦、可靠性、可扩展性。

21.3 Spring Boot与ActiveMQ的集成

Spring Boot与ActiveMQ的集成是Java开发中的重要内容。

21.3.1 集成ActiveMQ的步骤

定义:集成ActiveMQ的步骤是指使用Spring Boot与ActiveMQ集成的方法。
步骤

  1. 创建Spring Boot项目。
  2. 添加所需的依赖。
  3. 配置ActiveMQ。
  4. 创建消息生产者。
  5. 创建消息消费者。
  6. 测试应用。

示例
pom.xml文件中的依赖:

<dependencies><!-- Web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- ActiveMQ依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-activemq</artifactId></dependency><!-- 测试依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

application.properties文件中的ActiveMQ配置:

# 服务器端口 server.port=8080 # ActiveMQ配置 spring.activemq.broker-url=tcp://localhost:61616 spring.activemq.user=admin spring.activemq.password=admin 

消息生产者:

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.jms.core.JmsTemplate;importorg.springframework.stereotype.Component;@ComponentpublicclassMessageProducer{@AutowiredprivateJmsTemplate jmsTemplate;publicvoidsendMessage(String destination,String message){ jmsTemplate.convertAndSend(destination, message);System.out.println("发送消息:"+ message);}}

消息消费者:

importorg.springframework.jms.annotation.JmsListener;importorg.springframework.stereotype.Component;@ComponentpublicclassMessageConsumer{@JmsListener(destination ="test-queue")publicvoidreceiveMessage(String message){System.out.println("接收消息:"+ message);}}

控制器类:

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.RestController;@RestControllerpublicclassMessageController{@AutowiredprivateMessageProducer messageProducer;@GetMapping("/send")publicStringsendMessage(@RequestParamString message){ messageProducer.sendMessage("test-queue", message);return"消息发送成功";}}

测试类:

importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.boot.test.web.client.TestRestTemplate;importorg.springframework.boot.web.server.LocalServerPort;importstaticorg.assertj.core.api.Assertions.assertThat;@SpringBootTest(webEnvironment =SpringBootTest.WebEnvironment.RANDOM_PORT)classActiveMQApplicationTests{@LocalServerPortprivateint port;@AutowiredprivateTestRestTemplate restTemplate;@TestvoidcontextLoads(){}@TestvoidtestSendMessage(){String message ="Hello, ActiveMQ!";String response = restTemplate.getForObject("http://localhost:"+ port +"/send?message="+ message,String.class);assertThat(response).contains("消息发送成功");}}

✅ 结论:集成ActiveMQ的步骤包括创建Spring Boot项目、添加所需的依赖、配置ActiveMQ、创建消息生产者、创建消息消费者、测试应用。

21.4 Spring Boot与RabbitMQ的集成

Spring Boot与RabbitMQ的集成是Java开发中的重要内容。

21.4.1 集成RabbitMQ的步骤

定义:集成RabbitMQ的步骤是指使用Spring Boot与RabbitMQ集成的方法。
步骤

  1. 创建Spring Boot项目。
  2. 添加所需的依赖。
  3. 配置RabbitMQ。
  4. 创建消息生产者。
  5. 创建消息消费者。
  6. 测试应用。

示例
pom.xml文件中的依赖:

<dependencies><!-- Web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- RabbitMQ依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><!-- 测试依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

application.properties文件中的RabbitMQ配置:

# 服务器端口 server.port=8080 # RabbitMQ配置 spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest 

消息生产者:

importorg.springframework.amqp.rabbit.core.RabbitTemplate;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Component;@ComponentpublicclassMessageProducer{@AutowiredprivateRabbitTemplate rabbitTemplate;publicvoidsendMessage(String exchange,String routingKey,String message){ rabbitTemplate.convertAndSend(exchange, routingKey, message);System.out.println("发送消息:"+ message);}}

消息消费者:

importorg.springframework.amqp.rabbit.annotation.RabbitListener;importorg.springframework.stereotype.Component;@ComponentpublicclassMessageConsumer{@RabbitListener(queues ="test-queue")publicvoidreceiveMessage(String message){System.out.println("接收消息:"+ message);}}

RabbitMQ配置类:

importorg.springframework.amqp.core.Binding;importorg.springframework.amqp.core.BindingBuilder;importorg.springframework.amqp.core.DirectExchange;importorg.springframework.amqp.core.Queue;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;@ConfigurationpublicclassRabbitMQConfig{@BeanpublicQueuetestQueue(){returnnewQueue("test-queue",true);}@BeanpublicDirectExchangetestExchange(){returnnewDirectExchange("test-exchange");}@BeanpublicBindingtestBinding(){returnBindingBuilder.bind(testQueue()).to(testExchange()).with("test-routing-key");}}

控制器类:

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.RestController;@RestControllerpublicclassMessageController{@AutowiredprivateMessageProducer messageProducer;@GetMapping("/send")publicStringsendMessage(@RequestParamString message){ messageProducer.sendMessage("test-exchange","test-routing-key", message);return"消息发送成功";}}

测试类:

importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.boot.test.web.client.TestRestTemplate;importorg.springframework.boot.web.server.LocalServerPort;importstaticorg.assertj.core.api.Assertions.assertThat;@SpringBootTest(webEnvironment =SpringBootTest.WebEnvironment.RANDOM_PORT)classRabbitMQApplicationTests{@LocalServerPortprivateint port;@AutowiredprivateTestRestTemplate restTemplate;@TestvoidcontextLoads(){}@TestvoidtestSendMessage(){String message ="Hello, RabbitMQ!";String response = restTemplate.getForObject("http://localhost:"+ port +"/send?message="+ message,String.class);assertThat(response).contains("消息发送成功");}}

✅ 结论:集成RabbitMQ的步骤包括创建Spring Boot项目、添加所需的依赖、配置RabbitMQ、创建消息生产者、创建消息消费者、测试应用。

21.5 Spring Boot与Kafka的集成

Spring Boot与Kafka的集成是Java开发中的重要内容。

21.5.1 集成Kafka的步骤

定义:集成Kafka的步骤是指使用Spring Boot与Kafka集成的方法。
步骤

  1. 创建Spring Boot项目。
  2. 添加所需的依赖。
  3. 配置Kafka。
  4. 创建消息生产者。
  5. 创建消息消费者。
  6. 测试应用。

示例
pom.xml文件中的依赖:

<dependencies><!-- Web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Kafka依赖 --><dependency><groupId>org.springframework.kafka</groupId><artifactId>spring-kafka</artifactId></dependency><!-- 测试依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

application.properties文件中的Kafka配置:

# 服务器端口 server.port=8080 # Kafka配置 spring.kafka.bootstrap-servers=localhost:9092 spring.kafka.consumer.group-id=test-group spring.kafka.consumer.auto-offset-reset=earliest spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer 

消息生产者:

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.kafka.core.KafkaTemplate;importorg.springframework.stereotype.Component;@ComponentpublicclassMessageProducer{@AutowiredprivateKafkaTemplate<String,String> kafkaTemplate;publicvoidsendMessage(String topic,String message){ kafkaTemplate.send(topic, message);System.out.println("发送消息:"+ message);}}

消息消费者:

importorg.springframework.kafka.annotation.KafkaListener;importorg.springframework.stereotype.Component;@ComponentpublicclassMessageConsumer{@KafkaListener(topics ="test-topic", groupId ="test-group")publicvoidreceiveMessage(String message){System.out.println("接收消息:"+ message);}}

控制器类:

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.RestController;@RestControllerpublicclassMessageController{@AutowiredprivateMessageProducer messageProducer;@GetMapping("/send")publicStringsendMessage(@RequestParamString message){ messageProducer.sendMessage("test-topic", message);return"消息发送成功";}}

测试类:

importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.boot.test.web.client.TestRestTemplate;importorg.springframework.boot.web.server.LocalServerPort;importstaticorg.assertj.core.api.Assertions.assertThat;@SpringBootTest(webEnvironment =SpringBootTest.WebEnvironment.RANDOM_PORT)classKafkaApplicationTests{@LocalServerPortprivateint port;@AutowiredprivateTestRestTemplate restTemplate;@TestvoidcontextLoads(){}@TestvoidtestSendMessage(){String message ="Hello, Kafka!";String response = restTemplate.getForObject("http://localhost:"+ port +"/send?message="+ message,String.class);assertThat(response).contains("消息发送成功");}}

✅ 结论:集成Kafka的步骤包括创建Spring Boot项目、添加所需的依赖、配置Kafka、创建消息生产者、创建消息消费者、测试应用。

21.6 Spring Boot异步通信的基本方法

Spring Boot异步通信的基本方法包括使用@Async注解、使用CompletableFuture、使用消息队列。

21.6.1 使用@Async注解

定义:使用@Async注解是指使用Spring Boot异步通信的基本方法之一。
作用

  • 实现异步通信。
  • 提高应用程序的性能。

示例
pom.xml文件中的依赖:

<dependencies><!-- Web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 测试依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

异步配置类:

importorg.springframework.context.annotation.Configuration;importorg.springframework.scheduling.annotation.EnableAsync;@Configuration@EnableAsyncpublicclassAsyncConfig{}

异步服务类:

importorg.springframework.scheduling.annotation.Async;importorg.springframework.stereotype.Service;@ServicepublicclassAsyncService{@AsyncpublicvoidasyncMethod(){System.out.println("异步方法执行:"+Thread.currentThread().getName());}}

控制器类:

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RestController;@RestControllerpublicclassAsyncController{@AutowiredprivateAsyncService asyncService;@GetMapping("/async")publicStringasyncMethod(){System.out.println("主线程执行:"+Thread.currentThread().getName()); asyncService.asyncMethod();return"异步方法调用成功";}}

测试类:

importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.boot.test.web.client.TestRestTemplate;importorg.springframework.boot.web.server.LocalServerPort;importstaticorg.assertj.core.api.Assertions.assertThat;@SpringBootTest(webEnvironment =SpringBootTest.WebEnvironment.RANDOM_PORT)classAsyncApplicationTests{@LocalServerPortprivateint port;@AutowiredprivateTestRestTemplate restTemplate;@TestvoidcontextLoads(){}@TestvoidtestAsyncMethod(){String response = restTemplate.getForObject("http://localhost:"+ port +"/async",String.class);assertThat(response).contains("异步方法调用成功");}}

✅ 结论:使用@Async注解是指使用Spring Boot异步通信的基本方法之一,作用是实现异步通信、提高应用程序的性能。

21.6.2 使用CompletableFuture

定义:使用CompletableFuture是指使用Spring Boot异步通信的基本方法之一。
作用

  • 实现异步通信。
  • 提高应用程序的性能。

示例
控制器类:

importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RestController;importjava.util.concurrent.CompletableFuture;importjava.util.concurrent.ExecutionException;@RestControllerpublicclassCompletableFutureController{@GetMapping("/completableFuture")publicStringcompletableFuture()throwsExecutionException,InterruptedException{System.out.println("主线程执行:"+Thread.currentThread().getName());CompletableFuture<Void> future =CompletableFuture.runAsync(()->{System.out.println("异步方法执行:"+Thread.currentThread().getName());}); future.get();return"CompletableFuture调用成功";}}

测试类:

importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.boot.test.web.client.TestRestTemplate;importorg.springframework.boot.web.server.LocalServerPort;importstaticorg.assertj.core.api.Assertions.assertThat;@SpringBootTest(webEnvironment =SpringBootTest.WebEnvironment.RANDOM_PORT)classCompletableFutureApplicationTests{@LocalServerPortprivateint port;@AutowiredprivateTestRestTemplate restTemplate;@TestvoidcontextLoads(){}@TestvoidtestCompletableFuture(){String response = restTemplate.getForObject("http://localhost:"+ port +"/completableFuture",String.class);assertThat(response).contains("CompletableFuture调用成功");}}

✅ 结论:使用CompletableFuture是指使用Spring Boot异步通信的基本方法之一,作用是实现异步通信、提高应用程序的性能。

21.7 Spring Boot的实际应用场景

在实际开发中,Spring Boot消息队列与异步通信的应用场景非常广泛,如:

  • 实现用户注册的异步处理。
  • 实现订单的异步处理。
  • 实现邮件发送的异步处理。
  • 实现日志的异步处理。

示例

importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.scheduling.annotation.EnableAsync;importorg.springframework.scheduling.annotation.Async;importorg.springframework.stereotype.Service;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RestController;@SpringBootApplication@EnableAsyncpublicclassUserRegistrationApplication{publicstaticvoidmain(String[] args){SpringApplication.run(UserRegistrationApplication.class, args);}}@ServiceclassUserRegistrationService{@AsyncpublicvoidsendWelcomeEmail(String email){System.out.println("发送欢迎邮件:"+ email);try{Thread.sleep(2000);}catch(InterruptedException e){ e.printStackTrace();}System.out.println("邮件发送成功:"+ email);}}@RestControllerclassUserRegistrationController{@AutowiredprivateUserRegistrationService userRegistrationService;@GetMapping("/register")publicStringregisterUser(String email){System.out.println("用户注册:"+ email); userRegistrationService.sendWelcomeEmail(email);return"用户注册成功";}}// 测试类@SpringBootTest(webEnvironment =SpringBootTest.WebEnvironment.RANDOM_PORT)classUserRegistrationApplicationTests{@LocalServerPortprivateint port;@AutowiredprivateTestRestTemplate restTemplate;@TestvoidcontextLoads(){}@TestvoidtestRegisterUser(){String email ="[email protected]";String response = restTemplate.getForObject("http://localhost:"+ port +"/register?email="+ email,String.class);assertThat(response).contains("用户注册成功");}}

输出结果

控制台输出:

用户注册:[email protected] 发送欢迎邮件:[email protected] 邮件发送成功:[email protected] 

✅ 结论:在实际开发中,Spring Boot消息队列与异步通信的应用场景非常广泛,需要根据实际问题选择合适的异步通信方法。

总结

本章我们学习了Spring Boot消息队列与异步通信,包括消息队列的定义与特点、Spring Boot与ActiveMQ的集成、Spring Boot与RabbitMQ的集成、Spring Boot与Kafka的集成、Spring Boot异步通信的基本方法、Spring Boot的实际应用场景,学会了在实际开发中处理消息队列与异步通信问题。其中,消息队列的定义与特点、Spring Boot与ActiveMQ的集成、Spring Boot与RabbitMQ的集成、Spring Boot与Kafka的集成、Spring Boot异步通信的基本方法、Spring Boot的实际应用场景是本章的重点内容。从下一章开始,我们将学习Spring Boot的其他组件、微服务等内容。

Read more

openJiuwen集成蓝耘AI模型深度解析:从架构设计到企业级Agent实战部署

openJiuwen集成蓝耘AI模型深度解析:从架构设计到企业级Agent实战部署

前言 在人工智能技术从单纯的感知智能向认知智能演进的浪潮中,大语言模型(LLM)的成熟催生了AI Agent(人工智能体)这一全新的应用形态。AI Agent不再局限于传统的单指令执行,而是演进为具备自主感知、推理规划、决策执行能力的智能实体。在这一技术变革背景下,openJiuwen作为一个致力于提供灵活、强大且易用能力的开源Agent平台应运而生。本文将深度剖析openJiuwen的技术架构、核心优势,并基于真实的服务器部署环境,详细拆解从底层环境搭建到上层复杂智能体构建的全过程。 一、 Agentic AI时代的基础设施:openJiuwen概览 openJiuwen的定位不仅是一个开发工具,而是面向生产级应用的Agent全生命周期管理平台。它旨在解决当前大模型应用落地过程中面临的开发门槛高、协同调度难、运行稳定性差等痛点。通过提供标准化的开发框架与高可靠的运行引擎,openJiuwen支持开发者快速构建能够处理各类简单或复杂任务的AI Agent,并实现多Agent间的协同交互。 作为核心代码资产的入口,开发者能在这里查看项目的 Readme 文档、分支管理和最新提交

By Ne0inhk

用 OpenClaw + 飞书,快速搭建 5 个可协作的 AI 助理团队

多个飞书机器人 + 独立工作空间 + 互相协作 = 专业化分工的 AI 助理团队 写在前面 如何用 OpenClaw 搭建一套多 Agent 系统,让 AI 助理各司其职、协同工作?通过 OpenClaw 多 Agent 架构,你可以实现: * 多个独立的飞书机器人,每个人设不同 * 各自独立的工作空间,数据完全隔离 * 可以互相协作,通过 agentToAgent 通信 * 共享长期记忆,跨渠道信息同步 本文将详细介绍如何在腾讯云服务器上,用 OpenClaw 搭建一套飞书多 Agent 系统,包括完整配置流程、常见问题解决方案和实战协作案例。 目录 1. 为什么需要多 Agent 2. 前置准备 3. 5 个 Agent

By Ne0inhk
人工智能大模型应用开发:从微调适配到场景落地

人工智能大模型应用开发:从微调适配到场景落地

一、人工智能大模型应用开发:从微调适配到场景落地 1.1 本章学习目标与重点 💡 掌握大模型应用开发的核心流程,包括模型选型、微调适配、功能封装、部署上线等关键环节; 💡 熟练运用主流大模型框架(Hugging Face Transformers、LangChain、LlamaIndex 等),实现文本生成、问答系统、智能助手等常见应用; 💡 理解大模型微调的核心技术(全参数微调、LoRA、QLoRA 等),能够根据数据规模和硬件资源选择合适的适配方案; 💡 通过真实场景案例(企业知识库问答、智能客服、代码生成助手),掌握大模型从技术适配到业务落地的端到端开发能力。 ⚠️ 重点关注:大模型的上下文窗口限制、生成内容的准确性与安全性、微调过程中的显存优化、以及生产环境下的性能与稳定性平衡。 1.2 大模型应用开发基础:选型与环境搭建 大模型应用开发的第一步是明确业务需求,选择合适的模型并搭建稳定的开发环境。本节将从模型选型原则、主流开发框架介绍、环境搭建实操三个维度,为后续开发奠定基础。 1.2.1

By Ne0inhk
医疗AI场景下算法编程的深度解析(2026新生培训讲稿)(三)

医疗AI场景下算法编程的深度解析(2026新生培训讲稿)(三)

第5章 逻辑回归:疾病风险概率建模 逻辑回归(Logistic Regression)尽管名称中含有“回归”,但它实际上是一种广泛应用于分类任务的线性模型。在医疗领域,逻辑回归因其简单、高效、可解释性强,以及能够输出概率值的特点,成为疾病风险预测、诊断辅助、预后评估等任务的基石算法。本章将从算法原理出发,深入解析逻辑回归在医疗场景中的适用性,并通过实战案例展示从数据预处理、模型训练、结果解释到临床应用的完整流程。 5.1 算法原理 逻辑回归的核心思想是:通过线性回归的输出来估计样本属于某个类别的概率。它使用一个非线性函数(Sigmoid函数)将线性组合的实数输出映射到0到1之间的概率值,从而解决分类问题。 5.1.1 从线性回归到逻辑回归 线性回归模型试图用特征的线性组合来预测一个连续值: [ z = \theta_0 + \theta_1 x_1 + \theta_2 x_2 + … + \theta_p x_

By Ne0inhk