Java EE/Jakarta EE范畴一览
Java EE(Java Platform, Enterprise Edition)现在已经改名为Jakarta EE,是一套用于开发企业级应用的标准Java平台。它扩展了Java SE(Standard Edition),添加了支持大规模、多层次、可靠、安全、可伸缩和可管理企业应用程序的库和API。这里简要概述一下Java EE的主要组成部分和标准:
核心组件
Servlet API
用于构建Web应用程序的基础,处理HTTP请求和响应。
Servlet API 是 Java EE 规范的一个核心部分,主要用于构建基于 Web 的应用程序。它提供了一种在服务器端接收和响应客户端(如 Web 浏览器)请求的方式。Servlet 是 Java 编写的小程序,运行在服务器上,并通过 Servlet API 与客户端进行通信。
基本概念
- Servlet:一个 Java 类,用于扩展服务器的功能,处理来自 Web 客户端的请求,并对其进行响应。
- 请求处理:Servlet 通过
HttpServletRequest对象接收请求数据,使用HttpServletResponse对象生成响应。
Servlet 生命周期
- 加载和实例化:Servlet 容器(如 Apache Tomcat)首先加载 Servlet 类,并创建其实例。
- 初始化:通过调用
init方法初始化 Servlet。这个方法只执行一次,主要用于一次性设置工作。 - 请求处理:对于每个客户端请求,Servlet 容器调用
service方法。此方法根据请求的类型(GET、POST 等)进一步调用doGet、doPost等方法。 - 终止:当需要从服务中移除 Servlet 时,容器调用
destroy方法,进行资源释放和清理工作。这个方法也只执行一次。
创建一个基础 Servlet
以下是一个简单的 Servlet 示例,展示了如何处理 GET 请求:
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;public class SimpleServlet extends HttpServlet {public void init() throws ServletException {// 初始化代码}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setContentType("text/html");PrintWriter out = response.getWriter();out.println("<html><body>");out.println("<h1>Hello, World!</h1>");out.println("</body></html>");}public void destroy() {// 清理资源代码}
}
部署 Servlet
为了运行上述 Servlet,你需要将其部署到一个支持 Servlet API 的 Web 容器中,如 Apache Tomcat 或 Jetty。部署通常涉及到编写一些配置(如在 web.xml 文件中配置 Servlet 和 URL 映射),或者在使用新版本 Servlet 容器时,可以通过注解自动完成。
总结
Servlet API 提供了一种强大的方式来创建动态 Web 应用程序,通过接收、处理 HTTP 请求和生成响应。它是 Java Web 开发的基石,其他很多 Java Web 技术和框架(如 Spring MVC、JSF)都是建立在 Servlet 的基础之上。
JavaServer Pages (JSP)
允许在HTML页面中嵌入Java代码,用于动态生成Web内容。
JavaServer Pages (JSP) 是一个帮助开发者创建动态生成的web页面的技术,它允许开发者将Java代码嵌入到HTML页面中。JSP 被广泛用于简化网页内容的动态生成,特别是当页面内容依赖于用户的请求或需要从数据库检索信息时。JSP 最终是被服务器解释并执行,返回纯 HTML 输出到客户端(浏览器)。
JSP 工作原理
- 请求处理:当用户访问一个 JSP 页面时,请求首先被发送到服务器。
- JSP 到 Servlet 的转换:在后台,JSP 页面被转换成一个 Servlet。这一转换通常在第一次请求时完成,或者在开发者修改 JSP 后的第一次请求时完成。
- 代码编译:生成的 Servlet 代码被编译成可执行的 Java 类。
- 执行:Servlet 类被加载到 JVM 中并执行。执行过程中,它读取请求,处理请求,并生成响应。
- 生成 HTML:JSP 页面中的静态内容被直接写入到响应中,而嵌入的 Java 代码则根据其逻辑动态生成内容。生成的内容也写入响应中。
- 发送响应:最终,服务器将完整的 HTML 响应发送回客户端浏览器。
JSP 的主要组成部分
- 指令(Directives):这些指令用于设置与整个 JSP 页面相关的属性,如页面编码、引入文件等。
- 例如:
<%@ page language="java" contentType="text/html; charset=UTF-8" %>
- 例如:
- 脚本元素:
- 声明(Declarations):用于声明变量和方法。声明的代码片段在 JSP 转换成 Servlet 时被放入 Servlet 类的类体中。
- 例如:
<%! int i = 0; %>
- 例如:
- 表达式(Expressions):用于在页面中输出内容,替代了
out.print()方法。- 例如:
<%= "Hello, " + name %>
- 例如:
- 脚本片段(Scriptlets):包含任意的 Java 代码,这些代码在请求处理阶段执行。
- 例如:
<% for (int i = 0; i < 10; i++) { out.println(i); } %>
- 例如:
- 声明(Declarations):用于声明变量和方法。声明的代码片段在 JSP 转换成 Servlet 时被放入 Servlet 类的类体中。
- 动作(Actions):使用 XML 标记对执行特定操作的内置功能进行编码,如实例化 JavaBeans、执行重定向等。
- 例如:
<jsp:forward page="/nextPage.jsp" />
- 例如:
- 隐含对象:JSP 支持多种隐含对象,为开发者提供请求、响应等环境的直接访问,如
request,response,session,application等。
优点和缺点
优点:
- 简化了网页内容的动态生成。
- 支持重用代码和使用 JavaBeans 简化组件模型。
- 与 Servlet 技术无缝集成,可以轻松访问底层的 HTTP 信息。
缺点:
- 由于 JSP 页面中的 Java 代码和 HTML 混合,可能导致维护困难。
- 大量的逻辑放在 JSP 中会使页面复杂和难以管理,违反了 MVC 设计模式的理念。
JSP 技术现在已经逐渐被现代的 MVC 框架所取代,如 Spring MVC,这些框架提供了更清晰的分层和分离逻辑,但在某些遗留系统和特定应用场景中,JSP 仍然是一种有用的技术。
JavaServer Faces (JSF)
一个Web应用程序框架,简化了用户界面(UI)的开发,支持可重用组件和MVC架构。
JavaServer Faces (JSF) 是一个用于构建基于服务器的用户界面的 Java Web 应用程序框架。JSF 是 Java EE 的官方标准,专为简化企业级应用的用户界面开发而设计。它使用基于组件的方法,允许开发者通过拖放组件来创建视图,从而简化了 Web 应用程序的开发过程。
JSF 的核心特性
- 组件基础架构:JSF 提供了一套丰富的预定义界面组件,如文本框、按钮、链接等,并支持自定义组件的开发。
- 事件驱动:JSF 支持事件驱动编程模型,类似于桌面应用程序。组件可以生成用户交互事件(例如点击和选择),并且可以关联到服务器端的事件处理器。
- 导航管理:JSF 包括一个定义页面间导航逻辑的框架,使得开发者可以管理页面如何根据事件结果进行转换。
- 数据绑定:JSF 支持将页面组件与数据模型直接绑定,简化了数据从用户界面到应用程序后端的流动。
- 依赖注入:JSF 与 Java EE 的依赖注入和上下文管理无缝整合,特别是与 CDI (Contexts and Dependency Injection) 的集成。
- 面向方面的编程:通过使用拦截器和装饰器,开发者可以在不修改现有业务逻辑的情况下增加额外的行为。
JSF 的架构组件
- 面生命周期:JSF 应用遵循一个明确的请求处理生命周期,包括恢复视图、处理组件事件、验证组件数据、更新模型值和渲染视图等步骤。
- 托管 Bean:这些是用于在 JSF 页面和后端逻辑之间进行数据传递和控制页面逻辑的服务器端对象。
- 表达式语言 (EL):JSF 使用 EL 来绑定组件的属性到 Bean 的属性或方法上,允许在页面上简洁地引用动态值。
- 转换器和验证器:JSF 支持使用转换器将用户输入转换为应用程序中的数据类型,以及使用验证器来确保用户输入的数据有效。
- AJAX:JSF 允许开发者通过 AJAX 增强用户界面的交互性,而无需直接编写 JavaScript 代码。
开发环境
JSF 应用通常在支持 Java EE 的应用服务器上运行,如 WildFly, Payara, 或者 Tomcat(通过添加 JSF 支持)。开发过程可以通过 IDE(如 Eclipse, IntelliJ IDEA 或 NetBeans)进行,这些 IDE 提供了对 JSF 的丰富支持,包括视图设计、自动完成和调试。
示例代码
下面是一个简单的 JSF 页面示例,演示了如何使用托管 Bean 和组件:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"xmlns:h="http://xmlns.jcp.org/jsf/html">
<head><title>Simple JSF Example</title>
</head>
<body><h:form><h:outputLabel value="Enter your name: "/><h:inputText value="#{userBean.name}"/><h:commandButton value="Submit" action="#{userBean.sayHello}"/><h:outputText value="#{userBean.message}"/></h:form>
</body>
</html>
在上述示例中,userBean 是一个托管 Bean,包含用户的名称和一个方法来生成问候语。
总结
JSF 是一个强大的框架,专为简化复杂的用户界面开发设计。通过其组件化、事件驱动和模型视图控制器 (MVC) 设计,JSF 成为开发大型企业级 Web 应用的理想选择。然而,随着单页应用 (SPA) 框架的兴起,如 Angular、React 和 Vue.js,传统的 JSF 正在逐渐被这些现代框架所替代,特别是在需要高度动态的用户界面和前端驱动的交互中。
Java Persistence API (JPA)
处理关系数据管理的标准方式,提供了对象-关系映射(ORM)来管理数据库。
Java Persistence API (JPA) 是 Java EE 和现在的 Jakarta EE 平台中用于管理关系数据的标准 API。JPA 主要是为了简化实体数据的持久化即数据保存到数据库的处理过程,通过提供一个对象关系映射 (ORM) 框架,将 Java 对象映射到数据库表。它旨在克服传统 JDBC 直接操作数据库时的复杂性和繁琐性,提供一个更高级和面向对象的数据管理方式。
JPA 核心概念
-
实体(Entity):是持久化数据的核心概念,任何可以持久化到数据库的对象都称为实体。在 Java 类中通过使用
@Entity注解来标识。 -
实体管理器(Entity Manager):是 JPA 中用于管理实体包括实体的生命周期的组件。实体管理器通过
EntityManager接口实现,提供了创建、读取、删除和更新实体的操作。 -
持久化单元(Persistence Unit):在
persistence.xml配置文件中定义,指定了一组实体类和管理这些实体类的配置,包括数据库连接和特定的 ORM 设置。 -
事务(Transaction):用于确保数据一致性和完整性的方式。JPA 支持事务操作,允许一组操作要么全部成功,要么全部失败。
JPA 操作流程
- 定义实体类:首先,定义表示数据库表的实体类,并使用注解标识其映射关系。
- 配置持久化单元:在
persistence.xml文件中配置数据库和实体管理的相关属性。 - 进行 CRUD 操作:通过
EntityManager实例进行创建、读取、更新和删除操作。
示例代码
下面是一个简单的 JPA 实体类和基本的 CRUD 操作示例。
实体类定义
import javax.persistence.Entity;
import javax.persistence.Id;@Entity
public class User {@Idprivate Long id;private String name;// 构造函数、getter 和 setter
}
持久化操作示例
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;public class Main {public static void main(String[] args) {EntityManagerFactory emf = Persistence.createEntityManagerFactory("my-persistence-unit");EntityManager em = emf.createEntityManager();em.getTransaction().begin();User user = new User();user.setId(1L);user.setName("John Doe");em.persist(user); // 创建一个新用户user.setName("Jane Doe"); // 更新这个用户em.merge(user); // 合并更改到数据库User foundUser = em.find(User.class, 1L); // 读取用户System.out.println(foundUser.getName());em.remove(user); // 删除用户em.getTransaction().commit();em.close();emf.close();}
}
总结
JPA 提供了一个与数据库技术无关的数据持久化方式,使开发者能够以面向对象的视角来处理数据库操作,避免繁琐的 SQL 代码,同时自动处理很多数据库交互的复杂性。JPA 是现代 Java 应用中数据持久化的推荐方法,尤其适用于企业级应用。
Enterprise JavaBeans (EJB)
用于封装业务逻辑的可重用组件,支持事务处理、安全性和并发处理。
Enterprise JavaBeans (EJB) 是一种服务器端软件组件模型,它简化了企业应用的开发,特别是在需要处理事务、安全性和并发操作的应用程序。EJB 是 Java EE 规范的一部分,设计目的是让开发者能够快速开发可扩展、安全、可复用的业务逻辑组件。
EJB 的主要特性
-
事务管理:EJB 容器可以自动管理事务,确保数据完整性和一致性。开发者可以通过声明式事务管理来指定方法的事务行为,而无需编写具体的事务处理代码。
-
安全性:EJB 支持基于角色的安全访问控制,允许企业设置谁可以访问哪些 EJB。这种安全策略是通过声明式安全来实现的,使得开发者可以在没有编写复杂安全代码的情况下保护应用。
-
并发处理:EJB 容器管理并发访问,确保EJB实例的线程安全,允许多个客户端同时访问同一个 EJB。
-
生命周期管理:EJB 容器负责管理 EJB 的生命周期,包括实例化、持久化和销毁。
EJB 的类型
EJB 有三种主要类型,每种类型都针对不同的企业应用需求:
-
Session Beans:
- Stateless Session Beans:不保持客户端状态,适用于执行不依赖于以前调用状态信息的操作。
- Stateful Session Beans:保持与特定客户端的会话状态,适用于需要跨多个方法调用或事务保持信息的操作。
- Singleton Session Beans:为整个应用提供一个共享的业务逻辑组件实例,适合实现共享配置或缓存。
-
Message-driven Beans (MDB):允许 EJB 通过使用消息队列进行异步通信,适用于处理如 JMS 消息的应用。
-
Entity Beans(已被 Java Persistence API (JPA) 替代):早期的 EJB 规范包括了 Entity Beans,用于表示持久化到数据库中的业务数据。现在,这一功能由 JPA 完全取代。
开发和部署 EJB
EJB 组件在部署时需要配置描述文件(通常是 XML 文件),描述文件指定了 EJB 的属性、事务管理策略和安全策略等。这些组件被部署在支持 EJB 的应用服务器中(如 WildFly, IBM WebSphere, Oracle WebLogic 等)。
示例:一个简单的 Stateless Session Bean
import javax.ejb.Stateless;@Stateless
public class HelloBean implements HelloBeanRemote {public String sayHello(String name) {return "Hello, " + name + "!";}
}
在上面的示例中,HelloBean 是一个无状态的会话 Bean,提供了一个简单的方法 sayHello,该方法接收一个字符串参数并返回一个问候语。
总结
EJB 提供了一个强大的架构,用于开发分布式、事务性、多用户企业级应用程序。它抽象了许多复杂性,如事务管理、安全性、并发处理等,允许开发者专注于业务逻辑的实现。随着时间的推移,一些 EJB 的功能已经被更现代的 Java EE/Jakarta EE 技术如 CDI, JPA 等所取代,但 EJB 仍然在很多遗留系统中发挥着重要作用。
Java Message Service (JMS)
允许应用程序通过创建、发送、接收和读取数据(消息)来进行通信,支持可靠的异步通信。
Java Message Service (JMS) 是一个 Java 平台上的 API,专门用于在两个应用程序之间,或分布式系统中的组件之间,发送消息,实现异步通信。JMS 是一种中间件服务的形式,可以用来解耦应用程序组件,使它们可以独立地处理消息。
JMS 的主要特点
- 异步性:JMS 允许客户端继续进行其它处理,而不需要等待消息的发送或接收响应。
- 可靠性:提供了可靠的消息传递机制,确保消息可以成功送达,即使在消息系统失败的情况下也不会丢失消息。
- 解耦:发送者和接收者不需要同时在线,消息可以存储在消息队列中,直到接收者可用。
- 灵活性:支持点对点(Queue)和发布/订阅(Topic)两种消息传递模型。
JMS 的两种消息模型
-
点对点(Point-to-Point, P2P):
- 使用队列(Queue)作为中介。
- 每个消息只能有一个消费者(即一个消息被一个消费者接收)。
- 发送者和接收者之间没有时间依赖性,即发送者不需要在接收者接收时处于活动状态,反之亦然。
-
发布/订阅(Publish/Subscribe, Pub/Sub):
- 使用主题(Topic)作为中介。
- 消息可以有多个消费者。
- 通常用于实现信息的广播。
JMS 的主要组件
- JMS 提供者:实现 JMS 接口以提供消息服务的系统或中间件。
- JMS 客户端:生产(发送)和消费(接收)消息的应用程序。
- 消息:在应用程序之间传输的数据。
- 消息生产者:创建并发送消息的对象。
- 消息消费者:接收消息的对象。
- 消息队列/主题:存储消息的中间实体,直到它们被消费。
示例代码
以下是一个简单的 JMS 发送和接收消息的示例,假设使用了一个 JMS 兼容的消息代理。
发送消息
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSContext;
import javax.jms.JMSProducer;
import javax.jms.Queue;
import javax.naming.InitialContext;public class JmsSender {public static void main(String[] args) throws Exception {InitialContext ctx = new InitialContext();ConnectionFactory factory = (ConnectionFactory) ctx.lookup("myConnectionFactory");Queue queue = (Queue) ctx.lookup("myQueue");try (JMSContext context = factory.createContext()) {JMSProducer producer = context.createProducer();producer.send(queue, "Hello, JMS!");}}
}
接收消息
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSConsumer;
import javax.jms.JMSContext;
import javax.jms.Queue;
import javax.naming.InitialContext;public class JmsReceiver {public static void main(String[] args) throws Exception {InitialContext ctx = new InitialContext();ConnectionFactory factory = (ConnectionFactory) ctx.lookup("myConnectionFactory");Queue queue = (Queue) ctx.lookup("myQueue");try (JMSContext context = factory.createContext()) {JMSConsumer consumer = context.createConsumer(queue);String receivedMessage = consumer.receiveBody(String.class);System.out.println("Received Message: " + receivedMessage);}}
}
总结
JMS 是一个强大的工具,用于在 Java 应用程序中实现消息传递。它支持复杂的分布式系统中的异步通信和解耦,适合处理各种从简单的工作队列到复杂的事件处理系统的场景。
Java Transaction API (JTA)
管理多个资源(如数据库或消息服务)的事务处理。
Java Transaction API (JTA) 是一个 Java EE API,它允许应用程序执行跨多个资源(如数据库和消息服务)的分布式事务处理。JTA 是一个高级的事务管理接口,它抽象了底层的事务处理机制,提供统一的方法来控制事务的开始、提交和回滚。
JTA 的主要特性
- 分布式事务:JTA 支持分布式事务,这意味着事务可以跨多个网络分布的资源。例如,一个事务可能涉及两个数据库和一个消息队列。
- 事务管理器:JTA 定义了一个事务管理器,它是负责协调资源和管理事务边界的中心实体。
- 资源管理器:资源管理器是实际控制如数据库或JMS服务器资源的实体。JTA 通过资源管理器与这些资源进行交互。
- 两阶段提交:JTA 事务通常使用两阶段提交协议,以确保所有参与的资源都同意事务的最终结果。这是确保数据完整性和一致性的关键。
JTA 的工作流程
- 开始事务:事务管理器开始一个新的事务。
- 业务操作:应用程序执行涉及一个或多个资源(如数据库操作、消息发送等)的业务操作。
- 阶段一:准备:事务管理器询问所有参与的资源管理器是否可以提交事务。每个资源管理器都会锁定在此事务中涉及的资源并准备提交。
- 阶段二:提交/回滚:
- 如果所有资源管理器都准备好提交,事务管理器指示它们提交事务。
- 如果任何一个资源管理器无法准备好提交,事务管理器将指示所有资源管理器回滚事务。
使用 JTA 的场景
- 企业级应用:在需要确保数据完整性和一致性的企业级应用中,尤其是涉及多个数据库或者需要与其他企业系统集成时。
- 高可靠性系统:在金融服务、电子商务、供应链管理等领域,事务必须准确无误,因此需要强大的事务管理支持。
示例代码
在 Java EE 环境中,使用 JTA 通常不需要开发者直接与 JTA API 交互,因为容器(如 WildFly, WebLogic 等)提供了对事务的自动管理。但如果需要,可以手动管理事务,例如:
import javax.transaction.UserTransaction;@Resource
private UserTransaction utx;public void executeTransaction() {try {utx.begin();// 执行数据库操作database.updateSomething();// 执行其他资源操作jms.sendSomeMessage();utx.commit();} catch (Exception e) {try {utx.rollback();} catch (Exception ex) {ex.printStackTrace();}e.printStackTrace();}
}
在上面的例子中,UserTransaction 用于明确开始、提交或回滚事务。这种方式给开发者提供了对事务控制的显式管理。
总结
JTA 提供了一个强大的机制,用于管理复杂的分布式事务。通过抽象底层的事务处理细节,JTA 允许开发者专注于业务逻辑,同时确保数据的一致性和完整性。在 Java EE 应用程序中,JTA 是处理事务性操作的标准方法,尤其是在涉及多个后端资源时。
JavaMail
在Java应用程序中集成电子邮件服务的API。
JavaMail 是一个为发送和接收电子邮件提供支持的 Java API,它定义了一套可用于构建邮件客户端的标准类和接口。JavaMail API 是独立于协议的,尽管它主要用于通过 SMTP(用于发送邮件)、POP3(用于接收邮件)、和 IMAP(用于接收邮件)协议与邮件服务器进行交互。
JavaMail 的核心组件
- Session:代表邮件会话,包含与邮件服务器交互所需的配置信息。
- Message:代表一封电子邮件,可以包含文本、附件等内容。
- Transport:用于发送邮件的类。
- Store:用于从邮件服务器接收邮件的类。
JavaMail 的主要特性
- 灵活性:JavaMail API 支持扩展,可以使用任何邮件协议(如 SMTP, POP3, IMAP)。
- 易用性:API 提供了简单的方法来发送和接收邮件,使得开发邮件相关的应用变得容易。
- 功能丰富:支持创建、发送、接收和解析邮件,包括多部分内容和附件。
示例代码:发送简单的电子邮件
下面是一个使用 JavaMail API 发送简单电子邮件的示例。这个例子假设你已经有一个可用的 SMTP 服务器。
import javax.mail.*;
import javax.mail.internet.*;
import java.util.Properties;public class SendEmail {public static void main(String[] args) {// 设置邮件服务器Properties props = new Properties();props.put("mail.smtp.host", "smtp.example.com"); // SMTP Hostprops.put("mail.smtp.port", "587"); // TLS Portprops.put("mail.smtp.auth", "true"); // Enable Authenticationprops.put("mail.smtp.starttls.enable", "true"); // Enable StartTLS// 创建会话Session session = Session.getInstance(props, new javax.mail.Authenticator() {protected PasswordAuthentication getPasswordAuthentication() {return new PasswordAuthentication("username", "password");}});try {// 创建邮件消息Message message = new MimeMessage(session);message.setFrom(new InternetAddress("from@example.com"));message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("to@example.com"));message.setSubject("Test Subject");message.setText("Hello, this is a test email!");// 发送邮件Transport.send(message);System.out.println("Mail sent successfully!");} catch (MessagingException e) {e.printStackTrace();}}
}
JavaMail 在实际应用中的使用
JavaMail 被广泛用于需要邮件功能的企业应用中,包括:
- 自动发送通知邮件。
- 开发邮件客户端应用程序。
- 集成邮件功能到企业应用中,如自动订单确认邮件。
总结
JavaMail API 提供了一个功能强大、灵活且易于使用的平台,以编程方式发送和接收邮件。它支持丰富的内容类型,包括纯文本邮件和带附件的复杂邮件。对于需要集成邮件功能的 Java 应用程序,JavaMail 是一个理想的选择。
安全性
-
Java Authentication and Authorization Service (JAAS)
用于Java应用程序的安全框架,支持用户认证和授权。
Java Authentication and Authorization Service (JAAS) 是一个 Java SE 安全技术,用于对用户进行认证(Authentication)和授权(Authorization)。JAAS 提供了一种灵活的、独立于平台的方式,允许 Java 应用程序在保持安全的同时,对用户进行身份验证和权限控制。这种机制使得 Java 应用能够在多种认证技术(如用户名/密码、智能卡等)之间进行选择和扩展。
JAAS 的关键概念
-
认证(Authentication):
- 认证是确定某个实体(通常是用户)的身份的过程。JAAS 通过
LoginModule接口实现认证。应用程序可以通过使用不同的LoginModule来支持不同类型的认证机制。
- 认证是确定某个实体(通常是用户)的身份的过程。JAAS 通过
-
授权(Authorization):
- 授权是在认证成功后,决定用户可以访问的资源和操作的过程。JAAS 使用
Principal(身份标识)和权限集合(权限)来进行授权。
- 授权是在认证成功后,决定用户可以访问的资源和操作的过程。JAAS 使用
-
主体(Principal):
- 在 JAAS 中,主体是一个标识符,用于表示一个个体(如用户或用户组)。主体通常通过登录过程被验证其身份。
-
策略(Policy):
- JAAS 使用安全策略来控制对资源的访问。策略定义了哪些主体可以执行哪些操作。
JAAS 认证流程
-
应用程序调用
LoginContext类:LoginContext是 JAAS 认证的起点,负责协调不同的LoginModule。
-
加载配置的
LoginModule:- 应用程序在 JAAS 配置文件中指定了使用哪些
LoginModule。每个模块可以独立地尝试认证用户,例如,通过用户名和密码、指纹识别等方式。
- 应用程序在 JAAS 配置文件中指定了使用哪些
-
尝试认证:
- 每个
LoginModule尝试验证用户的凭据。如果某个模块成功验证用户,则认证过程可以继续或结束,取决于配置文件中的选项。
- 每个
-
提交或回滚:
- 如果认证成功,
LoginContext将调用每个LoginModule的commit方法,允许它们将相关的主体和凭据添加到Subject中。 - 如果认证失败,则调用
abort方法来清理状态。
- 如果认证成功,
JAAS 授权流程
- 在认证成功后,
Subject被填充了认证的主体和凭证信息。当应用程序需要执行受保护的操作时,它将检查Subject是否拥有执行该操作的足够权限。
示例代码
以下是使用 JAAS 进行认证的简单示例代码:
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;public class JaasAuthentication {public static void main(String[] args) {try {// 创建 LoginContext,"MyLoginConfig" 是 JAAS 配置文件中的配置名LoginContext lc = new LoginContext("MyLoginConfig");// 尝试登录lc.login();System.out.println("Authentication successful.");} catch (LoginException e) {System.out.println("Authentication failed: " + e.getMessage());}}
}
总结
JAAS 提供了一个强大的框架,用于在 Java 应用程序中实现认证和授权。它的设计允许开发者插入自定义的认证技术,同时提供了一套完善的方法来控制对资源的访问。这使得 JAAS 成为 Java 安全体系中非常关键的一部分,广泛应用于需要严格安全控制的企业级应用程序。
Web服务
-
JAX-RS (Java API for RESTful Web Services)
支持REST风格Web服务的创建。
JAX-RS(Java API for RESTful Web Services)是一套用于开发遵循REST架构风格的Web服务的Java编程语言API。JAX-RS是Java EE的一部分,其目的是提供一个易于使用的方式来开发轻量级的Web服务。通过使用JAX-RS,开发者可以快速构建基于HTTP协议的Web服务,这些服务可以输出和接受XML、JSON等多种格式的数据。
JAX-RS的核心组件
-
资源类(Resource Classes):
- 资源类是带有
@Path注解的POJO(Plain Old Java Object),用于处理Web服务的特定资源。
- 资源类是带有
-
HTTP方法注解:
- JAX-RS提供了一系列注解来表示HTTP请求方法,如
@GET、@POST、@PUT、@DELETE等,这些注解用于资源类的方法上,表明该方法应响应哪种HTTP方法。
- JAX-RS提供了一系列注解来表示HTTP请求方法,如
-
路径和参数注解:
@Path用于指定资源的URI。@PathParam、@QueryParam、@HeaderParam等注解用于将HTTP请求中的参数映射到资源方法的参数上。
-
响应构建:
- JAX-RS中,可以通过
Response类构建HTTP响应,包括状态码、响应头和响应体。
- JAX-RS中,可以通过
-
异常处理:
- 通过
ExceptionMapper接口可以处理应用中未捕获的异常,返回适当的HTTP响应。
- 通过
开发JAX-RS应用
开发一个JAX-RS应用通常涉及以下步骤:
-
创建资源类:
- 定义一个类,并使用
@Path注解标注以指定基础URI。 - 在类中定义方法,并使用
@GET、@POST等注解来处理对应的HTTP请求。
- 定义一个类,并使用
-
部署应用:
- 在Java EE容器中部署应用,如使用Tomcat、WildFly等服务器。JAX-RS应用可以打包为WAR文件进行部署。
示例代码
以下是一个简单的JAX-RS示例,展示了一个处理HTTP GET请求的资源类:
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;@Path("/hello")
public class HelloResource {@GET@Produces(MediaType.TEXT_PLAIN)public String getHello() {return "Hello, JAX-RS!";}
}
在这个例子中,HelloResource类定义了一个处理对/hello路径GET请求的方法。@Produces注解指定了返回内容的MIME类型。
总结
JAX-RS是开发RESTful Web服务的强大工具,其注解驱动的方法简化了Web服务的开发过程。通过JAX-RS,开发者可以轻松创建支持多种数据格式的Web API,并可以在多种Java EE兼容的应用服务器上运行。JAX-RS也支持客户端API,使得从Java客户端程序调用RESTful服务变得简单。这使得JAX-RS成为构建现代Web应用程序和微服务架构的理想选择。
-
JAX-WS (Java API for XML Web Services)
支持SOAP风格Web服务的创建。
JAX-WS(Java API for XML Web Services)是用于创建遵循SOAP(Simple Object Access Protocol)标准的Web服务的一套Java API。它是JAX-RPC(Java API for XML-Based RPC)的后续版本,提供了一个方便的方法来开发和发布Web服务以及创建Web服务客户端。JAX-WS支持SOAP 1.1、SOAP 1.2和XML消息的传输,并能处理WSDL(Web Services Description Language)文件来描述网络服务。
JAX-WS的核心功能
-
SOAP Web服务支持:
- JAX-WS允许开发者通过Java编程语言构建基于SOAP的服务,这些服务可以通过网络交换XML格式的数据。
-
WSDL支持:
- 通过JAX-WS,服务定义可以通过WSDL文档自动产生,也可以从现有的WSDL创建服务。
-
注解简化开发:
- JAX-WS使用Java注解简化了Web服务的开发,这些注解用于绑定Java类和方法到WSDL文件。
-
消息处理器:
- JAX-WS允许插入自定义的消息处理器,用于在SOAP消息传输过程中进行监控或修改。
-
客户端API:
- JAX-WS提供了一个客户端API,使得生成和调用Web服务的客户端代码变得简单。
开发JAX-WS Web服务
开发一个JAX-WS Web服务通常涉及以下步骤:
-
定义服务接口:
- 使用
@WebService注解标记一个接口或类,将其定义为一个Web服务。
- 使用
-
实现服务接口:
- 实现上述接口,使用
@WebMethod注解标记服务操作。
- 实现上述接口,使用
-
部署Web服务:
- 在Java EE服务器上部署Web服务,如GlassFish、WildFly等,这些服务器提供了对JAX-WS的内置支持。
示例代码
以下是一个简单的JAX-WS Web服务示例:
import javax.jws.WebService;
import javax.jws.WebMethod;@WebService
public class CalculatorService {@WebMethodpublic int add(int a, int b) {return a + b;}
}
在这个示例中,CalculatorService类定义了一个Web服务,其中包含一个名为add的方法,用于执行加法运算,该方法通过网络可被远程调用。
发布Web服务
对于开发完成的Web服务,还需要进行发布,以便可以被远程访问。这通常在部署到服务器上后自动完成,服务器会为Web服务生成WSDL文件,客户端可以通过这个WSDL了解如何与服务交互。
总结
JAX-WS是一个强大的API,用于在Java环境中创建和部署基于SOAP的Web服务。它提供了完整的支持,从服务的创建到客户端的生成,都可以利用Java的注解和简便的API来实现。JAX-WS特别适用于需要严格的服务定义和复杂交互的企业级应用,而且它支持Web服务的标准和协议,保证了广泛的兼容性和互操作性。
其他API和组件
-
Contexts and Dependency Injection (CDI)
一种依赖注入机制,用于在运行时管理对象的依赖关系,增强模块间的解耦。
Contexts and Dependency Injection (CDI) 是 Java EE 现在被称为 Jakarta EE 的核心规范之一,它为企业级 Java 应用提供了一种类型安全的依赖注入机制。CDI 的设计目的是简化企业应用的开发,通过提供一致的方法来管理服务的生命周期,处理依赖注入(DI),并实现不同组件之间的松耦合。
CDI 的主要特点
-
依赖注入:
- CDI 支持基于类型的依赖注入。开发者可以通过注解将类标记为可被注入的候选者,并在需要时自动由容器注入。
-
上下文管理:
- CDI 管理不同的上下文(例如请求、会话、应用),并确保组件在其生命周期内正确地创建和销毁。
-
事件处理:
- CDI 提供了一个事件模型,允许组件观察和响应应用内的事件,从而促进了组件之间的解耦。
-
类型安全:
- CDI 使用类型安全的方法来处理注入和事件,提供编译时检查,避免运行时的类型错误。
-
拦截器和装饰器:
- 支持拦截器和装饰器模式,使得在不修改现有类代码的情况下,增强类的行为成为可能。
-
扩展机制:
- CDI 容器可以通过 SPI(服务提供接口)被扩展,允许开发者自定义容器的行为。
CDI 中的核心注解
@Inject:标记在类的构造函数、方法或字段上,用于注入依赖。@Produces:标记在方法上,表明该方法用于生产可以被注入的对象。@Qualifier:用于区分同一类型的不同实现。@Scope:标记在类上,定义了被注解的bean的生命周期(如@RequestScoped,@SessionScoped,@ApplicationScoped)。@Named:提供一个可在 EL 表达式中引用的名字,用于解耦 Java 代码和 UI 模板。
示例代码
下面是一个使用 CDI 的简单示例,展示了依赖注入和作用域的使用:
import javax.inject.Inject;
import javax.enterprise.context.SessionScoped;
import java.io.Serializable;@SessionScoped
public class ShoppingCart implements Serializable {private List<Item> items = new ArrayList<>();@Injectprivate ItemService itemService;public void addItemById(String itemId) {Item item = itemService.findItemById(itemId);if (item != null) {items.add(item);}}// Getter 和 Setter
}
集成和使用
CDI 在 Java EE 和 Jakarta EE 环境中是自动启用的。在 Java SE 或者轻量级容器中,如Tomcat中使用CDI时,可能需要额外的设置或集成第三方库(如Weld)。
总结
CDI 提供了一个强大的框架,用于管理依赖注入和组件生命周期,极大地简化了 Java EE 应用的开发。通过它的使用,开发者可以更容易地编写可测试、可维护和松耦合的代码。CDI 的事件模型和拦截器机制也提供了额外的灵活性,用于处理跨应用程序的交互和业务逻辑的增强。
-
Bean Validation
一种用于对Java Beans进行约束验证的API。
Bean Validation 是 Java 平台的一个规范,旨在提供一种标准化的方法来验证 JavaBeans 的数据约束。这个 API,通常指的是 Jakarta Bean Validation(之前称为 Java Bean Validation),定义了一套简单且可扩展的约束声明和验证规则,可以应用于 Java 对象上,从而确保这些对象的数据满足业务规则的要求。
核心特点
- 标准化:Bean Validation 是一个标准的 Java API,可以与 JPA, JAX-RS, JSF 等 Java EE/Jakarta EE 技术无缝集成。
- 注解驱动:使用注解来声明约束,使得代码易于阅读和维护。
- 可扩展性:除了内置的标准约束外,还可以定义自己的约束。
- 自动和手动验证:支持在不同层自动验证 JavaBeans,也可以在需要时手动触发验证。
常用的约束注解
Bean Validation 提供了一系列的内置约束注解,包括:
@NotNull:确保字段不是 null。@Min和@Max:验证数字值的范围。@Size:验证元素(如字符串、集合)的大小。@Pattern:确保字符串值匹配一个正则表达式。@Email:验证字符串是一个格式有效的电子邮件地址。@Positive和@PositiveOrZero:验证数值是正数或零。@Negative和@NegativeOrZero:验证数值是负数或零。
验证过程
- 定义约束:在 JavaBean 属性或类上使用注解来定义约束。
- 触发验证:在应用的业务逻辑中,可以通过验证引擎手动触发验证,或者在某些框架中(如 JPA 或 Spring)自动进行。
- 处理验证结果:验证过程可以产生一系列的约束违规,开发者需要相应地处理这些错误,例如,向用户显示错误消息。
示例代码
下面是一个使用 Bean Validation 注解的简单 JavaBean 示例:
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;public class User {@NotNull(message = "Name cannot be null")@Size(min = 2, max = 100)private String name;@Min(value = 18, message = "Age must be greater than or equal to 18")private int age;// 构造函数、getter 和 setter 省略
}
集成和使用
Bean Validation 可以集成到任何使用 JavaBeans 的 Java 应用中。在 Java EE 环境中,这通常是自动配置的;在 Spring Framework 中,可以通过配置类或 XML 来启用 Bean Validation 支持。
例如,在一个 JAX-RS 应用中,Bean Validation 可以自动应用于传入的请求实体,无需任何额外配置:
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.validation.Valid;@Path("/users")
public class UserController {@POSTpublic Response addUser(@Valid User user) {// 如果 User 对象中的数据不满足注解定义的约束,这里不会执行// 处理 user 存储逻辑return Response.ok().build();}
}
总结
Bean Validation 是一个强大的工具,用于在 Java 应用程序中实现数据有效性检验。通过其注解驱动的方式,开发者可以方便地在各个层次上应用一致的验证逻辑,保证数据的准确性和业务规则的一致性。
Java EE的这些组件和API共同构成了一个强大的平台,使得开发者能够构建处理大量数据和交易、需要高度安全和可靠性的企业级应用程序。从Java EE 8开始,该平台逐渐过渡到了由Eclipse Foundation管理的Jakarta EE,以保持开源生态系统的持续发展。
相关文章:
Java EE/Jakarta EE范畴一览
Java EE(Java Platform, Enterprise Edition)现在已经改名为Jakarta EE,是一套用于开发企业级应用的标准Java平台。它扩展了Java SE(Standard Edition),添加了支持大规模、多层次、可靠、安全、可伸缩和可管…...
洛谷 P3391:文艺平衡树 ← Splay树模板题
【题目来源】https://www.luogu.com.cn/problem/P3391【题目描述】 您需要写一种数据结构(可参考题目标题),来维护一个有序数列。 其中需要提供以下操作:翻转一个区间,例如原有序序列是 5 4 3 2 1,翻转区间…...
【高校科研前沿】北师大陈晋教授团队在遥感顶刊发表最新成果:ClearSCD模型:在高空间分辨率遥感影像中综合利用语义和变化关系进行语义变化检测
01文章简介 论文名称:The ClearSCD model: Comprehensively leveraging semantics and change relationships for semantic change detection in high spatial resolution remote sensing imagery(ClearSCD模型:在高空间分辨率遥感影像中综合…...
关于YOLO8学习(五)安卓部署ncnn模型--视频检测
教学视频地址 B站 前文 关于YOLO8学习(一)环境搭建,官方检测模型部署到手机 关于YOLO8学习(二)数据集收集,处理 关于YOLO8学习(三)训练自定义的数据集 关于YOLO8学习(四)模型转换为ncnn 简介 本文将会讲解: (1)使用前文生成的ncnn模型,部署到安卓端,并且实…...
从哪些方面可以看出光伏的未来发展好?
光伏发电是一种基于半导体材料的光伏效应将太阳光转化为直流电能的发电技术。近年来,随着全球对可再生能源和环境保护的关注度不断提升,光伏发电行业发展迅速,成为未来能源领域的重要发展方向。 首先,从能源角度来看,光…...
VBA_MF系列技术资料1-605
MF系列VBA技术资料1-605 为了让广大学员在VBA编程中有切实可行的思路及有效的提高自己的编程技巧,我参考大量的资料,并结合自己的经验总结了这份MF系列VBA技术综合资料,而且开放源码(MF04除外),其中MF01-0…...
算法题① —— 数组专栏
1. 滑动窗口 1.1 长度最小的子数组 力扣:https://leetcode.cn/problems/minimum-size-subarray-sum/description/ int minSubArrayLen(int s, vector<int>& nums) {int result INT32_MAX; int sum 0; // 子序列的数值之和int subLength 0; // 子序列…...
算法学习笔记(差分约束系统)
前置:spfa 从例题入手: 【模板】差分约束系统 | StarryCoding 题目描述 给定 n n n未知量和一个大小为 m m m的不等式(或等式)组,请你判断这个不等式(或等式)组是否有解。 1 1 1 i i i j …...
HCIP的学习(14)
过滤策略—filter-policy 思科中:分发列表 过滤策略是只能够针对于路由信息进行筛选(过滤)的工具,而无法针对于LSA进行过滤。 在R4的出方向上配置过滤策略,使得R1不能学习到23.0.0.0/24路由信息1、抓取流量 […...
行业新应用:电机驱动将成为机器人的动力核心
电机已经遍布当今社会人们生活的方方面面,不仅应用范围越来越广,更新换代的速度也日益加快。按照工作电源分类,可以将它划分为直流电机和交流电机两大类型。直流电机中,按照线圈类型分类,又可以分为有铁芯的电机、空心…...
大模型模型简化机器人训练;简单易用的 3D 工具Project Neo;特斯拉放出了擎天柱机器人最新训练视频
✨ 1: DrEureka 利用大语言模型自动化将机器人仿真环境训练结果转移到真实世界 DrEureka是一种利用大型语言模型(LLMs)自动化和加速从仿真(sim)到现实世界(real)转移的技术。在机器人技能学习领域&#x…...
Win11安装Docker Desktop运行Oracle 11g 【详细版】
oracle docker版本安装教程 步骤拉取镜像运行镜像进入数据库配置连接数据库,修改密码Navicat连接数据库 步骤 拉取镜像 docker pull registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g运行镜像 docker run -d -p 1521:1521 --name oracle11g registry.cn-ha…...
分布式事务?哪几种方式实现?一文看懂!
什么是分布式事务 分布式事务是指在分布式系统中涉及到多个数据库或多个应用程序之间的事务处理,这些数据库或应用程序可能分布在不同的物理节点上,甚至可能位于不同的地理位置。在分布式事务中,需要确保所有参与者的事务操作都能够保持一致性…...
词令蚂蚁庄园今日答案如何在微信小程序查看蚂蚁庄园今天问题的正确答案?
词令蚂蚁庄园今日答案如何在微信小程序查看蚂蚁庄园今天问题的正确答案? 1、打开微信,点击搜索框; 2、打开搜索页面,选择小程序搜索; 3、在搜索框,输入词令搜索点击进入词令微信小程序; 4、打开…...
【Delphi 爬虫库 6】使用正则表达式提取猫眼电影排行榜top100
正则表达式库的简单介绍 正则表达式易于使用,功能强大,可用于复杂的搜索和替换以及基于模板的文本检查。这对于输入形式的用户输入验证特别有用-验证电子邮件地址等。您还可以从网页或文档中提取电话号码,邮政编码等,在日志文件中…...
Markdown和Latex中文字上下标的方法
技术背景 在Markdown和Latex中,如果只是写公式,不论是行内公式还是行间公式,都可以直接使用^和_这两个符号实现上下标。但有个问题是,如果只是使用公式来做上下标,出来的字体是斜着的。例如这样的语法: $$ …...
VSCode:设置顶部文件标签页滚动条的宽度
使用VSCode打开多个文件后,顶部的文件标签可以通过滚动条进行滚动,但是缺点是该滚动条太窄了,不好选择。 可以通过如下方法修改改滚动条的宽度: 1.点击设置 2.选择工作台->编辑管理->Title Scrollbar Sizing->Large 3.可…...
MySQL变量的定义与使用
# 关系运算 select x < y as 大小判断;# 返回结果1代表true,如果是0代表false select x > y; # 逻辑运算 select TRUE and FALSE;# 依然符合&(and)与、|(or)或、^(xor)亦或。 select …...
python-pytorch seq2seq+attention笔记0.5.00
python-pytorch seq2seq+attention笔记0.5.00 1. LSTM模型的数据size2. 关于LSTM的输入数据包含hn和cn时,hn和cn的size3. LSTM参数中默认batch_first4. Attention机制的三种算法5. 模型的编码器6. 模型的解码器7. 最终模型8. 数据的准备9. 遇到的问题10. 完整代码1. LSTM模型的…...
ansible 深入介绍之 主机清单与playbook
目录 一 inventory 主机清单 1,主机清单 是什么 2,主机清单 定义方式 2.1 自定义主机端口 2.2 定义 范围ip 地址 2.3 定义 拥有相似的主机名 3, inventory 中的变量 3.1 常见 变量 3.2 主机变量 3.3 组变量 3.…...
STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...
解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...
Spring AOP代理对象生成原理
代理对象生成的关键类是【AnnotationAwareAspectJAutoProxyCreator】,这个类继承了【BeanPostProcessor】是一个后置处理器 在bean对象生命周期中初始化时执行【org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization】方法时…...
数据分析六部曲?
引言 上一章我们说到了数据分析六部曲,何谓六部曲呢? 其实啊,数据分析没那么难,只要掌握了下面这六个步骤,也就是数据分析六部曲,就算你是个啥都不懂的小白,也能慢慢上手做数据分析啦。 第一…...
Android屏幕刷新率与FPS(Frames Per Second) 120hz
Android屏幕刷新率与FPS(Frames Per Second) 120hz 屏幕刷新率是屏幕每秒钟刷新显示内容的次数,单位是赫兹(Hz)。 60Hz 屏幕:每秒刷新 60 次,每次刷新间隔约 16.67ms 90Hz 屏幕:每秒刷新 90 次,…...
深入理解 C++ 左值右值、std::move 与函数重载中的参数传递
在 C 编程中,左值和右值的概念以及std::move的使用,常常让开发者感到困惑。特别是在函数重载场景下,如何合理利用这些特性来优化代码性能、确保语义正确,更是一个值得深入探讨的话题。 在开始之前,先提出几个问题&…...
java 局域网 rtsp 取流 WebSocket 推送到前端显示 低延迟
众所周知 摄像头取流推流显示前端延迟大 传统方法是服务器取摄像头的rtsp流 然后客户端连服务器 中转多了,延迟一定不小。 假设相机没有专网 公网 1相机自带推流 直接推送到云服务器 然后客户端拉去 2相机只有rtsp ,边缘服务器拉流推送到云服务器 …...
Python打卡训练营学习记录Day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
