StudyTonight-Spring-中文教程-一-

StudyTonight Spring 中文教程(一)

原文:StudyTonight

协议:CC BY-NC-SA 4.0

Spring

Spring 核心

Spring 简介

原文:https://www.studytonight.com/spring-framework/spring-introduction

Spring 是一个基于 Java 的应用框架,由 Pivotal 软件公司设计和开发。

在本教程中,我们将讨论 Spring 5 ,它是传统 Spring 框架的最新和更改进的版本。

Spring 是一个用于创建企业应用的应用框架。由于其庞大的库和工具,我们可以轻松创建基于网络的应用。

Spring 为创建 Java 企业应用提供了一个简单友好的环境。它是功能齐全的,并提供了其他各种子项目,如 Spring SecuritySpring BootSpring MVCSpring CloudSpring Data 等,有助于相应地构建应用。

随着时间的推移,Spring 5 得到了改进,在 Java EE 和 Spring 的早期,我们将应用部署到应用服务器上,但是现在在 Spring Boot 的帮助下,我们可以以 DevOps 和云友好的方式创建应用。

Spring 的核心和核心是一个 IOC 容器,它管理 bean 对象并允许依赖注入。我们将在后面的教程中讨论这些。

Spring 内置了多个组件(模块)与 web数据库网络等协同工作。下面是 Spring Runtime 的图片,展示了它的内部架构。

Spring 框架架构

在下图中,我们展示了 Spring 框架架构:

spring framework architecture

Spring 模块

Spring 框架根据其服务分为几个模块。这些模块是:

  • Spring 核心容器:它是 Spring 的核心模块,提供了 BeanFactory 和 ApplicationContext 这样的容器。

  • 控制反转:又称依赖注入,用于配置应用组件和 Java 对象的生命周期管理。

  • 面向方面编程:该模块支持在 Spring 框架内实现跨领域的关注点,如事务管理、远程访问等。

  • 数据访问:它通过使用 Java 数据库连接(JDBC)和 ORM(对象关系映射)工具来帮助处理数据库系统。

  • 模型视图控制器:它也被称为 MVC 模型,有助于创建基于 web 的应用和 RESTful Web 服务。

  • 认证授权:使用 Spring Security(Spring 的子项目)在框架内配置安全流程。

  • 消息传递: Spring 使用消息监听器对象,通过使用 JMS (Java 消息服务)来传递消息,这是对 JMS API 的改进。

  • 事务管理:它由几个事务管理 API 组成,为 Java 对象协调事务。

  • 远程管理:使用 Java 管理扩展(JMX)为本地或远程配置 Java 对象很有帮助。

  • 测试:测试模块,帮助编写单元测试和集成测试。

Spring 5 更新

  • 它要求最低 Java 版本是 Java 8 或更高。

  • 不推荐使用一些集成:平铺、加瓦瓦、速度、肖像等。

  • Spring MVC 升级为使用 Servlet API 4.0

  • 支持新的反应式编程框架: Spring WebFlux

《Spring》的历史和版本

下表包含相应年份的 Spring Framework 版本。它的第一个版本于 2002 年 10 月 1 日发布。

| 版本 | 日期(年) |
| Zero point nine | 2002 年 10 月 |
| One | 2003 年 6 月 |
| Two | 2006 年 |
| Three | 2009 年 12 月 |
| Four | 2013 年 12 月 |
| Five | 2017 年 9 月 |



Spring 特性

原文:https://www.studytonight.com/spring-framework/spring-features

Java Spring Framework 功能丰富,提供并帮助创建基于 Java 的可扩展应用。这里,我们讨论一些特性。尽管这些并不局限于此,因为 spring 提供了数十种不同的项目,如 Spring Data、Spring Cloud、Spring Boot 等。以下是 Spring 框架的特性。

  • 灵活的

  • 多产的

  • 快的

  • 安全的

  • 支持的

  • 到处

spring features

图:Spring 特性

Spring 无处不在

Spring 是全球最受欢迎的框架之一。它用于 Java 中的企业应用开发。我们可以用它来创建 web 服务、web 应用、基于云的服务等。谷歌、阿里巴巴、亚马逊、甲骨文等世界科技组织都在使用它。全世界的 Java 开发人员都信任 Spring 的库。无论是流媒体电视、连接物联网、电子商务应用、银行等,它几乎无处不在。

Spring 是柔性的

Spring 提供了灵活的第三方库和扩展,帮助开发人员构建应用。控制的反转(IoC)依赖注入(DI) 是 Spring 的主要特性,使其能够灵活地创建企业应用。Spring 提供了几个工具来帮助开发人员为 web 构建安全的、反应性的和基于云的微服务,甚至您可以将其用于企业应用的复杂流数据流。

Spring 是多产的

毫无疑问,Spring 是一个高效的框架,在添加了 Spring Boot 项目之后,Spring 框架已经转变为一个更高效的框架。Spring Boot 结合了所有的必需品和自动配置的设置。它有一个嵌入式 webserver,可以加快微服务的开发速度。最重要的是集成有助于连续创建应用的 spring 项目。例如,创建一个它提供框架的应用,连接它提供 Spring Data 的数据库,使用 Cloud,它提供 Spring cloud,为了安全,它提供 Spring Security 性。因此,我们需要做的就是根据需求将它们放入我们的应用中,这样我们的应用就准备好了。

Spring 很快

由于其设计和架构,Spring 框架的性能是超级。Spring foundation 专注于为应用提供在起点快速启动、稳定执行和快速关闭的性能。为了获得更好的性能和效率,Spring 项目支持反应式编程模型。Spring 提供了 Spring Initializer 工具来快速启动应用。Spring Boot 已经配备了嵌入式网络服务器等工具,自动配置有助于开发人员轻松构建应用。在 Spring 开发工具中添加 LiveReload 消除了服务器重启的问题和需要。

Spring 是安全的

Spring 本身是安全的,Java 语言也提供了安全性,但是为了更安全,我们可以使用 Spring Security 。Spring Security 是 Spring 的项目之一,旨在处理任何 Spring 应用的安全性。由于它是 Spring 框架的一部分,因此很容易与应用集成。Spring 快速处理和处理安全问题并加以处理。它密切监控第三方依赖关系,并定期更新以确保我们的数据和应用的安全。

Spring 是支持的

Spring 为全球所有的开发者提供了一个庞大的、全球性的、庞大的、多样的社区。Spring 为所有人提供支持,不管你住在哪里,也不管你的知识水平如何。它有助于所有年龄和能力,从完全初学者到行业专家。Spring 社区提供了各种各样的资源,如视频、指南、教程、会议、支持,甚至是正式的培训和认证。



Spring 环境设置

原文:https://www.studytonight.com/spring-framework/spring-environment-setup

要为 Spring Framework 建立一个开发环境,我们需要以下工具:

  • 安装 Java

  • 安装 Eclipse

  • 安装 Tomcat 服务器

  • 下载 Spring JARs

components of spring

因此,让我们在本地系统中下载并安装这些工具,以便成功执行 Spring 应用。

第一步:安装 Java

Java 是一种编程语言,Spring 框架使用它来创建应用。所以我们的第一个任务是在我们的计算机上安装 Java并设置它的类路径。关于 Java 语言的更多信息,你可以阅读我们的 Java 教程

步骤 2:下载并安装 Eclipse

Eclipse 是一个集成开发环境,用于软件开发。它提供了一个在单一位置构建应用的平台。我们可以使用它的控件来处理多种工具。

要下载月食,访问月食官方网站下载即可。下载 Zip 文件后,解压安装。

setup eclipse for spring installation

安装 Eclipse 时,确保 Java 已经安装了及其类路径,因为 Eclipse 在安装期间选择了 JVM 路径。****

步骤 3:下载 Tomcat 服务器

Tomcat 是一个允许在本地机器上测试 web 应用的服务器。在这里,我们将使用它来测试我们的 Spring 应用。我们可以从阿帕奇基金会官方网站下载。下载后,提取它,我们将使用它在服务器上运行应用。

spring setup - tomcat server installation

我们建议您下载 Tomcat 服务器的第 9 版。

步骤 4:下载 Spring JARs

为了使用 Spring 框架,我们必须有 Spring JARs,它们基本上是 Java 文件,包含包、类和接口来创建 Spring 应用。

有两种方法可以得到这些 JARs。要么从 Spring 官方网站下载它们并放入 Spring 项目中,要么创建一个 Maven 项目,它会自动将这些 JARs 下载到您的项目中。

如果你想直接下载这些 JARs,那么点击这里下载 Spring JARs 访问 Spring 的官方库。从那里挑选最新的 JARs,提取它们,并把它们放到 Spring 项目的 lib 文件夹中。

完成以上所有步骤之后,现在我们可以使用 Eclipse IDE 创建一个 Spring 应用了。在下一个主题中,我们将创建一个 Spring 应用



Spring Maven 项目

原文:https://www.studytonight.com/spring-framework/spring-maven-project

在本主题中,我们将学习创建一个基于 Spring 项目的简单 maven 。Maven 是一个自动化工具,它充当 Java 应用的依赖关系管理器。

因此,让我们从创建一个简单的项目开始,但在此之前,请确保您已经为 Spring 设置了开发环境并安装了 Eclipse、 Java 和 Apache Tomcat 服务器。

如果您还没有设置环境,那么我们建议您阅读我们的前一个主题

步骤 1:创建 Maven 项目

打开 Eclipse,点击文件菜单,然后选择新建- >马文项目,就像我们在给定截图中所做的那样。

first spring project using maven

选择 maven 后,它会打开如下所示的窗口,并要求选择原型。在这里,我们点击复选框,然后按下下一个按钮。

first spring project using maven

步骤 2:配置项目

通过提供组 id 和工件 id 来设置项目名称。工件 id 代表项目名称,所以在此之后给你的项目取一个有意义的名称,选择指定在每个 Maven 构建阶段执行的插件目标的打包。之后按完成按钮,你的 maven 项目就准备好了。

first spring project using maven

maven 项目结构

经过上面的步骤,Eclipse 创建了一个新项目,看起来像下面的 screeshot。该项目包含一个 pom.xml 文件,用于配置 maven 项目。我们将在后面的教程中讨论这个问题。

first spring project using maven

好吧,到目前为止,我们已经成功地创建了一个基于 maven 的 spring 项目。现在,在下一章中,我们将学习创建一个简单的 hello world 应用来了解应用的流程和结构。



使用 STS 的 Spring 项目

原文:https://www.studytonight.com/spring-framework/spring-project-using-sts

在本文中,我们将使用 STS 工具创建一个 Spring 项目。STS (Spring 工具套件)是由 Spring 基金会提供的官方 IDE。我们可以用它来创建 spring 应用。它类似于日蚀,如果你熟悉日蚀,那么你会发现它非常容易使用。让我们从下载 STS 开始,然后创建应用。

要下载 STS,您可以访问 Spring 的官方网站,或者只需使用此链接(下载 STS) 。下载后将其安装到您的本地系统,然后运行。

创建 Spring 项目

要创建 Spring 项目,点击文件菜单,选择项目,进一步弹出几个项目类型,如 Maven 项目、动态项目、Java 项目等。选择 maven 项目是因为我们使用了基于 Maven 的 spring 项目。有关创建基于 Maven 的 Spring 项目的更多细节,请阅读本文 Maven 项目

现在创建一个项目后,让我们创建一个简单的 hello spring 应用。为了创建应用,我们主要创建了三个文件:

  • HelloWorld.java

  • HelloWorldService.java

  • applicationContext.java

这个项目有一个包含配置和项目依赖关系的 pom.xml 文件。您必须向该文件添加 Spring Dependencies 来配置应用。之后,您的项目结构应该如下所示。

项目结构:

以下是创建的新项目的项目结构:

spring project using STS tool

现在让我们逐一查看每个文件中的代码。

HelloWorld.java

该文件包含用于加载应用上下文文件的代码,该文件被配置为加载 bean。好奇想知道,比恩是什么?别担心,我们将在后面的教程中介绍它。现在,只需创建这个文件。

package com.studytonight.example;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloWorld {

	public static void main(String[] args) {

		// loading the Bean and XML definitions from the given XML file
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		HelloWorldService obj = context.getBean(HelloWorldService.class);
		obj.hello();
		context.close();
	}
}

HelloWorldService.java

该文件包含将向控制台打印“Hello Spring”消息的代码。用“helloworldservice . Java”名称创建此文件。

package com.studytonight.example;

public class HelloWorldService {

	public void hello() {
		System.out.println("Hello Spring!");
	}
}

applicationContext.xml

这是 Spring 项目的配置文件。我们可以给它命名任何东西,但是现在在你的 maven 项目中把它保存为 applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">

	<context:component-scan base-package="com.studytonight.examples" />
	<bean id="helloWorldService"
		class="com.studytonight.example.HelloWorldService">
	</bean>
</beans>

pom.xml 文件

这个文件是 maven 项目的一部分,用于为我们的项目添加依赖项。对于我们的项目,我们添加了 spring 依赖项。这是这个项目最晚的一次。尽管我们可以从 maven 存储库中获得这些最新的依赖项。Spring 依存关系

<project 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>springproject</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<build>
		<sourceDirectory>src</sourceDirectory>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

运行应用:

运行此应用(项目)并获得以下结果。因为它不是一个 web 应用,所以我们可以简单地将它作为一个 Java 应用来运行。

你好 Spring!



简单的 Hello World 应用

原文:https://www.studytonight.com/spring-framework/simple-hello-world-application

首先,让我们创建一个简单的 hello world 应用。我们正在使用我们在上一个主题中创建的基于 maven 的 spring 项目

我们已经创建了几个文件,并用 Spring 5 依赖项更新了默认的 pom.xml 文件。因此,首先,将这些依赖项添加到 pom.xml 文件中。

Maven 项目的 Spring 5 依赖关系

在下面指定的 pom.xml 中,我们将添加所有 Spring 5 依赖项:

<dependencies>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-core</artifactId>
		<version>${spring.version}</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context</artifactId>
		<version>${spring.version}</version>
	</dependency>
</dependencies>
<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
</properties>

将这些依赖项添加到文件后。让我们创建一些 Java 文件和 XML 配置文件。这些文件是:

  • Hello.java

  • HelloWorldService.java

  • applicationContext.xml

  • pom.xml 文件

现在,让我们为我们的 spring 项目创建上面提到的所有 Java 和 XML 文件。

Hello.java

该文件包含用于加载应用上下文文件的代码,该文件被配置为加载 bean。好奇想知道,比恩是什么?别担心,我们将在后面的教程中介绍它。现在,只需创建这个文件。

package com.studytonight.example;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Hello {

	public static void main(String[] args) {

		// loading the Bean and XML definitions from the given XML file
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		HelloWorldService obj = context.getBean(HelloWorldService.class);
		obj.hello();
		context.close();
	}
}

HelloWorldService.java

该文件包含将向控制台打印“Hello Spring”消息的代码。用“helloworldservice . Java”名称创建此文件。

package com.studytonight.example;

public class HelloWorldService {

	public void hello() {
		System.out.println("Hello Spring!");
	}
}

applicationContext.xml

这是 Spring 项目的配置文件。我们可以给它命名任何东西,但是现在在你的 maven 项目中把它保存为 applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">

	<context:component-scan base-package="com.studytonight.examples" />
	<bean id="helloWorldService"
		class="com.studytonight.example.HelloWorldService">
	</bean>
</beans>

pom.xml 文件

这个文件是 maven 项目的一部分,用于为我们的项目添加依赖项。对于我们的项目,我们添加了 spring 依赖项。这是这个项目最晚的一次。尽管我们可以从 maven 存储库中获得这些最新的依赖项。Spring 依存关系

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>springproject</groupId>
  <artifactId>springproject</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  <dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
  <build>
    <sourceDirectory>src</sourceDirectory>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <version>3.2.3</version>
        <configuration>
          <warSourceDirectory>WebContent</warSourceDirectory>
        </configuration>
      </plugin>
    </plugins>

  </build>
</project>

项目结构:

在创建了以上所有文件之后,我们得到了以下目录结构。我们的 Spring 项目应该具有以下目录结构。

Spring Hello World Application

运行应用:

运行此应用(项目)并获得以下结果。由于它不是一个 web 应用,因此我们可以简单地将其作为一个 Java 应用来运行。

你好 Spring!



Spring IOC 容器

原文:https://www.studytonight.com/spring-framework/spring-ioc-container

Spring IoC 容器是 Spring 框架的核心部分,用于管理应用 bean。它在创建 bean 时注入依赖项,并在执行过程中管理 bean 的生命周期

SpringIOC 的基本任务是:

  • 例示

  • 配置和

  • 组装 Bean

IOC 容器从 Spring 配置文件中获取配置相关信息。可以是 XML 或者 Java 文件。

容器使用依赖注入来管理组成应用的组件。

**Spring 提供了两种 IOC 容器:

  • 豆工厂

  • 应用上下文

Spring 豆工厂界面

它是一个 IoC 容器,负责维护 beans 及其依赖关系。它基本上是一个提供基本功能的接口。

豆工厂接口方法:

以下是豆工厂接口方法:

|

方法名

|

描述

|
| boolean containsBean(String name) | 它检查这个 bean 工厂是否包含具有给定名称的 bean 定义或外部注册的单例实例。 |
| String[] getAliases(String name) | 它返回给定 bean 名称的别名(如果有)。 |
| <T> T getBean(Class<T> requiredType) | 它返回唯一匹配给定对象类型(如果有)的 bean 实例。 |
| <T> T getBean(Class<T> requiredType, Object... args) | 它返回指定 bean 的一个实例,该实例可以是共享的,也可以是独立的。 |
| Object getBean(String name) | 它返回指定 bean 的一个实例,该实例可以是共享的,也可以是独立的。 |
| <T> T getBean(String name, Class<T> requiredType) | 它返回指定 bean 的一个实例,该实例可以是共享的,也可以是独立的。 |
| Object getBean(String name, Object... args) | 它返回指定 bean 的一个实例,该实例可以是共享的,也可以是独立的。 |
| <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType) | 它返回指定 bean 的提供者,允许实例的延迟按需检索,包括可用性和唯一性选项。 |
| <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType) | 它返回指定 bean 的提供者,允许实例的延迟按需检索,包括可用性和唯一性选项。 |
| Class<?> getType(String name) | 它确定具有给定名称的 bean 的类型。 |
| Class<?> getType(String name, boolean allowFactoryBeanInit) | 它确定具有给定名称的 bean 的类型。 |
| boolean isPrototype(String name) | 它检查这个 bean 是否是原型。 |
| boolean isSingleton(String name) | 它检查这个 bean 是否是共享的单例。 |
| boolean isTypeMatch(String name, Class<?> typeToMatch) | 它检查具有给定名称的 bean 是否与指定的类型匹配。 |
| boolean isTypeMatch(String name, ResolvableType typeToMatch) | 它检查具有给定名称的 bean 是否与指定的类型匹配。 |

Spring 应用上下文子接口

ApplicationContextBeanFactory的子界面,提供更多类似企业的功能。它添加了特定于应用层的上下文,例如网络应用的WebApplicationContext

此应用上下文界面有几种实现,例如:

  • ClassPathXmlApplicationContext

  • XmlWebApplicationContext

  • filestystemxmlaplicationcontext

应用上下文方法:

以下是应用上下文接口中的方法。

|

方法名

|

描述

|
| String getApplicationName() | 它返回此上下文所属的已部署应用的名称。 |
| AutowireCapableBeanFactory getAutowireCapableBeanFactory() | 它为这个上下文公开了 AutowireCapableBeanFactory 功能。 |
| String getDisplayName() | 它返回该上下文的友好名称。 |
| String getId() | 它返回此应用上下文的唯一 id。 |
| ApplicationContext getParent() | 它返回父上下文,如果没有父上下文,则返回 null,这是上下文层次结构的根。 |
| long getStartupDate() | 它返回首次加载该上下文时的时间戳。 |

BeanFactory 和应用上下文之间的区别

两个接口(BeansFactory 和 ApplicationsContext)都充当 IoC 容器。BeanFactory 接口是一个基础接口,提供了创建和运行 IoC 容器的所有基本功能,而 ApplicationContext 接口是 BeanFactory 接口的一个子接口,它增加了一些额外的功能,如与 Spring 的 AOP 的简单集成、消息资源处理(对于 I18N)、应用层特定的上下文等。因此,我们可以使用 ApplicationContext 来获得更好的特性。

如何配置 IoC 容器?

这是基于 XML 的配置元数据的基本结构。

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

    <bean id="..." class="...">  
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions go here -->

</beans>

主要有三种方法可以配置我们的 IoC 容器。

  • 基于 XML 的

  • 基于注释

  • 基于 Java 的

在下一节中,我们将讨论如何以所有可能的方式配置 IoC 容器。



Spring XML 配置

原文:https://www.studytonight.com/spring-framework/spring-xml-based-configuration

在本主题中,我们将学习创建一个字符串应用,并使用 XML 代码对其进行配置。让我们创建一个 maven 项目,并使用 XML 文件对其进行配置。如果你不熟悉 maven 项目,那么你可以在这里阅读我们的详细文章

以下是我们项目中创建的文件。这些文件的源代码如下。

  • Employee.java

  • Engineer.java

  • Manager.java

  • 银行应用.java

  • applicationContext.xml

下面是我们在创建所有上述文件(java 和 xml)后的项目结构。

Spring 项目结构:

以下是项目的结构:

Spring XML Based Configuration

现在让我们创建 Java 类和 XML 配置文件。

Employee.java

它是一个包含抽象方法doWork()的接口,该方法将被实现的类覆盖。

package com.studytonight.community;

public interface Employee {

	void doWork();

}

Accountant.java

我们的 bean 类将用于执行实现。实现Employee接口,实现doWork()方法。

package com.studytonight.community;

public class Accountant implements Employee{

	public void doWork() {

		System.out.println("Audit the accounts...");
	}
}

Manager.java

这是另一个实现Employee接口并覆盖doWork()方法的类。

package com.studytonight.community;

public class Manager implements Employee{

	public void doWork() {

		System.out.println("Manage the branch office");
	}
}

银行应用.java

它是一个配置文件,读取applicationContext文件,使用getBean()方法获取 Bean,然后根据检索到的对象调用方法。

package com.studytonight.community;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BankApp {

	private static ApplicationContext context;
	public static void main(String[] args) {

		context = new ClassPathXmlApplicationContext("applicationContext.xml");
		Employee e = (Employee) context.getBean("manager");
		e.doWork();
	}

}

applicationContext.xml

这是一个配置 spring 并注册 bean 的应用上下文文件。

<?xml version="1.0" encoding="UTF-8"?>

<beans 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">

	<bean id="manager"
		class="com.studytonight.community.Manager">
	</bean>
</beans>

pom.xml 文件

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.studytonight</groupId>
  <artifactId>springApp</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>javax.annotation</groupId>
			<artifactId>javax.annotation-api</artifactId>
			<version>1.3.2</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<build>
		<sourceDirectory>src</sourceDirectory>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>

	</build>
</project>

运行应用:

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

管理分公司



Spring 注解和基于 XML 的配置

原文:https://www.studytonight.com/spring-framework/spring-annotation-and-xml-based-configuration

在本主题中,我们将学习创建一个字符串应用,并使用 XML 和注释代码对其进行配置。让我们创建一个 maven 项目,并使用 XML 文件对其进行配置。如果你不熟悉 maven 项目,那么你可以在这里阅读我们的详细文章

以下是我们项目中创建的文件。这些文件的源代码如下。

  • Employee.java

  • Accountant.java

  • Manager.java

  • 银行应用.java

  • applicationContext.xml

下面是我们在创建了以上所有文件(Java****XML)之后的项目结构。

Spring 项目结构:

以下是 spring 项目的项目结构:

spring project with XML config and annotations

让我们为项目创建 Java 类和 XML 文件。

银行应用.java

它是一个配置文件,读取applicationContext文件,使用getBean()方法获取 Bean,然后根据检索到的对象调用方法。

package com.studytonight.community;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BankApp {

	private static ApplicationContext context;
	public static void main(String[] args) {

		context = new ClassPathXmlApplicationContext("applicationContext.xml");
		Employee e = (Employee) context.getBean("manager");
		e.doWork();
	}

}

Employee.java

它是一个包含抽象方法 doWork()的接口,该方法将被实现的类覆盖。

package com.studytonight.community;

public interface Employee {

	void doWork();

}

Accountant.java

我们的 bean 类将用于执行实现。实现Employee接口,实现doWork()方法。

package com.studytonight.community;
import org.springframework.stereotype.Component;
@Component
public class Accountant implements Employee{

	public void doWork() {

		System.out.println("Audit the accounts...");
	}
}

Manager.java

这是另一个实现Employee接口并覆盖doWork()方法的类。

package com.studytonight.community;
import org.springframework.stereotype.Component;

@Component
public class Manager implements Employee{

	public void doWork() {

		System.out.println("Manage the branch office");
	}
}

applicationContext.xml

这是一个配置 spring 并注册 bean 的应用上下文文件。

<?xml version="1.0" encoding="UTF-8"?>
<beans 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="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 
                           http://www.springframework.org/schema/context/spring-context.xsd">

	<context:component-scan base-package="com.studytonight.community"></context:component-scan>

</beans>

pom.xml 文件

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.studytonight</groupId>
  <artifactId>springApp</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>javax.annotation</groupId>
			<artifactId>javax.annotation-api</artifactId>
			<version>1.3.2</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<build>
		<sourceDirectory>src</sourceDirectory>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>

	</build>
</project>

运行应用:

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

管理分公司



Spring 的 Java 配置(无 XML)

原文:https://www.studytonight.com/spring-framework/spring-configuration-using-java-no-xml

在本教程中,我们将创建一个 spring 项目,并使用 Java 代码对其进行配置。我们将不使用任何 XML 代码,只使用 Java 代码。该项目包含以下文件。

  • 银行应用.java

  • AppConfig.java

  • Accountant.java

  • Manager.java

  • Employee.java

  • pom.xml 文件

下面是为 Spring 应用创建的 maven 项目结构。

Spring 项目-结构:

以下是 spring 项目的项目结构:

spring project configuration using Java

在上述项目中创建的文件包含以下代码。请参见下面的文件。

银行应用.java

该文件包含为我们的应用创建 IOC 容器的代码。AnnotationConfigApplicationContext 类用于为应用上下文创建对象。

package com.studytonight.community;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class BankApp {

	public static void main(String[] args) {

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		Manager employee = context.getBean(Manager.class);
		employee.doWork();
		context.close();
	}
}

AppConfig.java

这是一个 Java 配置文件,它是我们为基于 xml 的配置示例创建的 applicationContext.xml 文件的替代文件。@Configuration注释表示这不是一个简单的类,而是一个配置类,@ComponentScan注释用于表示我们 spring 项目中的组件位置。

package com.studytonight.community;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.studytonight.community")
public class AppConfig {

}

Accountant.java

这是一个使用@Component注解的组件类。它实现了Employee接口并覆盖了它的方法doWork()

package com.studytonight.community;

import org.springframework.stereotype.Component;

@Component
public class Accountant implements Employee{

	public void doWork() {

		System.out.println("Auditing Accounts...");

	}
}

Manager.java

这是另一个使用@Component注释标记并实现Employee接口的组件类。

package com.studytonight.community;
import org.springframework.stereotype.Component;
@Component
public class Manager implements Employee{

	public void doWork() {

		System.out.println("Manage the branch office");
	}
}

Employee.java

这是一个包含doWork()抽象方法的界面Employee。每个实现这个接口的类都必须覆盖doWork()方法。

package com.studytonight.community;

public interface Employee {

	void doWork();

}

pom.xml 文件

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.studytonight</groupId>
  <artifactId>springApp</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>javax.annotation</groupId>
			<artifactId>javax.annotation-api</artifactId>
			<version>1.3.2</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<build>
		<sourceDirectory>src</sourceDirectory>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>

	</build>
</project>

运行应用:

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

管理分公司



Spring Bean

原文:https://www.studytonight.com/spring-framework/spring-bean

Bean 是 Spring 中的一个对象,由 Spring IoC 容器管理。Spring 使用我们在 XML 文件的 < bean > 标签中提供的配置元数据创建 bean。我们通过使用 XML 文件或 Java 注释向 IoC 容器提供元数据。

在元数据配置期间,我们为 bean 定义提供了一些可选属性,例如:

  • Bean 类名的完全限定名。比如com study south . community . reader

  • Bean 行为,如 Bean 作用域、生命周期回调等。

  • Bean 所需的 bean 依赖项(对其他 bean 的引用)。

标签结构

<bean id="demoBean" class="com.examples.DemoBean" /> 

id 属性为由属性指定的类设置唯一的 id。

Bean 定义属性

下表包含用于在配置文件中配置 bean 的标签属性。

|

Bean 属性

|

描述

|
| --- | --- |
| 班级 | 此属性用于指定为其创建对象的类。 |
| 名字 | 此属性用于为 bean 指定唯一的标识符。 |
| 作用域 | 它指定了 beans 的作用域,如 singleton 或 prototype。 |
| 构造器参数 | 它用于基于构造器的依赖注入。 |
| 性能 | 此属性用于基于属性的依赖注入。 |
| 自动装配模式 | 用于设置 bean 自动装配。 |
| 协作者和惰性初始化模式 | 它用于设置惰性 bean 初始化。 |
| 初始化方法 | 它用于设置在 bean 初始化时执行的初始化方法。 |
| 销毁方法 | 它用于设置在销毁 bean 对象之前执行的破坏性方法。 |

1.命名 Bean

为了在基于 XML 的配置中设置 bean 的名称,我们使用 id、 名称属性,或者两者都使用。 id 属性让我们可以精确地指定一个 id。

在设置 bean 名称时,我们需要遵循命名约定,这意味着 bean 名称以小写字母开头,并且是骆驼大小写。

<bean id="..." class="..."> 
    <!-- Configuration for this bean go here --> 
</bean>

惰性初始化

默认情况下,ApplicationContext实现急切地创建和配置所有单例 beans,作为初始化过程的一部分。

延迟初始化的 bean 告诉 IoC 容器在第一次请求时创建一个 bean 实例,而不是在启动时。

<bean id = "..." class = "..." lazy-init = "true">
      <!-- Configuration for this bean go here -->
</bean>

初始化方法

此属性用于指定在 bean 初始化时执行的方法。bean 标记和属性的语法如下。

<bean id = "..." class = "..." init-method = "...">
      <!-- Configuration for this bean go here -->
</bean>

销毁方法

此属性用于指定在 bean 销毁时执行的方法。bean 标记和属性的语法如下。

<bean id = "..." class = "..." destroy-method = "...">
      <!-- Configuration for this bean go here -->
</bean>

简单的 Bean 示例

让我们创建一个示例来创建一个 bean,并从 bean 和属性标签中访问它的属性。以下是我们在项目中创建的 Java 和 XML 文件。

//Employee.java

这是一个简单的 Java POJO bean 类,它有设置器和获取器方法来处理数据。

package com.studytonight.community;
public class Employee {

	int id;
	String name;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

// SpringApp.java

该文件读取 XML 文件,并获取 XML 文件中的 bean 数据集。我们使用获取器方法来获取 bean 数据。

package com.studytonight.community;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringApp {

	private static ApplicationContext context;
	public static void main(String[] args) {

		context = new ClassPathXmlApplicationContext("applicationContext.xml");
		Employee e = (Employee) context.getBean("employee");
		System.out.println("Id: "+e.getId());
		System.out.println("Name: "+e.getName());
	}
}

//application context . XML

这是一个上下文文件,通过使用属性标记来配置 bean 标记及其属性。

<?xml version="1.0" encoding="UTF-8"?>
<beans 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="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 
                           http://www.springframework.org/schema/context/spring-context.xsd">

	<bean id="employee" class="com.studytonight.community.Employee">
		<property name="id" value="0501"></property>
		<property name="name" value="Rahul"></property>
	</bean>
</beans>

//POM . XML

这是一个 maven 依赖文件,用于配置所有项目设置和依赖关系。

<project 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>SpringApp</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<dependencies>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<build>
		<sourceDirectory>src</sourceDirectory>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

Id: 501
姓名:拉胡尔



Spring Bean 生命周期

原文:https://www.studytonight.com/spring-framework/spring-bean-lifecycle

Spring bean 的生命周期包括几个步骤,包括 Bean 初始化和 Bean 销毁。这些步骤由 Spring IOC 管理,它允许我们执行自定义初始化和结束任务。

在 Spring 中,如果我们想在 bean 初始化时和销毁 bean 对象之前执行一些任务,那么我们可以使用 Spring 的预定义接口InitializingBeanDisposableBean。这些接口提供了可用于在创建 bean 之前和之后执行任务的方法。Java 也提供注释来处理 Bean 生命周期。

有两种方法可以执行这些任务:

  • 接口
  • 释文

Spring InitializingBean接口提供了一种方法afterPropertiesSet(),可以用来执行初始化任务,而DisposableBean接口提供了一种方法destroy(),可以在销毁 bean 对象之前进行资源清理。

使用接口的 Bean 生命周期

这里,我们在项目中使用这些接口。我们的项目是一个 maven 项目,包含下面的代码文件。

//Manager.java

我们的 bean 类将用于执行实现。实现Employee接口,实现doWork()方法。

package com.studytonight.community;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

@Component
public class Manager implements InitializingBean, DisposableBean, Employee{

	@Override
	public void afterPropertiesSet() throws Exception {

		System.out.println("Perform tasks while initializing Bean");

	}
	@Override
	public void destroy() throws Exception {

		System.out.println("Perform tasks before destroying of Bean");

	}
	@Override
	public void doWork() {
		System.out.println("Manage branch office");		
	}
}

//Employee.java

它是一个包含抽象方法 doWork()的接口,该方法将被实现的类覆盖。

package com.studytonight.community;
public interface Employee {

	void doWork();

}

// 银行应用.java

它是一个配置文件,读取applicationContext文件,使用getBean()方法获取 Bean,然后根据检索到的对象调用方法。

package com.studytonight.community;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class BankApp {

	public static void main(String[] args) {

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		Employee employee = (Employee) context.getBean("manager");
		employee.doWork();
		context.close();
	}
}

//app config . Java

package com.studytonight.community;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.studytonight.community")
public class AppConfig {

} 

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.studytonight</groupId>
  <artifactId>springApp</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>javax.annotation</groupId>
			<artifactId>javax.annotation-api</artifactId>
			<version>1.3.2</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<build>
		<sourceDirectory>src</sourceDirectory>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>

	</build>
</project>

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

初始化 Bean 时执行任务
管理分支机构
在销毁 Bean 前执行任务

Spring 注释:另一种方法

Spring 提供了两个注释:@PostConstruct@PreDestroy来执行初始化和结束任务。在这种情况下,我们不需要使用接口及其方法。这种方法非常简单,值得推荐。

注意:对于 Java 9 及更高版本,我们需要在项目中添加一些额外的 JARs,因为 javax.annotation 包已经从其默认类路径中移除。因此,将以下 JARs 添加到 pm.xml 文件中。

<dependency>
	<groupId>javax.annotation</groupId>
	<artifactId>javax.annotation-api</artifactId>
	<version>1.3.2</version>
</dependency>

使用 Spring 注释的生命周期

当使用注释时,没有提供任何方法,那么我们可以使用我们自己的带有注释的方法。看,initWork()方法和 predestroy()方法是我们自己创建的,我们在这两个方法上都使用了注释,以便在 Bean 生命周期中执行它们。您可以用这个代码替换上面的示例代码(manager.java),它将产生相同的结果。

package com.studytonight.community;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.stereotype.Component;

@Component
public class Manager implements Employee{

	public void doWork() {
		System.out.println("Manage the branch office");

	}
	@PostConstruct
	public void initWork() {

		System.out.println("Perform tasks while initializing Bean");

	}
	@PreDestroy
	public void Predestroy() {

		System.out.println("Perform tasks before destroying of Bean");
	}
}

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

初始化 Bean 时执行任务
管理分支机构
在销毁 Bean 前执行任务



Spring Bean 作用域

原文:https://www.studytonight.com/spring-framework/spring-bean-scope

Bean Scope 指的是 Bean 的生命周期,bean 的可见性,bean 存在多长时间,创建了多少实例,bean 是如何共享的?

Bean 的默认作用域是单例。spring 容器将创建 bean 的单个实例。它被缓存在内存中。对 bean 的所有请求都将返回同一个 bean 的共享引用。

Spring 提供了@Scope 注释来标记一个 bean 作用域。

Spring Bean 作用域

以下是 Spring 应用中使用的 bean 作用域的类型。

|

作用域

|

描述

|
| --- | --- |
| 一个 | 这是 bean 的默认作用域。它代表每个 Spring IoC 容器的单个 bean 作用域。 |
| 原型 | 它用于将单个 bean 定义的作用域设置为任意数量的对象实例。 |
| 请求 | 该 bean 作用域是为单个 HTTP 请求设置的。 |
| 会议 | 该作用域是为 HTTP 会话的单个 bean 定义设置的。 |
| 应用 | 它将 bean 作用域设置为一个 ServletContext。 |
| WebSocket | 它将 bean 作用域设置为一个网络套接字。 |

示例:Bean 单例作用域(默认作用域)

让我们创建一个示例,将 bean 作用域标记为默认,并检查它是否有默认作用域。

项目结构

项目文件源代码:

//App.java

该文件包含为我们的应用创建 IOC 容器的代码。AnnotationConfigApplicationContext 类用于为应用上下文创建对象。这里创建了两个 bean 对象,并检查它们是否相等。

package com.studytonight.community;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {

	public static void main(String[] args) {

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		Writer writer1 = context.getBean("fictionWriter", Writer.class);
		Writer writer2 = context.getBean("fictionWriter", Writer.class);

		boolean isSame = writer1 == writer2;
		System.out.println("Instance One :"+writer1);
		System.out.println("Instance One :"+writer2);
		System.out.println("Both bean instances are same: "+isSame);

		//writer.write();
		// Close the context
		context.close();
	}
}

//app config . Java

这是一个 Java 的配置文件,它是我们为基于 xml 的配置示例创建的 applicationContext.xml 文件的替代文件。@Configuration注释表示这不是一个简单的类,而是一个配置类,@ComponentScan注释用于表示我们 spring 项目中的组件位置。

package com.studytonight.community;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.studytonight.community")
public class AppConfig {

} 

//FictionWriter.java

package com.studytonight.community;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope
public class FictionWriter implements Writer {

	@Override
	public void write() {

		System.out.println("Write Fiction Novels...");
	}
}

//Writer.java

package com.studytonight.community;

public interface Writer {

	void write();
	void getAward();
}

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.studytonight</groupId>
  <artifactId>springproject</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
  <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
  <dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
  <build>
    <sourceDirectory>src</sourceDirectory>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>

  </build>
</project>

实例一:com . study south . community . fiction writer @ 6a 28 FFA 4
实例一:com . study south . community . fiction writer @ 6a 28 FFA 4
两个 bean 实例都是相同的:true

示例:Bean 作用域原型

这是另一种类型的 bean 作用域,在这种情况下,同一个类的两个 bean 对象是不相等的。

//FictionWriter.java

package com.studytonight.community;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("prototype")
public class FictionWriter implements Writer {

	@Override
	public void write() {

		System.out.println("Write Fiction Novels...");
	}
}

实例一:com . study south . community . fiction writer @ 6a 28 FFA 4
实例一:com . study south . community . fiction writer @ 48 AE 9 b55
两个 bean 实例相同:false



Spring 构造器的依赖注入

原文:https://www.studytonight.com/spring-framework/spring-constructorbased-dependency-injection

在本主题中,我们使用基于构造器的依赖注入技术通过构造器注入值,但是在继续之前,让我们先了解什么是依赖注入(DI)。

依赖注入是一种对象定义其依赖的技术。然后,IOC 容器在 bean 创建期间注入这些依赖关系。这个过程基本上是反过来的,也被称为控制的反过来。依赖注入使我们的代码松散耦合。它分为两大类:基于构造器的依赖注入和基于 Setter 的依赖注入。在这里,我们将通过一个例子来讨论基于构造器的 DI。

我们创建了一个基于 Maven 的 Spring 项目,它包含以下文件。

  • 银行应用.java

  • AppConfig.java

  • Employee.java

  • Manager.java

  • Accountant.java

  • pom.xml 文件

下面是为 Spring 应用创建的 maven 项目结构。

项目结构:

在上述项目中创建的文件包含以下代码。请参见下面的文件。

文件源代码:

// 银行应用.java

该文件包含为我们的应用创建 IOC 容器的代码。AnnotationConfigApplicationContext 类用于为应用上下文创建对象。

package com.studytonight.community;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class BankApp {

	public static void main(String[] args) {

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		Manager manager = context.getBean(Manager.class);
		manager.callMetting();
		context.close();
	}
}

//app config . Java

这是一个 Java 的配置文件,它是我们为基于 xml 的配置示例创建的 applicationContext.xml 文件的替代文件。@Configuration注释表示这不是一个简单的类,而是一个配置类,@ComponentScan注释用于表示我们 spring 项目中的组件位置。

package com.studytonight.community;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.studytonight.community")
public class AppConfig {

} 

//Employee.java

这是一个包含doWork()抽象方法的界面Employee。每个实现这个接口的类都必须覆盖doWork()方法。

package com.studytonight.community;

public interface Employee {

	void doWork();

}

//Accountant.java

这是一个使用@Component注解的组件类。它实现了Employee接口并覆盖了它的方法doWork()

package com.studytonight.community;
import org.springframework.stereotype.Component;
@Component
public class Accountant implements Employee{

	public Accountant() {
		System.out.println("Inside Accountant Constructor");
	}
	public void doWork() {	
		System.out.println("Audit the accounts...");
	}
}

//Manager.java

这是另一个使用@Component注释标记并实现Employee接口的组件类。在这个类中,我们实现了基于构造器的依赖注入。请参见,管理器类通过使用在管理器类构造器中实例化的会计类对象来调用会计类的方法。请看下面的例子。

package com.studytonight.community;
import org.springframework.stereotype.Component;

@Component
public class Manager implements Employee{

	Accountant accountant;

	public Manager(Accountant accountant) {
		System.out.println("manager constructor");
		this.accountant = accountant;
	}
	public void doWork() {
		System.out.println("Manage the branch office");
	}

	public void callMetting() {
		accountant.doWork();
	}
}

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.studytonight</groupId>
  <artifactId>springApp</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>javax.annotation</groupId>
			<artifactId>javax.annotation-api</artifactId>
			<version>1.3.2</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<build>
		<sourceDirectory>src</sourceDirectory>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>

	</build>
</project>

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

内部会计建造师
经理建造师
审核账目...

使用 XML 进行配置

上述项目仅使用 Java 代码进行配置。那里没有 XML 配置,但是我们也可以用 XML 代码来配置它。我们只需要创建一个文件 applicationContext.xml 并将其读入 BankApp 类。 applicationContext.xml 文件包含以下代码。

//application context . XML

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

	<bean id="accountant"
		class="com.studytonight.community.Accountant" />
	<bean id="manager" class="com.studytonight.community.Manager">
		<constructor-arg>
			<ref bean="accountant" />
		</constructor-arg>
	</bean>
</beans> 

将基元值注入构造器

除了引用变量,我们还可以向构造器中注入像 int、float 等基元值。例如,在管理器类中,我们在构造器中使用 int id 和字符串名称,并从 applicationContext.xml 文件中注入值。

//Manager.java

package com.studytonight.community;
import org.springframework.stereotype.Component;

@Component
public class Manager implements Employee{
	int id;
	String name;

	public Manager(int id, String name) {
		this.id = id;
		this.name = name;
	}
	public void doWork() {
		System.out.println("Manage the branch office");
	}

	public void managerInfo() {
		System.out.println("Name: "+name+" Id: "+id);
	}
}

//application context . XML

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

	<bean id="manager" class="com.studytonight.community.Manager">
		<constructor-arg type="int" value="10021" />
		<constructor-arg type="java.lang.String" value="Ramesh" />
	</bean>
</beans> 

运行应用

成功地将这两个文件更新到项目中后,运行应用,您将获得如下输出。

名称:Ramesh Id: 10021

指定构造器参数名

我们还可以使用构造器参数名称来消除值的歧义,就像我们在下面的例子中所做的那样。

<bean id="manager" class="com.studytonight.community.Manager">
    <constructor-arg name="id" value="10021"/>
    <constructor-arg name="name" value="Ramesh"/>
</bean>


Spring 设置器依赖注入

原文:https://www.studytonight.com/spring-framework/spring-setter-dependency-injection

在本主题中,我们使用设置器依赖注入技术通过设置器方法注入值。该项目是一个基于 Maven 的 Spring 项目,包含以下文件。

  • 银行应用.java

  • AppConfig.java

  • Manager.java

  • 附加 java

  • Employee.java

  • pom.ml

下面是为 Spring 应用创建的 maven 项目结构。

项目结构:

在上述项目中创建的文件包含以下代码。请参见下面的文件。

文件源代码:

//银行应用.java

该文件包含为我们的应用创建 IOC 容器的代码。AnnotationConfigApplicationContext 类用于为应用上下文创建对象。

package com.studytonight.community;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class BankApp {

	public static void main(String[] args) {

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		Manager manager = context.getBean(Manager.class);
		manager.callMetting();
		context.close();
	}
}

//app config . Java

这是一个 Java 的配置文件,它是我们为基于 xml 的配置示例创建的 applicationContext.xml 文件的替代文件。@Configuration注释表示这不是一个简单的类,而是一个配置类,@ComponentScan注释用于表示我们 spring 项目中的组件位置。

package com.studytonight.community;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.studytonight.community")
public class AppConfig {

}

//Manager.java

这是另一个使用@Component注释标记并实现Employee接口的组件类。在这个类中,我们实现了一个设置器依赖注入。请参见,管理器类通过使用在设置器方法中实例化的 account 类对象来调用 account 类的方法。请看下面的例子。

package com.studytonight.community;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Manager implements Employee{

	Accountant accountant;

	@Autowired
	public void setAccountant(Accountant accountant) {
		this.accountant = accountant;
	}
	public void doWork() {
		System.out.println("Manage the branch office");
	}

	public void callMetting() {
		accountant.doWork();
	}
}

//Accountant.java

这是一个使用@Component注解的组件类。它实现了Employee接口并覆盖了它的方法doWork()

package com.studytonight.community;
import org.springframework.stereotype.Component;
@Component
public class Accountant implements Employee{

	public Accountant() {
		System.out.println("Inside Accountant Constructor");
	}
	public void doWork() {	
		System.out.println("Audit the accounts...");
	}
}

//Employee.java

这是一个包含doWork()抽象方法的界面Employee。每个实现这个接口的类都必须覆盖doWork()方法。

package com.studytonight.community;

public interface Employee {

	void doWork();

}

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.studytonight</groupId>
  <artifactId>springApp</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>javax.annotation</groupId>
			<artifactId>javax.annotation-api</artifactId>
			<version>1.3.2</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<build>
		<sourceDirectory>src</sourceDirectory>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>

	</build>
</project>

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

内部会计建造师
审核账目...

使用 XML 进行配置

上述项目仅使用 Java 代码进行配置。那里没有 XML 配置,但是我们也可以用 XML 代码来配置它。我们只需要创建一个文件 applicationContext.xml 并读入 BankApp 类。 applicationContext.xml 文件包含以下代码。

//application context . XML

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

	<bean id="accountant"
		class="com.studytonight.community.Accountant" />
	<bean id="manager" class="com.studytonight.community.Manager">
		<property name="accountant">
			<ref bean="accountant" />
		</property>
	</bean>
</beans> 


Spring 自动装配

原文:https://www.studytonight.com/spring-framework/spring-autowiring

自动装配是 Spring 中用来实现自动依赖注入的一种技术。通过使用它,Spring 容器可以自动连接协作 beans 之间的关系。它被称为 Spring 自动装配。

Spring 提供@Autowired 注释,使您能够隐式地注入对象依赖关系。它在内部使用设置器或构造器注入。

注意:我们不能使用@Autowired 注解来注入原语和字符串值。它的工作方式仅供参考。

启用 Spring 自动装配

Spring 框架支持自动依赖注入。换句话说,通过在 Spring 配置文件中声明所有的 bean 依赖关系,Spring 容器可以自动连接协作 bean 之间的关系。这叫做 Spring bean 自动装配。

在基于 Java 的配置中,我们可以通过使用@componentScan 注释来启用它。

@Configuration
@ComponentScan("com.studytonight")
public class AppConfig{
}

而在 XML 配置的情况下,我们可以在 applicationcontext 文件内部使用标签。

自动连接也可以用于字段、方法和构造器。让我们看一些例子

启用注释注入后,我们可以在属性、设置器和构造器上使用自动连接

示例:现场自动装配

Spring 允许使用带有字段的@Autowired 注释来注入依赖关系,就像我们在下面的例子中所做的那样。完整的例子,请参考我们的详细文章@带字段自动装配

@Service
@Component
public class UserServices {	 

	@Autowired
	private SessionFactory sessionFactory;

	public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }
}

示例:方法自动装配

Spring 允许使用@Autowired 注释和方法来注入依赖关系,就像我们在下面的例子中所做的那样。完整的例子可以参考我们详细的文章@用方法自动装配。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class FictionWriter implements Writer {

	private Award award;

	@Autowired
	public void awardInstance(Award award) {
		this.award = award;
	}
}

示例:构造器自动装配

Spring 允许使用带有构造器的@Autowired 注释来注入依赖项,就像我们在下面的例子中所做的那样。完整的例子可以参考我们详细的文章@带构造器的自动装配

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class TechnicalWriter implements Writer{

	private Award award;

	@Autowired
	public TechnicalWriter(@Qualifier("pulitzerAward") Award award) {
		this.award = award;
	}
}

我们也可以将它与字段、构造器和方法混合使用。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class TechnicalWriter implements Writer{

	@Autowired
	private Award award;  // Field Autowired

	@Autowired            // Constructor Autowired
	public TechnicalWriter(Writer writer) {
		TechnicalWriter tWriter =  writer
	}
}

之后,我们将讨论使用@限定符注释、以及潜在的异常场景来解决 bean 冲突。



Spring @Qualifier注解

原文:https://www.studytonight.com/spring-framework/qualifier-annotation

Spring 中的@Qualifier注解用于在相同类型的 bean 对象之间区分一个 bean。

如果我们有多个相同类型的 bean,并且只想连接其中一个,那么使用@限定符注解和@自动连接来指定哪个 bean 将被连接。

如果我们没有在给定的项目中使用这个注解,那么我们会得到如下错误:

原因:org . spring framework . beans . factory . nounique beans definitionexception:没有“com . study south . community . award”类型的合格 bean 可用:期望单个匹配的 bean,但找到了 3 个:bookerAward、nationalAward、pulitzerAward

在本主题中,我们使用@Qualifier注解来指定依赖关系实例。该项目是一个基于 Maven 的 Spring 项目,包含以下文件。

  • App.java

  • AppConfig.java

  • Award.java

  • BookerAward.java

  • 国家奖 java

  • 普利策奖. java

  • FictionWriter.java

  • TechnicalWriter.java

  • Writer.java

  • pom.xml 文件

项目结构

文件源代码:

//App.java

该文件包含为我们的应用创建 IOC 容器的代码。AnnotationConfigApplicationContext类用于为应用上下文创建一个对象。

package com.studytonight.community;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class App {

	public static void main(String[] args) {

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		Writer writer = context.getBean("fictionWriter", Writer.class);
		writer.write();
		writer.getAward();
		// Close the context
		context.close();
	}
}

//app config . Java

这是一个 Java 配置文件,它是我们为基于 xml 的配置示例创建的 applicationContext.xml 文件的替代文件。@Configuration注解表示这不是一个简单的类,而是一个配置类,@ComponentScan注解用于表示我们 spring 项目中的组件位置。

package com.studytonight.community;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.studytonight.community")
public class AppConfig {

} 

//Award.java

这是一个包含award()抽象方法的界面Award。实现这个接口的每个类都必须覆盖奖励()方法。

package com.studytonight.community;

public interface Award {

	void award();

}

//BookerAward.java

这是一个使用@Component注解标记的组件类,实现了Award接口。

package com.studytonight.community;

import org.springframework.stereotype.Component;

@Component
public class BookerAward implements Award {

	@Override
	public void award() {

		System.out.println("You got booker prize...");
	}
}

//FictionWriter.java

这是另一个使用@Component注解标记并实现Writer接口的组件类。

package com.studytonight.community;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class FictionWriter implements Writer {

	@Autowired
	@Qualifier("bookerAward")
	private Award award;

	@Override
	public void write() {

		System.out.println("Write Fiction Novels...");
	}

	@Override
	public void getAward() {

		award.award();
	}
}

//国家奖。java

这是另一个使用@Component注解标记并实现Award接口的组件类。

package com.studytonight.community;

import org.springframework.stereotype.Component;

@Component
public class NationalAward implements Award{

	public void award() {

		System.out.println("Your Writting got National Award!");
	}
}

//普利策奖。java

这是另一个使用@Component注解标记并实现Award接口的组件类。

package com.studytonight.community;

import org.springframework.stereotype.Component;

@Component
public class PulitzerAward implements Award {

	@Override
	public void award() {

		System.out.println("You have won Pulitzer Award.");
	}
}

//TechnicalWriter.java

这是另一个使用@Component注解标记并实现Writer接口的组件类。

package com.studytonight.community;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class TechnicalWriter implements Writer{

	@Autowired
	@Qualifier("pulitzerAward")
	private Award award;

	@Override
	public void write() {

		System.out.println("Write technical stuffs...");
	}

	@Override
	public void getAward() {
		award.award();

	}
}

//Writer.java

package com.studytonight.community;

public interface Writer {

	void write();
	void getAward();
}

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.studytonight</groupId>
  <artifactId>springproject</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
  <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
  <dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
  <build>
    <sourceDirectory>src</sourceDirectory>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>

  </build>
</project>

写小说...
你获得了布克奖...



Spring @Qualifier和构造器

原文:https://www.studytonight.com/spring-framework/spring-qualifier-with-constructors

在本主题中,我们使用带有构造器的@Qualifier注释来指定依赖关系实例。我们可以在单个构造器参数或方法参数上指定@Qualifier 注释,如下例所示:

让我们创建一个 spring 项目,这个项目是一个基于 Maven 的 Spring 项目,包含以下文件。

  • App.java

  • AppConfig.java

  • Award.java

  • BookerAward.java

  • 国家奖 java

  • 普利策奖. java

  • FictionWriter.java

  • TechnicalWriter.java

  • Writer.java

  • pom.xml 文件

项目结构:

文件源代码:

//App.java

该文件包含为我们的应用创建 IOC 容器的代码。AnnotationConfigApplicationContext类用于为应用上下文创建一个对象。

package com.studytonight.community;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
	public static void main(String[] args) {

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		Writer writer = context.getBean("fictionWriter", Writer.class);
		writer.write();
		writer.getAward();
		// Close the context
		context.close();
	}
}

//app config . Java

这是一个 Java 配置文件,它是我们为基于 xml 的配置示例创建的 applicationContext.xml 文件的替代文件。@Configuration注释表明这不是一个简单的类,而是一个配置类,@ComponentScan注释用于指示我们的 spring 项目中组件的位置。

package com.studytonight.community;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.studytonight.community")
public class AppConfig {

} 

//Award.java

这是一个包含award()抽象方法的界面Award。每个实现这个接口的类都必须覆盖award()方法。

package com.studytonight.community;
public interface Award {
	void award();

}

//BookerAward.java

这是一个使用@Component注释标记的组件类,实现了Award接口。

package com.studytonight.community;
import org.springframework.stereotype.Component;
@Component
public class BookerAward implements Award {
	@Override
	public void award() {

		System.out.println("You got booker prize...");
	}
}

//FictionWriter.java

这是另一个使用@Component注释标记并实现Writer接口的组件类。

package com.studytonight.community;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class FictionWriter implements Writer {
	private Award award;

	@Autowired
	public FictionWriter(@Qualifier("bookerAward") Award award) {
		this.award = award;
	}
	@Override
	public void write() {

		System.out.println("Write Fiction Novels...");
	}
	@Override
	public void getAward() {

		award.award();
	}
}

//国家奖。java

这是另一个使用@Component注释标记并实现Award接口的组件类。

package com.studytonight.community;
import org.springframework.stereotype.Component;

@Component
public class NationalAward implements Award{	
	public void award() {		
		System.out.println("Your Writting got National Award!");
	}
}

//普利策奖。java

这是另一个使用@Component注释标记并实现Award接口的组件类。

package com.studytonight.community;
import org.springframework.stereotype.Component;
@Component
public class PulitzerAward implements Award {

	@Override
	public void award() {

		System.out.println("You have won Pulitzer Award.");
	}
}

//TechnicalWriter.java

这是另一个使用@Component注释标记并实现Writer接口的组件类。

package com.studytonight.community;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class TechnicalWriter implements Writer{

	private Award award;

	@Autowired
	public TechnicalWriter(@Qualifier("pulitzerAward") Award award) {
		this.award = award;
	}
	@Override
	public void write() {

		System.out.println("Write technical stuffs...");
	}
	@Override
	public void getAward() {
		award.award();		
	}
}

//Writer.java

package com.studytonight.community;
public interface Writer {

	void write();
	void getAward();
}

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.studytonight</groupId>
  <artifactId>springproject</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
  <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
  <dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
  <build>
    <sourceDirectory>src</sourceDirectory>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>

  </build>
</project>

运行应用

成功地将这两个文件更新到项目中后,运行应用,您将获得如下输出。

写小说...
你获得了布克奖...



Spring @Bean注解

原文:https://www.studytonight.com/spring-framework/spring-bean-annotation

Spring @Bean 注解用于显式声明单个 bean,而不是 Spring 自动创建的。它将 bean 的声明从类定义中分离出来,让我们按照自己的选择创建和配置 bean。

配置文件(用@configuration 注解标记的文件)用于声明 bean,然后由 Spring 容器获取该 bean。我们举个例子来理解一下。在 AppConfig 文件中,我们使用@bean 注解创建了一个名为 manager 的 Bean。我们没有使用任何 XML 文件和<bean>标签来创建一个 bean,因为@Bean 注解本身就可以完成所有的工作。我们的项目包含以下文件。

  • 银行应用.java
  • AppConfig.java
  • Manager.java
  • Employee.java
  • pom.xml 文件

//app config . Java

这是一个 Java 配置文件,它是我们为基于 xml 的配置示例创建的 applicationContext.xml 文件的替代文件。@Configuration注解表示这不是一个简单的类,而是一个配置类,@ComponentScan注解用于表示我们 spring 项目中的组件位置。

package com.studytonight.community;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

	@Bean
	public Manager manager() {
		return new Manager();
	}
}

银行应用.java

该文件包含为我们的应用创建 IOC 容器的代码。AnnotationConfigApplicationContext 类用于为应用上下文创建对象。

package com.studytonight.community;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class BankApp {

	public static void main(String[] args) {

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		Employee employee = context.getBean("manager",Employee.class);
		employee.work();
		context.close();
	}
}

//Manager.java

这是另一个使用@Component注解标记并实现Employee接口的组件类。在这个类中,我们实现了一个设置器依赖注入。请参见,管理器类通过使用在设置器方法中实例化的 account 类对象来调用 account 类的方法。请看下面的例子。

package com.studytonight.community;

import org.springframework.stereotype.Component;

public class Manager implements Employee{

	public void work() {
		System.out.println("Manage the branch office");

	}
}

//Employee.java

这是一个包含doWork()抽象方法的界面Employee。每个实现这个接口的类都必须覆盖doWork()方法。

package com.studytonight.community;

public interface Employee {

	void work();

} 

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.studytonight</groupId>
  <artifactId>springApp</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>javax.annotation</groupId>
			<artifactId>javax.annotation-api</artifactId>
			<version>1.3.2</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<build>
		<sourceDirectory>src</sourceDirectory>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>

	</build>
</project>

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

管理分公司



Spring 读取属性文件

原文:https://www.studytonight.com/spring-framework/spring-read-property-file

如果我们在一个文件中有一些值(数据),并且想使用 bean 的获取器方法读取它们,那么就使用属性文件。属性文件用于包含 Spring 应用的属性值。

我们可以用它来保存 bean 的字段值。它使用。属性扩展名创建一个文件作为属性文件。

如何将属性文件加载到 Spring 应用中

为了加载属性文件,Spring 提供了@PropertySource注释和<context:property-placeholder>标记。如果您正在使用 XML,那么您可以使用<内容:属性-占位符>标记,否则使用注释来加载属性文件。例如,

XML 标记示例

使用这个标签进入 applicationContext.xml 加载属性文件。

content:property-placeholder location="classpath:filename.properties" />

注释示例

将此注释与配置类一起使用,以加载属性文件。

@PropertySource("classpath:manager.properties")

如何从属性文件中读取属性

要读取属性,使用@Value()注释或<property/>标记。Spring 允许使用 XML 和非 XML 配置。让我们看看语法

XML 标记示例

使用这个标签进入 applicationContext.xml 读取属性。

<property name="propertyName" value="${propertyValue}"> </property>

注释示例

将此注释用于类字段,并创建一个获取器方法。

@Value("{propertyName}")

用 Java 读取属性文件的示例

让我们创建一个示例来读取属性文件的属性。这个项目有以下几个 java 文件。

// 银行应用.java

该文件包含为我们的应用创建 IOC 容器的代码。AnnotationConfigApplicationContext 类用于为应用上下文创建对象。

在这里,我们使用获取器来读取管理器 bean 的属性。

package com.studytonight.community;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class BankApp {

	public static void main(String[] args) {

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		Manager employee = context.getBean(Manager.class);
		employee.work();
		System.out.println("Email: " + employee.getEmail());
		System.out.println("Id: " + employee.getId());
		context.close();
	}
}

//app config . Java

这是一个 Java 配置文件,它是我们为基于 xml 的配置示例创建的 applicationContext.xml 文件的替代文件。@Configuration注释表示这不是一个简单的类,而是一个配置类,@PropertySource注释用于表示属性文件在我们的 spring 项目中的位置。

package com.studytonight.community;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;

@Configuration
@PropertySource("classpath:manager.properties")
public class AppConfig {

	@Bean
	public Manager manager() {
		return new Manager();
	}
}

//Manager.java

这是一个使用@Component注释标记的组件类,实现了Employee接口。在这个类中,我们使用@Value 注释将字段映射到属性文件。看,我们创建了获取器来从属性文件中读取属性。请看下面的例子。

package com.studytonight.community;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class Manager implements Employee{

	@Value("${id}")
	private int id;
	@Value("${email}")
	private String email;

	public void work() {
		System.out.println("Manage the branch office");

	}
	public int getId() {
		return id;
	}
	public String getEmail() {
		return email;
	}
}

// manager.properties

这是我们的属性文件,包含两个带值的属性。

email=manager@studytonight.com
id=1025

//Employee.java

这是一个包含Work()抽象方法的界面Employee。实现此接口的每个类都必须重写此方法。

package com.studytonight.community;
public interface Employee {

	void work();
} 

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.studytonight</groupId>
  <artifactId>springApp</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>javax.annotation</groupId>
			<artifactId>javax.annotation-api</artifactId>
			<version>1.3.2</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<build>
		<sourceDirectory>src</sourceDirectory>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>

	</build>
</project>

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

管理分公司
manager@studytonight.com
1025



Spring 字段注入

原文:https://www.studytonight.com/spring-framework/spring-field-injection

Spring 主要使用两种类型的依赖注入:构造器注入和设置器注入,但是我们也可以使用另一种称为字段注入的注入技术。场注入可以通过直接在场上使用@Autowired注解来完成。

在本主题中,我们将使用基于字段的 DI 技术。该项目是一个基于 Maven 的 Spring 项目,包含以下文件。

  • App.java

  • AppConfig.java

  • Award.java

  • FictionWriter.java

  • TechnicalWriter.java

  • Writer.java

  • pom.xml 文件

项目结构:

//App.java

该文件包含为我们的应用创建 IOC 容器的代码。AnnotationConfigApplicationContext 类用于为应用上下文创建对象。

package com.studytonight.community;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class App {

	public static void main(String[] args) {

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		Writer writer = context.getBean("fictionWriter", Writer.class);
		writer.write();
		writer.getAward();
		// Close the context
		context.close();
	}
}

//app config . Java

这是一个 Java 配置文件,它是我们为基于 xml 的配置示例创建的 applicationContext.xml 文件的替代文件。@Configuration注释表示这不是一个简单的类,而是一个配置类,@ComponentScan 注释用于表示我们 spring 项目中组件类的位置。

package com.studytonight.community;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.studytonight.community")
public class AppConfig {

} 

//Award.java

这是一个将由 Spring IOC 容器读取的组件类。

package com.studytonight.community;

import org.springframework.stereotype.Component;

@Component
public class Award {

	public void award() {

		System.out.println("Your Writting got Award!");
	}
}

//FictionWriter.java

这是另一个组件类,它实现了 Writer 接口。这个类使用带有字段的@Autowired 注释来实现字段依赖注入,并且不创建设置器方法,只创建获取器方法。

package com.studytonight.community;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class FictionWriter implements Writer {

	@Autowired
	Award award;

	@Override
	public void write() {

		System.out.println("Write Fiction Novels...");
	}

	@Override
	public void getAward() {

		award.award();
	}

}

//TechnicalWriter.java

这是另一个组件类,它实现了 Writer 接口。这个类使用带有字段的@Autowired 注释来实现字段依赖注入,并且不创建设置器方法,只创建获取器方法。

package com.studytonight.community;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class TechnicalWriter implements Writer{

	@Autowired
	private Award award;

	@Override
	public void write() {

		System.out.println("Write technical stuffs...");
	}

	@Override
	public void getAward() {
		award.award();

	}
}

//Writer.java

它是一个包含两个方法的接口,实现它的每个类也必须实现它的方法。

package com.studytonight.community;

public interface Writer {

	void write();
	void getAward();
}

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.studytonight</groupId>
  <artifactId>springproject</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
  <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
  <dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
  <build>
    <sourceDirectory>src</sourceDirectory>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>

  </build>
</project>

写小说...
你的写作获奖了!



Spring 方法注入

原文:https://www.studytonight.com/spring-framework/spring-method-injection

与字段注入类似,Spring 允许方法依赖注入将依赖注入到 bean 中。Spring 主要使用两种类型的依赖注入:构造器注入和 Setter 注入,但是我们也可以使用另一种注入技术,称为方法注入。方法注入类似于设置器注入,只是方法可以是任何常规方法。它使用@Autowired注释将一个方法标记为方法注入。

在本主题中,我们使用的是基于方法的 DI 技术。该项目是一个基于 Maven 的 Spring 项目,包含以下文件。

  • App.java

  • AppConfig.java

  • Award.java

  • FictionWriter.java

  • TechnicalWriter.java

  • Writer.java

  • pom.xml 文件

项目结构:

//App.java

该文件包含为我们的应用创建 IOC 容器的代码。AnnotationConfigApplicationContext 类用于为应用上下文创建对象。

package com.studytonight.community;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class App {

	public static void main(String[] args) {

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		Writer writer = context.getBean("fictionWriter", Writer.class);
		writer.write();
		writer.getAward();
		// Close the context
		context.close();
	}
}

//app config . Java

这是一个 Java 配置文件,它是我们为基于 xml 的配置示例创建的 applicationContext.xml 文件的替代文件。@Configuration注释表示这不是一个简单的类,而是一个配置类,@ComponentScan 注释用于表示我们 spring 项目中组件类的位置。

package com.studytonight.community;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.studytonight.community")
public class AppConfig {

} 

//Award.java

这是一个将由 Spring IOC 容器读取的组件类。

package com.studytonight.community;

import org.springframework.stereotype.Component;

@Component
public class Award {

	public void award() {

		System.out.println("Your Writting got Award!");
	}
}

//FictionWriter.java

这是另一个组件类,它实现了 Writer 接口。这个类使用@Autowired 注释和方法来实现方法依赖注入,并且不创建设置器方法,只创建获取器方法。

package com.studytonight.community;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class FictionWriter implements Writer {

	Award award;

	@Autowired
	public void awardInstance(Award award) {
		this.award = award;
	}
	@Override
	public void write() {

		System.out.println("Write Fiction Novels...");
	}
	@Override
	public void getAward() {

		award.award();
	}
}

//TechnicalWriter.java

这是另一个组件类,它实现了 Writer 接口。这个类使用@Autowired 注释和方法来实现方法依赖注入,并且不创建设置器方法,只创建获取器方法。

package com.studytonight.community;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class TechnicalWriter implements Writer{

	private Award award;

	@Autowired
	public void awardInstance(Award award) {
		this.award = award;
	}
	@Override
	public void write() {

		System.out.println("Write technical stuffs...");
	}
	@Override
	public void getAward() {
		award.award();
	}
}

//Writer.java

它是一个包含两个方法的接口,实现它的每个类也必须实现它的方法。

package com.studytonight.community;

public interface Writer {

	void write();
	void getAward();
}

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.studytonight</groupId>
  <artifactId>springproject</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
  <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
  <dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
  <build>
    <sourceDirectory>src</sourceDirectory>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>

  </build>
</project>

写小说...
你的写作获奖了!



Spring 表达式语言

原文:https://www.studytonight.com/spring-framework/spring-expression-language

Spring 表达式语言是一种用于应用中查询的表达式语言。它是为了 p 的目的而设计的,以便为 Spring 框架提供一种支持良好的表达式语言。我们可以将它用于两种类型的配置 XML 和注释。它可以用来将一个 bean 或 bean 属性注入到另一个 bean 中。它是一组丰富的功能,允许以下特性。

  • 字面表达式

  • 变量

  • 布尔和关系运算符

  • 访问属性、数组、列表和映射

  • 方法调用

  • 关系运算符

  • 分配

  • 调用构造器

  • Bean 引用

  • 内嵌列表

  • 三元算子

举例的时间到了

让我们看一些在 spring 应用中使用表达式语言的有用例子。

文字表达的表达式语言

我们可以使用表达式语言来设置 bean 属性的文字值。看,我们用花括号括起文字值,并将其赋给 value 属性。我们也可以通过使用@Value 注释对 Java 代码做同样的事情。我们已经为两者添加了示例。

<!-- XML Code  -->
<bean id="user" class="com.studytonight.User">
  <property name="id" value = "#{'1021'}" />
</bean>

<!-- Java Code -->
package com.studytonight;
class User{
   @Value("#{1021}")
   int id;
   @Value("#{'Rohan'}")
   String name;
...
}

变量的表达式语言

我们可以在大括号内传递变量来设置属性的值。我们可以使用它通过解析变量从属性文件中获取值。

package com.studytonight;
class User{
   @Value("#{user.id}")
   int id;
   @Value("#{'user.name'}")
   String name;

...

}

运算符的表达式语言

表达式语言允许在表达式中使用运算符来设置值。您可以看到,在计算表达式后,将为属性设置一个布尔值。

package com.studytonight;
class Demo{
   @Value("#{a<b}")
   private boolean isGreater;

   @Value("#{a<b?true:false}")
   private boolean check;
...
}

方法调用的表达式语言

我们可以在大括号内调用任何方法,因为表达式语言允许方法调用特性使其更加动态。请看下面的例子。

package com.studytonight;
class User{
   @Value("#{user.id}")
   int id;
   @Value("#{'user.name'.toUpperCase()}")
   String name;
...
}

JSP 页面中的表达式语言

这是我们需要使用表达式语言时的大部分情况。Spring 与 JSP 一起工作,表达式语言在查询数据、制作动态表达式以及向用户显示动态数据方面表现良好。

<body>
<strong>Hello,</strong>
<h2>${user.name}</h2>
</body>


Spring MVC

Spring MVC 简介

原文:https://www.studytonight.com/spring-framework/spring-mvc-introduction

spring MVC 是一个 Spring 模块,用于使用 Spring 框架创建 web 应用。Spring 提供了一个源模块spring-webmvc来构建基于 MVC 的 web 应用。

什么是 MVC?

MVC 是一种用于创建应用的设计模式。MVC 代表模型、视图和控制器。它由三个组件模型、视图和控制器组成,在下面的架构中,我们可以看到 MVC 组件是如何交互和协同工作的。我们将在后面的教程中详细介绍 MVC 的每个组件,但是现在,我们可以将其理解为 Controller 是一个请求处理程序,它处理用户请求并响应请求的视图页面。视图是一个页面,可以是一个 HTML 或 JSP 页面,作为结果呈现,而模型表示数据库表,用于应用和数据库之间的数据处理。

Spring MVC 使用 Servlet Dispatcher 作为前端控制器,主要作为请求处理程序工作,也处理所有用户定义的控制器。

Spring MVC 架构

用户:用户是客户端-服务器架构中请求资源的客户端。

视图: 视图是 MVC 架构中的一个组件,代表一个 HTML/JSP 文件,由控制器随机生成。例如,

//hello.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello JSP</title>
</head>
<body>
<h1>Hello, Welcome to JSP</h1>
</body>
</html>

前端控制器:它是 Spring 框架的内置控制器,用于处理 web 应用的所有请求。Spring 的DispatcherServlet作为前置控制器工作。

模型:它是一个组件,是 MVC 架构的一部分,代表一个类。该模型用于编写业务逻辑和获取器、设置器方法。例如,

//User.java

package com.studytonight.models;

public class User {
	int id;
	String name;
	String lastName;
	String email;

	public User(int id, String name, String lastName, String email) {
		//super();
		this.id = id;
		this.name = name;
		this.lastName = lastName;
		this.email = email;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
}

控制器:用于处理 web 应用中的客户端请求。它接收来自用户的请求,并在与模型和数据库协调后发送所请求的视图。在 Spring 应用中,标记有@Controller 或@RestController 注释的类被视为控制器,可以用来处理请求和响应。例如,

package com.studytonight.controllers;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.studytonight.models.User;
import com.studytonight.service.UserService;

@Controller
public class UserController {

	@Autowired
	private UserService userService;

	@GetMapping("/users")
	@ResponseBody
	public void users() {
		List<User> users =  userService.getUser();
		for(User user: users) {
			System.out.println(user.getFirstName()+" "+user.getLastName()+" "+user.getEmail());
		}
	}
}

好了,到这里为止,希望你已经有了 MVC 的概念,以及 MVC 在 web 应用中是如何工作的。在下一个主题中,我们将介绍 MVC 组件和工作示例。



Spring MVC 视图

原文:https://www.studytonight.com/spring-framework/spring-mvc-view

视图是 MVC 架构的一个组件,用于响应用户请求向用户返回用户界面输出。视图页面可以是任何 HTML 或 JSP 文件。

Spring MVC 在内部使用视图解析器将请求的视图提取给用户。在 Spring 应用中有几种配置视图的方法。我们可以使用 XML、Java 代码和属性文件来配置视图。

Spring MVC 定义了ViewResolverView接口,允许您在浏览器中渲染模型,而无需将您与特定的视图技术联系起来。ViewResolver提供视图名称和实际视图之间的映射。View解决在移交给特定技术视图之前的数据准备。

视图解析器实现

以下是视图解析器接口的实现类。

|

视图解析器

|

描述

|
| --- | --- |
| 抽象视图解析器 | 此类用于缓存视图实例。缓存提高了某些视图技术的性能。虽然我们可以通过将 cache 属性设置为 false 来关闭缓存。 |
| XmlViewResolver | 这个类用于处理 XML 视图文件。它接受用 XML 编写的配置文件,与 Spring 的 XML bean 工厂具有相同的 DTD。 |
| ResourceBundleViewResolver | 它使用资源包中的 bean 定义,由包的基本名称指定。对于它应该解析的每个视图,它使用属性[viewname]的值。(类)作为视图类和属性[viewname]的值。url 作为视图 URL。 |
| UrlBasedViewResolver | 在没有显式映射定义的情况下,它会影响逻辑视图名称到 URL 的直接解析。 |
| InternalResourceViewResolver | 它是 UrlBasedViewResolver 的一个方便的子类,支持 InternalResourceView 和诸如 JstlView 和 TilesView 之类的子类。 |
| FreeMarkerViewResolver | 这个类是支持 FreeMarkerView 的 UrlBasedViewResolver 的子类。 |
| 内容协商视图解析器 | 它用于根据请求文件名解析视图。 |

Spring 视图解析器是如何工作的?

当用户请求视图时,控制器与视图解析器交互。视图解析器将请求的视图返回给控制器,然后控制器返回给用户。

在 Spring 配置视图

在 Spring 应用中有三种配置视图的方法。我们可以使用以下任何方式来配置视图:

  • 可扩展置标语言
  • Java 代码
  • 属性文件

使用 XML 标记配置视图

我们可以使用<bean>标签来设置类InternalResourceViewResolver<property>标签来设置视图页面的前缀和后缀。例如,前缀表示存储视图文件的包位置,后缀表示视图文件的扩展名。请参见下面的代码。

<!-- Define Spring MVC view resolver -->
<bean
	class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<property name="prefix" value="/WEB-INF/views/" />
	<property name="suffix" value=".jsp" />
</bean>

使用 Java 代码配置视图

我们可以通过向配置类添加一些代码来配置 Java 中的视图处理。标有@Configuration注释的类被视为配置类。您可以看到,我们使用了setPrefix()setSuffix()方法来代替 XML 文件的<property>标签。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
public class AppConfig {

	@Bean
	public ViewResolver viewResolver() {
		InternalResourceViewResolver irvr = new InternalResourceViewResolver();
		irvr.setPrefix("WEB-INF/views");
		irvr.setSuffix(".jsp");
		irvr.setOrder(0);
		return irvr;
	}
} 

使用属性文件配置视图

我们可以使用属性文件来设置视图配置,如前缀和后缀。

spring.mvc.view.prefix = /WEB-INF/views
spring.mvc.view.suffix = .jsp

创建之后,我们可以使用@PropertySource注释将其读入我们的应用。例如,

@PropertySource("classpath:views.properties")

在这里,视图是属性文件的名称。在下一个主题中,我们将看到一个简单的 Hello Spring 应用。



Spring MVC 你好世界应用

原文:https://www.studytonight.com/spring-framework/spring-mvc-hello-world-application

在本文中,我们将使用 Spring MVC 创建一个简单的 hello world 应用。我们创建了一个基于 maven 的 Spring 项目,它包含一个控制器、一个视图(JSP 文件)和一些 XML 文件。我们的项目如下图所示。

项目结构

项目文件源代码:

//HelloController.java

是一个控制器类文件,使用@Controller注解,返回一个索引 JSP 页面作为 MVC 的视图组件。

package com.studytonight.controller;

import org.springframework.stereotype.Controller;

@Controller
public class HelloController {

	public String hello() {
		return "index";
	}
} 

//spring-MVC-app-servlet . XML

这是一个配置文件,包含基本包定位器和InternalResourceViewResolver通过给视图(JSP)文件添加后缀和前缀来获取视图。

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

	<!-- Step 3: Add support for component scanning -->
	<context:component-scan base-package="com.studytonight.controller" />

	<!-- Step 4: Add support for conversion, formatting and validation support -->
	<mvc:annotation-driven/>

	<!-- Step 5: Define Spring MVC view resolver -->
	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/view/" />
		<property name="suffix" value=".jsp" />
	</bean>
</beans> 

// web.xml

当我们使用 Spring MVC 时,这个 XML 文件是必需的,用于配置前端控制器 DispatcherServlet 和应用上下文文件。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	id="WebApp_ID" version="3.1">

	<display-name>spring-mvc-app</display-name>

	<absolute-ordering />

	<!-- Spring MVC Configs -->

	<!-- Step 1: Configure Spring MVC Dispatcher Servlet -->
	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring-mvc-demo-servlet.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<!-- Step 2: Set up URL mapping for Spring MVC Dispatcher Servlet -->
	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

</web-app>

//index.jsp

这是一个视图文件,将由控制器返回给客户端。

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Hello Spring</title>
</head>
<body>
<p>Hello Welcome to Spring MVC</p>
</body>
</html>

输出:

运行该应用,您将在浏览器中获得如下输出。

Spring MVC 的无 XML 配置

在这种情况下,我们希望仅使用 Java 代码(无 XML)配置 Dispatcher servelet,然后将以下文件包含到您的项目中,并删除spring-MVC-app-servlet . XMLweb.xml 文件。

项目结构

配置文件有以下源代码。

//MyWebInitializer.java

这个类类似于 web.xml,用于为 Spring 应用配置 DispatcherServlet。getServletConfigClasses()方法用于加载 AppConfig.java 类。

package com.studytonight.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class MyWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

	@Override
	protected Class<?>[] getRootConfigClasses() {
		// TODO Auto-generated method stub
		return null;
	}

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

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

//app config . Java

这类似于我们配置视图文件的应用上下文。在这里,我们使用了InternalResourceViewResolver类及其方法setPrefix()setSuffix()来配置视图文件。

package com.studytonight.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@EnableWebMvc
public class AppConfig {
	// define a bean for ViewResolver
	@Bean
	public ViewResolver viewResolver() {
		InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
		viewResolver.setPrefix("/WEB-INF/view/");
		viewResolver.setSuffix(".jsp");
		return viewResolver;
	}
}

将这些文件添加到项目中并运行项目。它将产生类似的输出。



Spring MVC 处理表单数据

原文:https://www.studytonight.com/spring-framework/spring-mvc-handling-form-data

在本文中,我们将创建一个 Spring 应用,并将 HTML 表单数据提取到 JSP 页面中。

我们将使用参数隐式对象来获取表单数据。下面是我们的项目结构,显示了我们项目中可用的文件。

项目结构

// HelloController.java

这是一个控制器类,包含两种方法showForm()showdata()showForm()方法与用户表单请求映射,用于返回用户表单。

package com.studytonight.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class HelloController {

	@RequestMapping(value = "userform", method = RequestMethod.GET)
	public String showForm() {
		return "user-form";
	}	

	@RequestMapping(value = "showdata", method = RequestMethod.GET)
	public String showdata() {
		return "user-data";
	}
}

//user-form.jsp

这是我们的 HTML 表单页面,它接受用户输入,并在 showdata mapping 处将其提交给服务器。该请求将由控制器(家庭控制器)处理。

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>User Form</title>
</head>
<body>
<form action="showdata" method="Get">
	<input type="text" name="user_name"><br/><br/>
	<input type="submit" />
</form>
</body>
</html>

//user-data.jsp

此页面显示用户以 HTML 形式输入的输入。控制器将此页面作为响应返回给客户端。该页面使用表达式语言获取用户表单数据。这里,参数是一个包含所有请求数据的 JSP 隐式对象。

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Hello JSP</title>
</head>
<body>
<strong>Hello,</strong>
${param.user_name}
</body>
</html>

这些是 Spring 配置 XML 文件,配置视图文件和 dispatcher servlet,为应用提供一个前端控制器。

//spring-MVC-app-servlet . XML

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

	<!-- Step 3: Add support for component scanning -->
	<context:component-scan base-package="com.studytonight.controller" />

	<!-- Step 4: Add support for conversion, formatting and validation support -->
	<mvc:annotation-driven/>

	<!-- Step 5: Define Spring MVC view resolver -->
	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/views/" />
		<property name="suffix" value=".jsp" />
	</bean>
</beans> 

// web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	id="WebApp_ID" version="3.1">

	<display-name>spring-mvc-app</display-name>

	<absolute-ordering />

	<!-- Spring MVC Configs -->

	<!-- Step 1: Configure Spring MVC Dispatcher Servlet -->
	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring-mvc-app-servlet.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<!-- Step 2: Set up URL mapping for Spring MVC Dispatcher Servlet -->
	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

</web-app>

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>spring-mvc-app</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.10.0.pr3</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.3.0</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.3</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。输入用户名后提交表单。

这是显示上述用户名提交的用户名的第二个 JSP 页面。



向 Spring 模型添加数据

原文:https://www.studytonight.com/spring-framework/adding-data-to-spring-model

在本文中,我们将向 Spring 模型添加数据。Spring Model是 Spring 中的一个界面,用来给模型添加属性。它提供了几种方法来处理从控制器到视图的数据。

主要用于将数据从控制器传到查看页面。让我们通过例子来理解。

模型接口方法

以下是模型界面的方法。

| 修饰符和类型 | 方法和描述 |
| 模型添加属性(集合>属性值) | 此方法用于将所提供集合中的所有属性复制到此地图中,并为每个元素生成属性名。 |
| 模型添加属性(映射属性) | 它将所提供地图中的所有属性复制到该地图中。 |
| 模型添加属性(对象属性值) | 它使用生成的名称将提供的属性添加到此地图。 |
| 模型添加属性(字符串属性名,对象属性值) | 它在提供的名称下添加提供的属性。 |
| 地图〔t0〕asmap() | 它将当前模型属性集作为地图返回。 |
| 布尔包含属性(字符串属性名) | 如果此模型包含给定名称的属性,则返回 true,否则返回 false。 |
| 对象 getAttribute(字符串属性名) | 它返回给定名称的属性值(如果有)。 |
| 模型合并属性(映射属性) | 它将所提供地图中的所有属性复制到该地图中,具有相同名称的现有对象优先。 |

项目结构

// HelloController.java

这是一个控制器类,包含两种方法showForm()showdata()showForm()方法与用户表单请求映射,用于返回用户表单。这里,我们使用 Spring Model 将 user_name 传递给 view(user-data.jsp)。

package com.studytonight.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class HelloController {

	@RequestMapping("userform")
	public String showForm() {
		return "user-form";
	}	

	@RequestMapping(value = "showdata", method = RequestMethod.GET)
	public String showdata(HttpServletRequest request, Model model) {
		String name = request.getParameter("user_name");
		model.addAttribute("name",name);
		return "user-data";
	}
}

//user-form.jsp

这是我们的 HTML 表单页面,它接受用户输入,并在 showdata mapping 处将其提交给服务器。该请求将由控制器(HelloController)处理。

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>User Form</title>
</head>
<body>
<form action="showdata" method="Get">
	<input type="text" name="user_name"><br/><br/>
	<input type="submit" />
</form>
</body>
</html>

//user-data.jsp

此页面显示用户以 HTML 形式输入的输入。控制器将此页面作为响应返回给客户端。该页面使用表达式语言获取用户表单数据。这里,我们使用了在控制器中绑定的属性名称作为 model.addAttribute(“名称”,name) 。我们在这里没有像在上一篇文章中那样使用参数

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Form</title>
</head>
<body>
<strong>Hello,</strong>
${name}
</body>
</html>

这些是 Spring 配置 XML 文件,配置视图文件和 dispatcher servlet,为应用提供一个前端控制器。

//spring-MVC-app-servlet . XML

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

	<!-- Step 3: Add support for component scanning -->
	<context:component-scan base-package="com.studytonight.controller" />

	<!-- Step 4: Add support for conversion, formatting and validation support -->
	<mvc:annotation-driven/>

	<!-- Step 5: Define Spring MVC view resolver -->
	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/views/" />
		<property name="suffix" value=".jsp" />
	</bean>
</beans> 

// web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	id="WebApp_ID" version="3.1">

	<display-name>spring-mvc-app</display-name>

	<absolute-ordering />

	<!-- Spring MVC Configs -->

	<!-- Step 1: Configure Spring MVC Dispatcher Servlet -->
	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring-mvc-app-servlet.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<!-- Step 2: Set up URL mapping for Spring MVC Dispatcher Servlet -->
	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

</web-app>

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>spring-mvc-app</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.10.0.pr3</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.3.0</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.3</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

这是显示上述用户名提交的用户名的第二个 JSP 页面。



Spring @RequestParam注解

原文:https://www.studytonight.com/spring-framework/spring-requestparam-annotation

Spring @RequestParam注解用于获取表单请求中某个参数的值。在 Spring MVC 中,“请求参数”映射到查询参数,形成数据。

例如,如果我们想从请求的网址获取参数(用户名)值,那么我们可以使用 @RequestParam注解。我们只需要提供一个参数名。

http://localhost:8080/spring-mvc-app/showdata?user_name=studytonight

在上面的网址中,参数是:用户名值:今晚学习,我们可以在我们的应用中获取它,如下所示:

@RequestMapping("showdata")
public String userForm(@RequestParam("user_name") String name, Model model)
{
	model.addAttribute("name", name);
	return "user-data";		
}

@RequestParam注解使用了名称必填默认值等多个属性。我们可以根据用例在我们的应用中使用它们。

默认值属性

为参数设置默认值,以避免空值。我们可以使用这个属性来处理缺失的值。如果参数不包含任何值,则将提供该默认值。

@RequestMapping("showdata")
public String userForm(@RequestParam(defaultValue = "No_value") String name, Model model)
{
	model.addAttribute("name", name);
	return "user-data";		
}

必需属性

必要的属性用于在数据丢失的情况下处理异常。它抛出 HTTP 状态 400–错误请求(必需的字符串参数‘user _ name’不存在)。为了避免这种异常,我们可以使用必需的属性。

@RequestMapping("showdata")
public String userForm(@RequestParam(required = false) String name, Model model)
{
	model.addAttribute("name", name);
	return "user-data";		
}

Java 8 可选类

我们可以使用Optional类,通过提供一个值来避免数据丢失时的异常。它类似于默认属性,但如果您使用的是 java 8 或更高版本,则可以使用它。

@RequestMapping("showdata")
public String userForm(@RequestParam Optional<String> name, Model model)
{
    String name1 = name.orElseGet(()->"no value found"); 
	model.addAttribute("name", name1);
	return "user-data";		
}

@RequestParam 属性

以下是@RequestParam 注解的属性列表。

|

类型和元素

|

描述

|
| 字符串默认值 | 此元素用于为参数设置默认值。 |
| 字符串名称 | 它指示要绑定到的请求参数的名称。 |
| 布尔型必填 | 用于设置参数是否为必选项。 |
| 字符串值 | 它类似于 name 元素,可以用作别名。 |

Spring @RequestParam 注解工作示例

让我们通过示例来理解,并创建一个基于 maven 的 Spring 应用并添加这些文件。之后,使用网络服务器(Apache Tomcat)运行这个示例。查看项目的源代码。

// HelloController.java

是一个使用@Controller注解的控制器类文件。它显示一个用户表单,并通过提交该表单显示用户输入的数据。

package com.studytonight.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class HelloController {

	@RequestMapping("/")
	public String showForm() {
		return "user-form";
	}

	@RequestMapping("showdata")
	public String userForm(@RequestParam("user_name") String name, Model model)
	{
			model.addAttribute("name", name);
			return "user-data";		
	}
}

//user-form.jsp

它是一个 JSP 页面,显示一个 HTML 表单来获取用户信息。

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>User Form</title>
</head>
<body>
<form action="showdata" method="Get">
	<label>Enter User Name: </label><input type="text" name="user_name"><br/><br/>
	<input type="submit" />
</form>
</body>
</html>

//user-data.jsp

这个 JSP 页面显示了用户提交的数据。

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Hello JSP</title>
</head>
<body>
<strong>Hello,</strong>
${name}
</body>
</html>

//spring-MVC-app-servlet . XML

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

	<!-- Step 3: Add support for component scanning -->
	<context:component-scan base-package="com.studytonight.controller" />

	<!-- Step 4: Add support for conversion, formatting and validation support -->
	<mvc:annotation-driven/>

	<!-- Step 5: Define Spring MVC view resolver -->
	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/views/" />
		<property name="suffix" value=".jsp" />
	</bean>
</beans> 

// web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	id="WebApp_ID" version="3.1">

	<display-name>spring-mvc-app</display-name>

	<absolute-ordering />

	<!-- Spring MVC Configs -->

	<!-- Step 1: Configure Spring MVC Dispatcher Servlet -->
	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring-mvc-app-servlet.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<!-- Step 2: Set up URL mapping for Spring MVC Dispatcher Servlet -->
	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

</web-app>

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>spring-mvc-app</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.3.0</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.3</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

这是显示上述用户名提交的用户名的第二个 JSP 页面。



Spring @ModelAttribute注解

原文:https://www.studytonight.com/spring-framework/spring-modelattribute-annotation

Spring @ModelAttribute注解用于将方法参数或方法返回值绑定到一个命名的模型属性,该属性还可以在视图页面中使用。

它可以在方法级别或方法参数级别使用。

@方法级别的模型属性

我们可以在方法级别使用这个注解来指定这个方法可以添加一个或多个模型属性。

@PostMapping("save")
@ModelAttribute("user") 
public String save(User user, Model model) {	
	model.addAttribute("user", user);
	return "response";
}

@方法参数处的模型属性

我们可以将它与方法参数一起使用,该参数指示应该从模型中检索该参数。如果参数不存在,那么首先应该将其实例化,然后添加到模型中。

在这个例子中,我们在参数中使用了@ModelAttribute

@PostMapping("save")
public String save(@ModelAttribute("user") User user, Model model) {	
	model.addAttribute("user", user);
	return "response";
}

举个例子

让我们通过例子来理解。在这里,我们创建了一个 Spring MVC 应用,并在它的控制器类中使用了@ModelAttribute 注解。

下面是我们项目的源文件,AppConfig 和 MainApp 都是 Spring MVC 的配置文件。

//app config . Java

这是我们的应用配置文件,它实现了WebMvcConfugurer接口来制作这个 MVC 应用,并创建了一个方法 viewResolver 来映射我们的视图文件(JSP)。

package com.studytonight;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@ComponentScan("com.studytonight")
public class AppConfig implements WebMvcConfigurer{
	@Bean
	public ViewResolver viewResolver() {
		InternalResourceViewResolver irvr = new InternalResourceViewResolver();
		irvr.setPrefix("WEB-INF/views/");
		irvr.setSuffix(".jsp");
		irvr.setOrder(0);
		return irvr;
	}
}

//main app . Java

这个类初始化我们的网络应用,并通过注册我们的 AppConfig 类来创建ServletContext(上图文件)。

package com.studytonight;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

public class MainApp implements WebApplicationInitializer {

	@Override
	public void onStartup(ServletContext servletContext) throws ServletException { 
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
		context.register(AppConfig.class);
		context.setServletContext(servletContext);
		ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
		servlet.setLoadOnStartup(1);
		servlet.addMapping("/");
		context.close();	

	}
}

//user controller . Java

这是我们的控制器类,我们在其中使用@ModelAttribute 和方法参数将模型数据提取到视图文件中。

package com.studytonight.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

import com.studytonight.model.User;

@Controller
public class UserController {

	@GetMapping("/")
	public String index(Model model) {
		model.addAttribute("user", new User());
		return "index";
	}

	@PostMapping("save")
	public String save(@ModelAttribute("user") User user, Model model) {	
		model.addAttribute("user", user);
		return "response";
	}
}

//User.java

package com.studytonight.model;

public class User {

	private int id;
	private String name;
	private String email;
	private String password;
	private String confirm_password;

	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getConfirm_password() {
		return confirm_password;
	}
	public void setConfirm_password(String confirm_password) {
		this.confirm_password = confirm_password;
	}
} 

//index.jsp

在这个 JSP 页面中,我们使用 modelAttribute 与@ModelAttribute 参数进行映射,将表单数据与模型绑定在一起。

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>User Form</title>
</head>
<body>
	<form:form action="save" method="post" modelAttribute="user">
		User Name: <form:input type="text" path="name" />
		<br>
		<br>
		Email: <form:input type="email" path="email" style="margin-left:34px;" />
		<br>
		<br> 
		Password: <form:input type="password" path="password"  style="margin-left:10px;" />
		<br>
		<br>
		Confirm Password: <form:input type="password" path="confirm_password" />
		<br>
		<br>
		<input type="submit" value="Register">
	</form:form>
</body>
</html>

//response.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Response User Data</title>
</head>
<body>
	<h2>${user.name}</h2>
	<p>Email: ${user.email}</p>
	<p>Password: ${user.password}</p>
</body>
</html>

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>springmvc</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.3.0</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.3</version>
				<configuration>
                    <source>11</source>
                    <target>11</target>
                </configuration>
			</plugin>
		</plugins>
	</build>
</project>

运行应用

成功完成项目并添加依赖项后,使用服务器运行应用,您将获得如下输出。

输入用户信息

检索数据



Spring MVC 和 Thymeleaf

原文:https://www.studytonight.com/spring-framework/spring-mvc-with-thymeleaf

在本文中,我们将学习在我们的 Spring 应用中使用 Thymeleaf。Thymeleaf 是一个模板引擎,用于在 Spring MVC 中创建视图页面。它提供了完整的 Spring 集成,旨在取代 JSP 成为 Spring MVC 中的视图页面。如果您正在使用网络应用,最好使用 Thymeleaf。

它可以在网络和非网络应用中工作,甚至可以在离线环境中处理任何 XML 文件。要在您的项目中使用 Thymeleaf,只需将这个依赖项添加到您的 pom.xml 文件中。

<dependency>
	<groupId>org.thymeleaf</groupId>
	<artifactId>thymeleaf-spring5</artifactId>
	<version>3.0.11.RELEASE</version>
</dependency>

让我们通过一个创建基于 maven 的 spring 项目的例子来理解。我们的项目结构包含几个文件,如下所示。

项目结构

//app config . Java

这是一个 Java 配置文件,它是我们为基于 xml 的配置示例创建的 applicationContext.xml 文件的替代文件。@Configuration注释表示这不是一个简单的类,而是一个配置类,@ComponentScan 注释用于表示我们 spring 项目中组件类的位置。

package com.studytonight;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;

import com.studytonight.models.User;

@EnableWebMvc
@Configuration
@ComponentScan("com.studytonight.controller")
public class AppConfig implements WebMvcConfigurer{

	@Autowired
	ApplicationContext applicationContext;

	@Bean
	public ViewResolver thymeleafResolver() {
		ThymeleafViewResolver ivr = new ThymeleafViewResolver();
		ivr.setTemplateEngine(templateEngine());
		ivr.setOrder(0);
		return ivr;
	}

	@Bean
	public SpringResourceTemplateResolver templateResolver() {
		SpringResourceTemplateResolver srtr = new SpringResourceTemplateResolver();
		srtr.setApplicationContext(applicationContext);
		srtr.setPrefix("/WEB-INF/views/");
		srtr.setSuffix(".html");
		return srtr;
	}

	@Bean
	public SpringTemplateEngine templateEngine() {
		SpringTemplateEngine templateEngine = new SpringTemplateEngine();
		templateEngine.setTemplateResolver(templateResolver());
		templateEngine.setEnableSpringELCompiler(true);
		return templateEngine;
	}

}

//main app . Java

该文件包含为我们的应用创建 IOC 容器的代码。AnnotationConfigApplicationContext类用于为应用上下文创建一个对象。

package com.studytonight;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
public class MainApp implements WebApplicationInitializer {

	@Override
	public void onStartup(ServletContext servletContext) throws ServletException { 
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
		context.register(AppConfig.class);
		context.setServletContext(servletContext);
		ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
		servlet.setLoadOnStartup(1);
		servlet.addMapping("/");
		context.close();	
	}
} 

//HomeController.java

这是一个控制器类,包含两种方法showForm()showdata()showForm()方法与用户表单请求映射,用于返回用户表单。这里,我们使用 Spring Model 将 user_name 传递给 view(user-data.jsp)。

package com.studytonight.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import com.studytonight.models.User;

@Controller
public class HomeController {

	@RequestMapping("/index")
	public String hello() {		
		return "index";
	}

	@RequestMapping("/thymeleaf")
	public String thyme(Model model) {
		model.addAttribute("user", new User());
		return "thyme";
	}
}

//User.java

它是我们的用户 bean 类,包含获取器和设置器方法。

package com.studytonight.models;
public class User {

	int id;
	String user_name;
	String email;

	public String getUser_name() {
		return user_name;
	}
	public void setUser_name(String user_name) {
		this.user_name = user_name;
	}

	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
}

//thyme.html

这是一个使用 Thymeleaf 库显示表单的 HTML 文件。这里,我们使用<html xmlns:th="http://www.thymeleaf.org">标签在我们的 HTML 页面中包含 Thymeleaf。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Spring Thymeleaf</title>
</head>
<body>
<h2>User Form</h2>
<label>Enter User Name</label><br>
<input type="text" th:field="*{user.user_name}" /><br><br>
<label>Enter Email</label><br>
<input type="email" th:field="*{user.email}" /><br><br>
<input type="submit">
</body>
</html>

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>springmvc</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf -->
		<dependency>
			<groupId>org.thymeleaf</groupId>
			<artifactId>thymeleaf-spring5</artifactId>
			<version>3.0.11.RELEASE</version>
		</dependency>

	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<build>
		<sourceDirectory>src</sourceDirectory>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.3</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。



Spring MVC 表单验证

原文:https://www.studytonight.com/spring-framework/spring-mvc-form-validation

在本文中,我们将学习如何在服务器端验证用户数据。这是我们在创建 web 应用时需要执行的基本任务之一。

为了以有效的形式获取用户数据,我们需要在客户端或服务器端或者两者都验证它。Spring 提供了一个@Valid注释来获取有效的表单数据,并使用 Hibernate Validator API 来验证数据。

Hibernate Validator 是 Spring 框架中用于 Bean 验证的实现 API。它提供了几个注释,以便与 Java 代码进行简单明了的验证集成。它适用于服务器和客户端应用编程。

Hibernate 验证器注释

以下是 Spring 应用中用于数据验证的常用注释。

|

注释

|

描述

|
| @NotNull | 它确定该值不能为空。 |
| @Min | 它确定该数字必须等于或大于指定值。 |
| @Max | 它确定该数字必须等于或小于指定值。 |
| @大小 | 它确定大小必须等于指定的值。 |
| @模式 | 它确定序列遵循指定的正则表达式。 |
| @电子邮件 | 它检查指定的字符序列是否是有效的电子邮件地址。 |
| @NotEmpty | 它检查带注释的元素是否不为空。 |
| @Null | 它检查带注释的值是否为空。 |
| @否定 | 它检查元素是否严格为负。零值被视为无效。 |
| @否定零 | 它检查元素是负的还是零。 |

如果您正在使用 maven 项目,那么将以下依赖项添加到 pom.xml 文件中。关于最新的 hibernate 验证器依赖,你可以访问它的官方网站

<dependency>
	<groupId>org.hibernate.validator</groupId>
	<artifactId>hibernate-validator</artifactId>
	<version>6.1.1.Final</version>
</dependency>

Spring MVC 表单验证示例

让我们通过示例来理解,并创建一个基于 maven 的 Spring 项目并添加这些文件。之后,使用网络服务器(Apache Tomcat)运行这个例子。见下面项目的源代码。

//HomeController.java

是一个使用@Controller注解的控制器类文件。它有两种方法,一种用于显示用户表单,另一种用于验证提交的用户表单。

package com.studytonight.controllers;
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.studytonight.models.UserForm;

@Controller
public class HomeController {

	@GetMapping("/userform")
	public String index(@ModelAttribute("registration") UserForm registration) {		
		return "index";
	}

	@PostMapping("/userform")
	public String register(@Valid @ModelAttribute("registration") UserForm registration, BindingResult result) {
		if (result.hasErrors()) {
			System.out.println("error");
			return "index";
		}
		return "success";
	}
}

//main app . Java

该文件包含为我们的应用创建 IOC 容器的代码。AnnotationConfigWebApplicationContext类用于为应用上下文创建一个对象。

package com.studytonight;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
public class MainApp implements WebApplicationInitializer {

	@Override
	public void onStartup(ServletContext servletContext) throws ServletException { 
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
		context.register(AppConfig.class);
		context.setServletContext(servletContext);
		ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
		servlet.setLoadOnStartup(1);
		servlet.addMapping("/");
		context.close();	
	}
} 

//app config . Java

这是一个配置文件,它是我们为基于 xml 的配置示例创建的 applicationContext.xml 文件的替代文件。@Configuration注释表示这不是一个简单的类,而是一个配置类,@ComponentScan 注释用于表示我们 spring 项目中组件类的位置。

package com.studytonight;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@EnableWebMvc
@Configuration
@ComponentScan("com.studytonight.controllers")
public class AppConfig implements WebMvcConfigurer{

	@Autowired
	ApplicationContext applicationContext;

	@Bean
	public ViewResolver viewResolver() {
		InternalResourceViewResolver ivr = new InternalResourceViewResolver();
		ivr.setPrefix("/WEB-INF/views/");
		ivr.setSuffix(".jsp");
		ivr.setOrder(0);
		return ivr;
	}
}

//index.jsp

这是一个 JSP 文件,包含一个在应用运行时显示的 HTML 表单。

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>User Form</title>
<style type="text/css">
.error {
	color: #ff0000;
}

.errorblock {
	color: #000;
	background-color: #ffEEEE;
	border: 3px solid #ff0000;
	padding: 8px;
	margin: 16px;
}
</style>
</head>
<body>
	<form:form modelAttribute="registration">
		<form:errors path="*" cssClass="errorblock" element="div" />
		<br>
		<label>Enter User Name </label>
		<br>
		<br>
		<form:input path="name" />
		<br>
		<br>
		<label>Enter Email </label>
		<br>
		<br>
		<form:input path="email" />
		<br>
		<br>
		<input type="submit" value="Register">
		<br>
	</form:form>
</body>
</html>

//success.jsp

如果用户表单验证成功,这个 JSP 文件将显示为一个响应。

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h2>Registered Successfully</h2>
</body>
</html>

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>springmvc</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
		<groupId>org.hibernate.validator</groupId>
		<artifactId>hibernate-validator</artifactId>
		<version>6.1.1.Final</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<build>
		<sourceDirectory>src</sourceDirectory>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.3</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

//user form . Java

package com.studytonight.models;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
public class UserForm {

	@NotEmpty(message = "Name can not empty")
	String name;
	String lastName;
	@NotEmpty(message = "Email can not empty")
	@Email
	String email;

	public UserForm(String name, String lastName, String email) {
		this.name = name;
		this.lastName = lastName;
		this.email = email;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
}

运行应用

成功完成项目并添加依赖项后,使用服务器运行应用,您将获得如下输出。

提交空表单:空表单验证

电子邮件错误:电子邮件验证

提供正确的信息

表单提交成功



Spring MVC 表单标签

原文:https://www.studytonight.com/spring-framework/spring-mvc-form-tags

Spring 提供了一个表单标签库来使用 JSP 实现视图页面。它提供了用于创建 HTML 组件、错误消息、主题和国际化消息的标签。当您使用 Spring MVC 时,它非常有用。

它是一个内置的库,因此我们可以通过使用以下标签在 JSP 页面上使用它:

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>

添加这个标签后,我们可以使用表单前缀创建一个 HTML 表单。例如,要创建一个输入文本,我们可以这样使用它:

<form:input type="text" path="name" />

它相当于下面的 HTML 代码。

<input id="name" name="name" type="text" value=""/>

Spring MVC 表单标签列表

Spring 提供了以下标签,可用于在应用中创建表单。

| 表单标签 | 描述 | 例子 |
| 表单:表单 | 它是一个表单标签,用于创建一个 HTML 表单。 |

<form:form action="save" method="post" modelAttribute="user">

|
| 表单:输入 | 这是一个用于创建文本字段的输入标签。 |

<form:input type="text" path="name" />

|
| 表单:单选按钮 | 这是一个用于创建单选按钮的单选标签。 |

<form:radiobutton path="choice" />

|
| 表单:复选框 | 这是一个用于创建复选框的复选框标签。 |

<form:checkbox path="india" value="91"/>

|
| 表单:密码 | 它是一个输入标签,用于创建密码输入字段。 |

<form:input type="password" path="password" />

|
| 表单:选择 | 这是一个用于创建下拉列表的选择标记。 |

<form:select path="country_names" />

|
| 表单:文本区域 | 该标签用于生成多行文本字段。 |

<form:textarea path="name" col="5" row="2" />

|
| 表单:隐藏 | 这是一个用于创建隐藏输入字段的输入标签。 |

<form:hidden path="name" />

|
| 球衣 | 这是一个选项标签,用于创建一个单一的 HTML 选项。 |

<form:select path="name" value="1">
    <form:option value="1">1</form:option>
	<form:option value="2">2</form:option>
</form:select>

|
| 表单:标签 | 这是一个标签标签,用于创建表单域标签标签。 |

<form:label path="contact">Contact</form:label>

|

举例时间:

让我们创建一个基于 maven 的 Spring 示例,使用 Spring 表单标签库生成表单。在这里,我们已经给出了我们项目的一些基本源文件。您可以参考它们来了解 Spring 表单标签库。给定的类文件是我们配置 MVC 应用及其视图的配置文件。

package com.studytonight;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@ComponentScan("com.studytonight")
public class AppConfig implements WebMvcConfigurer{
	@Bean
	public ViewResolver viewResolver() {
		InternalResourceViewResolver irvr = new InternalResourceViewResolver();
		irvr.setPrefix("WEB-INF/views/");
		irvr.setSuffix(".jsp");
		irvr.setOrder(0);
		return irvr;
	}
}

//main app . Java

正是我们的 ServlertDispatcher 类创建了应用上下文并注册了我们的配置类。

package com.studytonight;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
public class MainApp implements WebApplicationInitializer {

	@Override
	public void onStartup(ServletContext servletContext) throws ServletException { 
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
		context.register(AppConfig.class);
		context.setServletContext(servletContext);
		ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
		servlet.setLoadOnStartup(1);
		servlet.addMapping("/");
		context.close();	
	}
}

//user controller . Java

这是一个控制器类,包含两个方法 index()和 save(),index()用于呈现包含使用 Tag 库创建的用户表单的 JSP 页面,第二个方法返回另一个显示用户输入的数据的 JSP 页面。

package com.studytonight.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import com.studytonight.model.User;

@Controller
public class UserController {

	@GetMapping("/")
	public String index(Model model) {
		model.addAttribute("user", new User());
		return "index";
	}

	@PostMapping("save")
	public String save(@ModelAttribute("user") User user, Model model) {
		model.addAttribute("user", user);
		return "response";
	}
}

//User.java

它是一个 bean 类,用于保存应用中的用户数据。

package com.studytonight.model;

public class User {

	private int id;
	private String name;
	private String email;
	private String password;
	private String confirm_password;

	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getConfirm_password() {
		return confirm_password;
	}
	public void setConfirm_password(String confirm_password) {
		this.confirm_password = confirm_password;
	}
}

查看文件

在这里,您可以看到我们在 JSP 页面中使用 Spring 标签库创建了一个用户表单。我们使用了几个标签,如文本框、电子邮件、密码框等。

//index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>User Form</title>
</head>
<body>
	<form:form action="save" method="post" modelAttribute="user">
		User Name: <form:input type="text" path="name" />
		<br>
		<br>
		Email: <form:input type="email" path="email" style="margin-left:34px;" />
		<br>
		<br> 
		Password: <form:input type="password" path="password"  style="margin-left:10px;" />
		<br>
		<br>
		Confirm Password: <form:input type="password" path="confirm_password" />
		<br>
		<br>
		<input type="submit" value="Register">
	</form:form>
</body>
</html>

//response.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Response User Data</title>
</head>
<body>
	<h2>${user.name}</h2>
	<p>Email: ${user.email}</p>
	<p>Password: ${user.password}</p>
</body>
</html>

运行应用

成功完成项目并添加依赖项后,使用服务器运行应用,您将获得如下输出。

使用表单标签创建的用户表单

输入用户信息

检索数据

//response.jsp 文件



Spring MVC 重定向

原文:https://www.studytonight.com/spring-framework/spring-mvc-redirect

在本文中,我们将学习通过在控制器类中使用前缀重定向:来将请求从一个动作重定向到另一个动作。这取决于应用流和重定向请求的场景。在这里,我们将在保存记录后将表单请求重定向到另一个操作。我们可以这样使用:redirect:action_name.

它是我们控制器的一部分,所以将在我们的控制器类中执行。让我们通过一个例子来理解,创建一个基于 maven 的 spring 项目,并在其中添加这些文件。

我们提供源代码文件,因此您可以在项目中使用它们来理解这个概念。请参见以下源代码文件。

//user controller . Java

这是我们的控制器类,包含三个方法 index()、save()和 userSaved()。这里,第一个方法返回一个用户表单,第二个方法保存并重定向到第三个方法,第三个方法简单返回一个响应视图页面。

package com.studytonight.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

@Controller
public class UserController {

	@GetMapping("/")
	public String index() {
		return "index";
	}

	@PostMapping("save")
	public String save( ) {
        // data saving stuffs
		return "redirect:user_saved"; // it redirects to other action
	}

	@GetMapping("user_saved")
	public String userSaved() {
		return "response";
	}
}

//app config . Java

这是一个配置文件,它是我们为基于 xml 的配置示例创建的 applicationContext.xml 文件的替代文件。@Configuration注释表示这不是一个简单的类,而是一个配置类,@ComponentScan 注释用于表示我们 spring 项目中组件类的位置。

package com.studytonight;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@ComponentScan("com.studytonight")
public class AppConfig implements WebMvcConfigurer{
	@Bean
	public ViewResolver viewResolver() {
		InternalResourceViewResolver irvr = new InternalResourceViewResolver();
		irvr.setPrefix("WEB-INF/views/");
		irvr.setSuffix(".jsp");
		irvr.setOrder(0);
		return irvr;
	}
}

//main app . Java

该文件包含为我们的应用创建 IOC 容器的代码。AnnotationConfigWebApplicationContext类用于为应用上下文创建一个对象。

package com.studytonight;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

public class MainApp implements WebApplicationInitializer {

	@Override
	public void onStartup(ServletContext servletContext) throws ServletException { 
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
		context.register(AppConfig.class);
		context.setServletContext(servletContext);
		ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
		servlet.setLoadOnStartup(1);
		servlet.addMapping("/");
		context.close();	

	}
}

查看页面

//index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>User Form</title>
</head>
<body>
	<form action="save" method="post">
		User Name: <input type="text" name="user_name"><br><br>
		 Email: <input type="email" name="email"><br> <br>
		 <input type="submit" value="Register">
	</form>
</body>
</html>

//response.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Response User Data</title>
</head>
<body>
    <h2>User is added.</h2>
</body>
</html>

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>springmvc</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.3.0</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.3</version>
				<configuration>
                    <source>11</source>
                    <target>11</target>
                </configuration>
			</plugin>
		</plugins>
	</build>
</project>

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。



Spring I18N(国际化)

原文:https://www.studytonight.com/spring-framework/spring-i18n-internationalization

I18N 是国际化的首字母缩略词,Spring framework 用它来做一个面向国际层面的应用。这意味着我们可以创建一个针对多个地区的应用,就像一个可以在美国、中国、俄罗斯和世界上任何其他国家使用的应用一样,只需实现 i18N。

Spring 框架也使用localersolver来支持国际化和本地化。在本教程中,我们将学习在我们的 spring MVC 应用中实现国际化。

让我们创建一个基于 maven 的 spring 项目,我们的项目如下所示,包含几个源代码文件。

项目结构

//app config . Java

这是一个配置文件,它是我们为基于 xml 的配置示例创建的 applicationContext.xml 文件的替代文件。@Configuration注释表示这不是一个简单的类,而是一个配置类,@ComponentScan 注释用于表示我们 spring 项目中组件类的位置。

这里,我们为 i18n 支持配置了我们的应用。您可以注意到,除了视图解析器之外,我们还添加了一些获取阿郎参数的方法。

package com.studytonight;

import java.util.Locale;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@EnableWebMvc
@Configuration
@ComponentScan("com.studytonight.controller")
public class AppConfig implements WebMvcConfigurer{

	@Bean(name = "messageSource")
    public ReloadableResourceBundleMessageSource reloadableResourceBundleMessageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasenames("classpath:messages");
        messageSource.setDefaultEncoding("UTF-8");
        return messageSource;
    }

	@Bean
	public ViewResolver viewResolver() {
		InternalResourceViewResolver irvr = new InternalResourceViewResolver();
		irvr.setPrefix("WEB-INF/views/");
		irvr.setSuffix(".jsp");
		irvr.setOrder(0);
		return irvr;
	}

	@Bean(name="localeResolver")
	public LocaleResolver localeResolver() {
		SessionLocaleResolver slr = new SessionLocaleResolver();
		slr.setDefaultLocale(Locale.US);
		return slr;
	}

	@Bean
	public LocaleChangeInterceptor localeChangeInterceptor() {
		LocaleChangeInterceptor localeChangeInterceptor =  new LocaleChangeInterceptor();
		localeChangeInterceptor.setParamName("lang");
		return localeChangeInterceptor;
	}

	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(localeChangeInterceptor());
	}
}

//WebAppInitializer.java

该文件包含为我们的应用创建 IOC 容器的代码。AnnotationConfigWebApplicationContext类用于为应用上下文创建一个对象。

package com.studytonight;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
public class WebAppInitializer implements WebApplicationInitializer {

	@Override
	public void onStartup(ServletContext servletContext) throws ServletException { 
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
		context.register(AppConfig.class);
		context.setServletContext(servletContext);
		ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
		servlet.setLoadOnStartup(1);
		servlet.addMapping("/");
		context.close();	
	}
}

//HomeController.java

这是我们的控制器类,它在应用启动时向浏览器返回一个索引 JSP 页面。

package com.studytonight.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class HomeController {

	@GetMapping("/")
	public String index() {
		return "index";
	} 
}

这些是我们的属性文件,第一个包含英语的值,第二个包含西班牙语的值。

// messages_en.properties

#labels
label.name=Name
label.email=Email

#buttons
label.register=Register Here

// messages_es.properties

#labels
label.name=nombre
label.email=correo electrónico

#buttons
label.register = Registrarse aquí

//index.jsp

这个 JSP 文件使用 < spring:message > 标签从属性文件中获取值并相应地显示它们。

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>User Form</title>
</head>
<body>
	<form action="register" method="post">
		<spring:message code="label.name"/>
		<br>
		<input type="text" name="name"/>
		<br>
		<spring:message code="label.email"/>
		<br>
		<input type="email" name="email" />
		<br>
		<input type="submit" value="<spring:message code="label.register"/>">
	</form>
</body>
</html>

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.studytonight</groupId>
  <artifactId>springi18</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  <dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.3.0</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.3</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
				</configuration>
			</plugin>
			<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                </configuration>
            </plugin>
		</plugins>
	</build>
</project>

运行应用

成功完成项目并添加依赖项后,使用服务器运行应用,您将获得如下输出。

以上表单页面以美国英语显示(默认)。但是,如果我们想用任何其他语言显示它,那么我们可以通过将阿郎参数设置为 URL 来实现。见下面的输出,我们通过 lang=es西班牙语显示网页。



Spring MVC 和 JPA

原文:https://www.studytonight.com/spring-framework/spring-mvc-with-jpa

JPA (Java Persistence API)是一个在 Java 应用和关系数据库之间充当桥梁的 API。它是一组用于高效执行数据库操作的类和接口。它减少了 Java 应用中的数据库配置工作,并且得到了所有主要数据库 MySQL、Oracle、Redhat 等的支持。

最初 JPA 是结合 EJB 作为业务逻辑层发布的,可以使用javax.ejb.EntityBean接口访问。但是现在各种有 JPA 持久味道的产品,比如 Hibernate、Spring Data JPA 等。

在本文中,我们将学习在 Spring 应用中使用 JPA 并连接数据库(MySQL)。下图显示了我们基于 Maven 的 Spring 项目的结构和文件层次。

项目结构

//寄存器控制器. java

这是我们的控制器类,它有两个方法 index()和 save()。第一个用于将 JSP 页面作为用户表单返回,第二个用于将用户详细信息保存到数据库中。

package com.studytonight.controllers; 

import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import com.studytonight.models.User;
import com.studytonight.service.UserService;

@Controller
public class RegisterController{

	@Autowired 
	private UserService userService;

	@GetMapping("/")
	public String index() {
		return "register";
	}

	@PostMapping("save")
	public String save(@Valid @ModelAttribute User user, BindingResult result) {
		if(result.hasErrors()) {
			return "register";
		}else {
			 userService.register(user);
			 return "successful";
		}	
	}	
}

//user.java

这是我们的实体类,表示数据库中的用户表结构。我们使用@Entity 注释将其标记为实体。Spring 将在 MySQL 数据库中创建一个用户表。

package com.studytonight.models;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class User {

	@Id
	@GeneratedValue
	private Long id;
	private String name;
	private Long mobile;
	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Long getMobile() {
		return mobile;
	}
	public void setMobile(Long mobile) {
		this.mobile = mobile;
	}
} 

//UserRepository.java

它是 DAO 实现的接口。它包含一个 save()方法。

package com.studytonight.repository;
import com.studytonight.models.User;
public interface UserRepository {
	User save(User user);
} 

//user repository impl . Java

执行数据库操作的是我们的 DAO(数据访问对象)实现类。在我们的例子中,我们将用户数据插入到表中,因此使用了 EntityManager 的persist()方法。

package com.studytonight.repository;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.studytonight.models.User;

@Component
@Repository
public class UserRepositoryImpl implements UserRepository{

	@PersistenceContext
	private EntityManager em;

	@Override
	@Transactional
	public User save(User user) {
		em.persist(user);
		em.flush();
		return  user;
	}
} 

//user service . Java

它是服务类实现的接口。它包含一个方法寄存器()。

package com.studytonight.service;
import org.springframework.stereotype.Service;
import com.studytonight.models.User;
public interface UserService {
	User register(User user);
} 

//user service impl . Java

正是我们的服务实现类调用了 DAO 的 save()方法来保存用户数据。

package com.studytonight.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.studytonight.models.User;
import com.studytonight.repository.UserRepository;

@Component
@Service
public class UserServiceImpl implements UserService {

	@Autowired
	UserRepository userRepository;

	@Override
	@Transactional
	public User register(User user) {
		// TODO Auto-generated method stub
		return userRepository.save(user);
	}
} 

这些 XML 文件是 Java 持久性 API 配置文件,包含连接细节、数据库方言和 EntityManagerFactory 配置。

//持久性. xml

<persistence 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
	version="2.0">
	<persistence-unit name="punit"></persistence-unit>
</persistence>

/jpacontext . XML

<beans 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">

	<context:annotation-config />
	<context:component-scan
		base-package="com.studytonight"></context:component-scan>

	<bean
		class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

	<bean id="datasource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName"
			value="com.mysql.jdbc.Driver"></property>
		<property name="url"
			value="jdbc:mysql://localhost:3306/springwithdb?autoReconnect=true"></property>
		<property name="username" value="root_user" />
		<property name="password" value="root_password" />
	</bean>

	<bean id="entityManagerFactory"
		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="persistenceUnitName" value="punit" />
		<property name="dataSource" ref="datasource" />
		<property name="jpaVendorAdapter">
			<bean
				class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
				<property name="showSql" value="true" />
			</bean>
		</property>
		<!-- JPA vendor properties: specific to Hibernate, in our case -->
		<property name="jpaPropertyMap">
			<map>
				<entry key="hibernate.dialect"
					value="org.hibernate.dialect.MySQLDialect" />

				<entry key="hibernate.hbm2ddl.auto" value="create"></entry>
				<entry key="hibernate.format_sql" value="true"></entry>
			</map>
		</property>

	</bean>

	<bean id="transactionManager"
		class="org.springframework.orm.jpa.JpaTransactionManager">
		<property name="entityManagerFactory" ref="entityManagerFactory" />
	</bean>
	<tx:annotation-driven />

	<bean id="persistenceExceptionTranslationPostProcessor"
		class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

</beans>

//register.jsp

这是一个 JSP 页面,包含一个 HTML 表单,并在应用启动时呈现。

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>User Registration Form</title>
</head>
<body>
	<h2>User Registration Form</h2>
	<form action="save" method="post">
		<label>User Name : </label> <input type="text" name="name"><br>
		<br> <label>Mobile : </label> <input type="text" name="mobile"><br>
		<br> <input type="submit" value="Register">
	</form>
</body>
</html>

//successful.jsp

当用户注册成功时,这个 JSP 页面显示一个成功页面。

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title></title>
</head>
<body>
	<h2>Registered Successfully!</h2>
</body>
</html>

//servletconfig . XML

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

	<!-- Step 3: Add support for component scanning -->
	<context:component-scan base-package="com.studytonight.controllers" />

	<!-- Step 4: Add support for conversion, formatting and validation support -->
	<mvc:annotation-driven/>

	<!-- Step 5: Define Spring MVC view resolver -->
	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/views/" />
		<property name="suffix" value=".jsp" />
	</bean>
</beans>

// web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	version="2.5">
	<display-name>springwithdb</display-name>

	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classPath:/jpaContext.xml</param-value>
	</context-param>

	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Spring MVC Configs -->

	<!-- Step 1: Configure Spring MVC Dispatcher Servlet -->
	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/servlet-config.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<!-- Step 2: Set up URL mapping for Spring MVC Dispatcher Servlet -->
	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

</web-app>

POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>springwithdb</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate.validator</groupId>
			<artifactId>hibernate-validator</artifactId>
			<version>6.1.1.Final</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.10.0.pr3</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.13</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>4.1.4.Final</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>3.2.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>3.2.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.3.0</version>
		</dependency>
		<dependency> 
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-entitymanager</artifactId>
			<version>4.1.9.Final</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.transaction/jta -->
		<dependency>
			<groupId>javax.transaction</groupId>
			<artifactId>jta</artifactId>
			<version>1.1</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<build>
		<sourceDirectory>src</sourceDirectory>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.3</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

当用户成功注册后,数据将存储在用户表中,您可以通过访问数据库进行验证。



Spring 的 CSS 和 JS 处理

原文:https://www.studytonight.com/spring-framework/css-and-js-handling-in-spring

在本文中,我们将学习 Spring 框架中的 CSSJavaScript 文件处理。当创建一个网络应用时,我们需要在我们的应用中添加网络技术,比如 CSS、JavaScript 等。

Spring 提供了<mvc:resource>标签来映射我们应用项目中文件的位置。这个标签使用映射属性来映射资源,使用位置属性来定位资源。我们可以简单地将这个标签放入我们的 servlet 上下文文件,如下所示。

<mvc:resources mapping="/js/**" location="/js/" />
<mvc:resources mapping="/css/**" location="/css/" />

然后将这个 taglib 库添加到 JSP 文件中,为 CSS 和 JS 文件添加标签。

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

添加这个 JSTL 库后,将这些标签添加到 JSP 页面的头部。

<script src="<c:url value="/js/jsfile.js" />"></script>
<link href="<c:url value="/css/cssfile.css" />" rel="stylesheet"></link>

注意:将所有 CSS 文件放入 webapp/css 文件夹,JavaScript 文件放入项目中 webapp/js 文件夹。您可以参考我们的项目结构来了解文件位置和目录层次结构。

举个例子

让我们创建一个例子来理解 Spring 框架中的 CSS 和 JavaScript 文件处理。以下是我们项目的源文件。你可以让他们参考你的项目。

JSP 文件//user-form.jsp

在这个文件中,我们创建了一个 HTML 表单,并添加了 CSS 和 JS 文件。

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>  
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>User Form</title>
<script src="<c:url value="/js/jsfile.js" />"></script>
<link href="<c:url value="/css/cssfile.css" />" rel="stylesheet"></link>
</head>
<body>
<h2>User Form</h2>
<form action="showdata" method="Get">
	<label>Enter User Name: </label><input type="text" name="user_name"><br/><br/>
	<label>Enter password : </label><input type="password" name="password"><br/><br/>
	<input type="submit" onclick="save()" />
</form>
</body>
</html>

//控制器 HelloController.java

这是我们的控制器类,包含两种显示 JSP 页面的方法。

package com.studytonight.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController {

	@RequestMapping("/")
	public String showForm() {
		return "user-form";
	}

	@RequestMapping("showdata")
	public String userForm(@ModelAttribute("user_name") String user, Model model)
	{
			model.addAttribute("name", user);
			return "user-data";		
	}
}

//spring-MVC-app-servlet . XML

在这个文件中,我们使用<mvc:resources>标签来配置 CSS 和 JS 文件。

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

	<!-- Step 3: Add support for component scanning -->
	<context:component-scan
		base-package="com.studytonight.controller" />

	<!-- Step 4: Add support for conversion, formatting and validation support -->
	<mvc:annotation-driven />

	<mvc:resources mapping="/js/**" location="/js/" />
	<mvc:resources mapping="/css/**" location="/css/" />

	<!-- Step 5: Define Spring MVC view resolver -->
	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/views/" />
		<property name="suffix" value=".jsp" />
	</bean>
</beans> 

// web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	id="WebApp_ID" version="3.1">

	<display-name>spring-mvc-app</display-name>

	<absolute-ordering />

	<!-- Spring MVC Configs -->

	<!-- Step 1: Configure Spring MVC Dispatcher Servlet -->
	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring-mvc-app-servlet.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<!-- Step 2: Set up URL mapping for Spring MVC Dispatcher Servlet -->
	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

</web-app>

//user-form.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Hello JSP</title>
</head>
<body>
<strong>Hello,</strong>
${name}
</body>
</html>

//cssfile . CSS

h2{
	color:blue;
}

//jsfile . js

function save(){
	alert("Data Saved.");
}

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>spring-mvc-app</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.3.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.3</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

项目结构

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

请注意,在 CSS 文件中,我们对 H2 标签应用了 CSS color 属性,这很有效,在 JS 文件中,我们创建了一个方法,在单击提交按钮时显示一条警告消息。



Spring REST

Spring REST 控制器

原文:https://www.studytonight.com/spring-framework/spring-restcontroller

RestController 是与 REST 服务一起工作的控制器的专用版本。Spring 框架传统上使用@Controller注释来创建处理 HTTP 请求的控制器。

在 Spring 4 中,添加了一个新的注释@RestController来创建一个特定的控制器,它是@Controller 和@RequestBody 注释的组合形式。它减少了用@ResponseBody 注释添加控制器的每个请求处理方法的工作量。

创建 RestController 的目的是处理 REST 服务请求。让我们通过例子来理解。在这里,我们创建了一个基于 maven 的 spring 项目,如下所示。

Spring 支架项目结构

//app config . Java

这是一个配置文件,它是我们为基于 xml 的配置示例创建的 applicationContext.xml 文件的替代文件。@Configuration注释表示这不是一个简单的类,而是一个配置类,@ComponentScan 注释用于表示我们 spring 项目中组件类的位置。

package com.studytonight;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@EnableWebMvc
@Configuration
@ComponentScan("com.studytonight.controllers")
public class AppConfig implements WebMvcConfigurer{

	@Autowired
	ApplicationContext applicationContext;

	@Bean
	public ViewResolver viewResolver() {
		InternalResourceViewResolver ivr = new InternalResourceViewResolver();
		ivr.setPrefix("/WEB-INF/views/");
		ivr.setSuffix(".jsp");
		ivr.setOrder(0);
		return ivr;
	}
}

//main app . Java

该文件包含为我们的应用创建 IOC 容器的代码。AnnotationConfigWebApplicationContext类用于为应用上下文创建一个对象。

package com.studytonight;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
public class MainApp implements WebApplicationInitializer {

	@Override
	public void onStartup(ServletContext servletContext) throws ServletException { 
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
		context.register(AppConfig.class);
		context.setServletContext(servletContext);
		ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
		servlet.setLoadOnStartup(1);
		servlet.addMapping("/");
		context.close();	
	}
}

//HomeController.java

这是控制器类,但不简单,是 RestController 有两个方法 getUser()和 postUser(),这两个方法都以 JSON 格式返回一个用户对象。为了将结果绑定到 Java 到 JSON,我们在 pom.xml 文件中使用了杰克逊库。

package com.studytonight.controllers;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.studytonight.models.User;

@RestController
public class HomeController {

	@GetMapping("/user")
	public User getUser(@RequestParam(value = "name", defaultValue = "david") String name,
			@RequestParam(value = "lastName", defaultValue = "mark") String lastName,
			@RequestParam(value = "email", defaultValue = "david@gmail.com") String email) {		
		User user = new User();
		user.setName(name);
		user.setLastName(lastName);
		user.setEmail(email);
		return user;
	}

	@PostMapping("/user")
	public User postUser(@RequestBody User user) {
		return user;
	}
}

这是我们需要添加到 pom.xml 文件中的依赖项,以将数据绑定到 JSON 格式。

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
	<artifactId>jackson-databind</artifactId>
	<version>2.10.0.pr3</version>
</dependency>

//User.java

这是一个用户类,将被用作一个 bean 来保存从 HTML 表单输入的用户数据。

package com.studytonight.models;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
public class User {

	@NotEmpty(message = "Name can not empty")
	String name;
	String lastName;
	@NotEmpty(message = "Email can not empty")
	@Email
	String email;

	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
}

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

如果我们不提供参数值,那么它会显示控制器中设置的默认值。

这就是我们如何通过使用 get request 向控制器传递新值,并以 JSON 格式获取新数据。



Spring REST CURD 应用

原文:https://www.studytonight.com/spring-framework/spring-rest-crud-application

在本文中,我们将创建一个 CRUD(创建、读取、更新和删除)Spring 应用。这个应用使用 REST(表示状态转移)方法来执行 CRUD 操作。它使用 @RestController 注释来创建一个控制器,该控制器处理请求并将响应以 JSON 格式发回。

REST 是一种架构风格,包含一组创建 web 服务的约束。可以参考我们关于 REST API 的文章。我们也可以用这种方法执行 CRUD 操作。让我们通过示例来理解并创建一个基于 maven 的项目,该项目包含几个文件,其结构如下所示。

项目结构

// DemoAppConfig.java

这是一个 Java 配置文件,它是我们为基于 xml 的配置示例创建的 applicationContext.xml 文件的替代文件。@Configuration注释表示这不是一个简单的类,而是一个配置类,@ComponentScan注释用于表示我们 spring 项目中的组件位置。

@PropertySource注释用于读取属性文件。在这里,我们已经设置了数据库配置和会话工厂来使用数据库。

package com.studytonight.springdemo.config;

import java.beans.PropertyVetoException;
import java.util.Properties;
import java.util.logging.Logger;
import javax.sql.DataSource;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import com.mchange.v2.c3p0.ComboPooledDataSource;

@Configuration
@EnableWebMvc
@EnableTransactionManagement
@ComponentScan("com.studytonight.springdemo")
@PropertySource({ "classpath:persistence-mysql.properties" })
public class DemoAppConfig implements WebMvcConfigurer {

	@Autowired
	private Environment env;
	private Logger logger = Logger.getLogger(getClass().getName());	
	// define a bean for ViewResolver
	@Bean
	public DataSource myDataSource() {
		ComboPooledDataSource myDataSource = new ComboPooledDataSource();
		try {
			myDataSource.setDriverClass("com.mysql.jdbc.Driver");		
		}
		catch (PropertyVetoException exc) {
			throw new RuntimeException(exc);
		}
		logger.info("jdbc.url=" + env.getProperty("jdbc.url"));
		logger.info("jdbc.user=" + env.getProperty("jdbc.user"));
		myDataSource.setJdbcUrl(env.getProperty("jdbc.url"));
		myDataSource.setUser(env.getProperty("jdbc.user"));
		myDataSource.setPassword(env.getProperty("jdbc.password"));
		myDataSource.setInitialPoolSize(getIntProperty("connection.pool.initialPoolSize"));
		myDataSource.setMinPoolSize(getIntProperty("connection.pool.minPoolSize"));
		myDataSource.setMaxPoolSize(getIntProperty("connection.pool.maxPoolSize"));		
		myDataSource.setMaxIdleTime(getIntProperty("connection.pool.maxIdleTime"));
		return myDataSource;
	}

	private Properties getHibernateProperties() {
		// set hibernate properties
		Properties props = new Properties();
		props.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
		props.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
		return props;				
	}

	private int getIntProperty(String propName) {	
		String propVal = env.getProperty(propName);
		int intPropVal = Integer.parseInt(propVal);		
		return intPropVal;
	}	

	@Bean
	public LocalSessionFactoryBean sessionFactory(){
		LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
		sessionFactory.setDataSource(myDataSource());
		sessionFactory.setPackagesToScan(env.getProperty("hibernate.packagesToScan"));
		sessionFactory.setHibernateProperties(getHibernateProperties());		
		return sessionFactory;
	}

	@Bean
	@Autowired
	public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
		HibernateTransactionManager txManager = new HibernateTransactionManager();
		txManager.setSessionFactory(sessionFactory);
		return txManager;
	}	
}

【t0///my pringgmvcdisperservicinitiator . Java

这是 servlet dispatcher 初始值设定项类,它从demappconfig文件中读取配置并启动应用。

package com.studytonight.springdemo.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class MySpringMvcDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
	@Override
	protected Class<?>[] getRootConfigClasses() {
		return null;
	}

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

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

//customer Dao . Java

这是一个 DAO(数据访问对象)接口,它包含几个在实现类中实现的方法。

package com.studytonight.springdemo.dao;

import java.util.List;
import com.studytonight.springdemo.entity.Customer;
public interface CustomerDAO {
	public List<Customer> getCustomers();
	public void saveCustomer(Customer theCustomer);
	public Customer getCustomer(int theId);
	public void deleteCustomer(int theId);
} 

//customdaimple . Java

这是一个 DAO(数据访问对象)实现类,它实现了 CutomerDAO 接口并实现了它的方法。

package com.studytonight.springdemo.dao;

import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.studytonight.springdemo.entity.Customer;

@Repository
public class CustomerDAOImpl implements CustomerDAO {
	@Autowired
	private SessionFactory sessionFactory;
	@Override
	public List<Customer> getCustomers() {
		Session currentSession = sessionFactory.getCurrentSession();
		Query<Customer> theQuery = 
				currentSession.createQuery("from Customer order by lastName",
											Customer.class);
		List<Customer> customers = theQuery.getResultList();
		return customers;
	}

	@Override
	public void saveCustomer(Customer theCustomer) {
		Session currentSession = sessionFactory.getCurrentSession();
		currentSession.saveOrUpdate(theCustomer);
	}

	@Override
	public Customer getCustomer(int theId) {
		Session currentSession = sessionFactory.getCurrentSession();
		Customer theCustomer = currentSession.get(Customer.class, theId);
		return theCustomer;
	}

	@Override
	public void deleteCustomer(int theId) {
		Session currentSession = sessionFactory.getCurrentSession();
		Query theQuery = 
				currentSession.createQuery("delete from Customer where id=:customerId");
		theQuery.setParameter("customerId", theId);		
		theQuery.executeUpdate();		
	}
}

//Customer.java

这是一个用于表示客户详细信息的实体类。

package com.studytonight.springdemo.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="customer")
public class Customer {

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="id")
	private int id;

	@Column(name="first_name")
	private String firstName;

	@Column(name="last_name")
	private String lastName;

	@Column(name="email")
	private String email;

	public Customer() {

	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	@Override
	public String toString() {
		return "Customer [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", email=" + email + "]";
	}

} 

//customer rest controller . Java

这是我们的控制器类,用@RestController 标记,执行 CRUD 操作。它以 JSON 格式向用户返回输出。

package com.studytonight.springdemo.rest;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.studytonight.springdemo.entity.Customer;
import com.studytonight.springdemo.service.CustomerService;

@RestController
public class CustomerRestController {

	@Autowired
	private CustomerService customerService;

	@GetMapping("/customers")
	public List<Customer> getCustomers(){
		return customerService.getCustomers();
	}

	@GetMapping("/customers/{customerId}")
	public Customer getCustomer(@PathVariable int customerId){
		return customerService.getCustomer(customerId);
	}

	@PostMapping("/customers")
	public Customer addCustomer(@RequestBody Customer customer){
		customer.setId(0);
		customerService.saveCustomer(customer);
		return customer;
	}

	@PutMapping("/customers")
	public Customer updateCustomer(@RequestBody Customer customer){
		customerService.saveCustomer(customer);
		return customer;
	}

	@DeleteMapping("/customers/{customerId}")
	public String deleteCustomer(@PathVariable int customerId){
		customerService.deleteCustomer(customerId);
		return "Deleted Customer Id: "+customerId;
	}

}

//CustomerService.java

package com.studytonight.springdemo.service;

import java.util.List;
import com.studytonight.springdemo.entity.Customer;
public interface CustomerService {
	public List<Customer> getCustomers();
	public void saveCustomer(Customer theCustomer);
	public Customer getCustomer(int theId);
	public void deleteCustomer(int theId);
} 

//customer service impl . Java

package com.studytonight.springdemo.service;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.studytonight.springdemo.dao.CustomerDAO;
import com.studytonight.springdemo.entity.Customer;

@Service
public class CustomerServiceImpl implements CustomerService {

	// need to inject customer dao
	@Autowired
	private CustomerDAO customerDAO;

	@Override
	@Transactional
	public List<Customer> getCustomers() {
		return customerDAO.getCustomers();
	}

	@Override
	@Transactional
	public void saveCustomer(Customer theCustomer) {
		customerDAO.saveCustomer(theCustomer);
	}

	@Override
	@Transactional
	public Customer getCustomer(int theId) {
		return customerDAO.getCustomer(theId);
	}

	@Override
	@Transactional
	public void deleteCustomer(int theId) {
		customerDAO.deleteCustomer(theId);
	}
} 

//persistence-MySQL . properties

这是一个包含数据库相关配置的属性文件,在配置文件中使用@PropertySource注释进行访问。

#
# JDBC connection properties
#
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springwithdb?useSSL=false
jdbc.user=user_name
jdbc.password=user_password

#
# Connection pool properties
#
connection.pool.initialPoolSize=5
connection.pool.minPoolSize=5
connection.pool.maxPoolSize=20
connection.pool.maxIdleTime=3000

#
# Hibernate properties
#
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show_sql=true
hibernate.packagesToScan=com.studytonight.springdemo.entity

运行应用

成功完成项目并添加依赖项后,使用服务器运行应用,您将获得如下输出。

为了测试应用,我们使用了一个 Postman 应用。这是一个检查 web 请求的好应用。可以从官方网站安装后使用。

访问所有客户

添加新客户

添加新客户后显示所有客户

获取单个客户



Spring REST 异常处理

原文:https://www.studytonight.com/spring-framework/spring-rest-exception-handling

在本文中,我们将在 Spring REST 应用中添加异常处理。在我们的上一个主题中,我们学习了用一个例子创建一个 REST 应用。现在,我们将看到错误/异常处理,以避免应用的异常终止。

复制输入错误或未找到资源错误的应用非常重要。有时,当用户请求不存在的资源时,他会面临一个 404 -未找到

我们创建了一个包含几个文件的项目,您可以从前面的主题中获得大部分文件代码,这里我们只提供了用于异常处理的代码。

项目结构

//customer error response . Java

此类用于为用户设计错误消息。它包含状态、消息和时间戳等消息属性,为用户提供有意义的信息。

package com.studytonight.springdemo.rest;

public class CustomerErrorResponse {

	private int status;
	private String message;
	private long timeStamp;
	public CustomerErrorResponse(int status, String message, long timeStamp) {
		super();
		this.status = status;
		this.message = message;
		this.timeStamp = timeStamp;
	}
	public int getStatus() {
		return status;
	}
	public void setStatus(int status) {
		this.status = status;
	}
	public String getMessage() {
		return message;
	}
	public void setMessage(String message) {
		this.message = message;
	}
	public long getTimeStamp() {
		return timeStamp;
	}
	public void setTimeStamp(long timeStamp) {
		this.timeStamp = timeStamp;
	}
}

//customnotfounindexception . Java

这里,我们正在创建一个自定义异常类来生成一个异常对象。它扩展了 RuntimeException 类,使其对象成为异常。

package com.studytonight.springdemo.rest;

public class CustomerNotFoundException extends RuntimeException{

	public CustomerNotFoundException() {
		super();
	}
	public CustomerNotFoundException(String message, Throwable cause, boolean enableSuppression,
			boolean writableStackTrace) {
		super(message, cause, enableSuppression, writableStackTrace);
	}
	public CustomerNotFoundException(String message, Throwable cause) {
		super(message, cause);

	}
	public CustomerNotFoundException(String message) {
		super(message);

	}
	public CustomerNotFoundException(Throwable cause) {
		super(cause);
	}
} 

//customer rest controller . Java

如果找不到客户 id,此控制器类将引发自定义异常。看,我们使用了自定义异常 CustomerNotFoundException 来处理应用流。

package com.studytonight.springdemo.rest;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.studytonight.springdemo.entity.Customer;
import com.studytonight.springdemo.service.CustomerService;

@RestController
public class CustomerRestController {

	@Autowired
	private CustomerService customerService;

	@GetMapping("/customers")
	public List<Customer> getCustomers(){
		return customerService.getCustomers();
	}

	@GetMapping("/customers/{customerId}")
	public Customer getCustomer(@PathVariable int customerId){
		Customer customer = customerService.getCustomer(customerId);
		if(customer == null) {
			throw new CustomerNotFoundException("Customer Id not Found : "+customerId);
		}
		return customerService.getCustomer(customerId);
	}

	@PostMapping("/customers")
	public Customer addCustomer(@RequestBody Customer customer){
		customer.setId(0);
		customerService.saveCustomer(customer);
		return customer;
	}

	@PutMapping("/customers")
	public Customer updateCustomer(@RequestBody Customer customer){
		customerService.saveCustomer(customer);
		return customer;
	}

	@DeleteMapping("/customers/{customerId}")
	public String deleteCustomer(@PathVariable int customerId){
		customerService.deleteCustomer(customerId);
		return "Deleted Customer Id: "+customerId;
	}
}

//customer remainxceptionhandler . Java

这是一个自定义异常处理程序类,使用 Spring ExceptionHandler 来处理异常。这里,我们通过使用这个类来处理 NOT_FOUND 和 BAD_REQUEST 异常。

package com.studytonight.springdemo.rest;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class CustomerRestExceptionalHandler {
	@ExceptionHandler
	public ResponseEntity<CustomerErrorResponse> handleException(CustomerNotFoundException e){
		CustomerErrorResponse error = new CustomerErrorResponse(HttpStatus.NOT_FOUND.value(), e.getMessage(), System.currentTimeMillis());
		return new ResponseEntity<CustomerErrorResponse>(error, HttpStatus.NOT_FOUND);
	}	
	@ExceptionHandler
	public ResponseEntity<CustomerErrorResponse> handleException(Exception e){
		CustomerErrorResponse error = new CustomerErrorResponse(HttpStatus.BAD_REQUEST.value(), e.getMessage(), System.currentTimeMillis());
		return new ResponseEntity<CustomerErrorResponse>(error, HttpStatus.BAD_REQUEST);
	}	
}

运行应用

成功完成项目并添加依赖项后,使用服务器运行应用,您将获得如下输出。

为了测试应用,我们使用了一个 Postman 应用。这是一个检查 web 请求的好应用。可以从官方网站安装后使用。

访问所有客户

按标识访问单个客户

我们可以通过个人客户的 id 来访问他们,但是如果没有找到记录,我们会收到一条消息。

错误输入

有可能,如果用户输入了一个非数字 id,那么我们的应用就会处理这个异常,并向用户提供一个适当的消息。



Spring 和 Hibernate

Spring Hibernate 配置

原文:https://www.studytonight.com/spring-framework/hibernate-configuration

Hibernate 是一个基于 ORM 的框架,用于在 Java 应用中将 Java 对象映射到关系数据库。它主要用于在数据库中存储数据。Hibernate 主要用于通过使用 Java 代码来管理数据库。它将 Java 类映射到数据库表,将 Java 类型映射到数据库类型。它由红帽设计和开发,最初于 2001 年 5 月 23 日发布。

我们可以通过看到下图来理解,该图显示了 hibernate 框架如何将 java 类字段映射到表列及其类型。

在本教程中,我们将看到如何在 spring web 应用中配置 hibernate。我们可以通过使用 XML 文件或 Java 注释来配置 Hibernate。XML 方法比较古老,注释是一种新的现代方法。因此,我们将使用注释来配置 hibernate,但是您可以自由使用任何方法。

hibernate 使用 SessionFactory 类来处理数据表,并提供读取、保存和获取数据的方法。

使用 Java 注释和代码的 Hibernate 配置

该文件显示了在 Spring 应用中使用 Java 注释和代码的基本 hibernate 配置。

package com.studytonight;

import org.apache.tomcat.dbcp.dbcp2.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import java.util.Properties;
import javax.sql.DataSource;

@Configuration
@EnableTransactionManagement
@ComponentScan("com.studytonight") 
public class HibernateConf {

	@Bean
	public LocalSessionFactoryBean sessionFactory() {
		LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
		sessionFactory.setDataSource(dataSource());
		sessionFactory.setPackagesToScan("com.studytonight.models");
		sessionFactory.setHibernateProperties(hibernateProperties());
		return sessionFactory;
	}

	@Bean
	public DataSource dataSource() {
		BasicDataSource dataSource = new BasicDataSource();
		dataSource.setDriverClassName("com.mysql.jdbc.Driver");
		dataSource.setUrl("jdbc:mysql://localhost:3306/springwithdb?useSSL=false");
		dataSource.setUsername("user-name");
		dataSource.setPassword("password");
		return dataSource;
	}

	@Bean
	public PlatformTransactionManager hibernateTransactionManager() {
		HibernateTransactionManager transactionManager
		= new HibernateTransactionManager();
		transactionManager.setSessionFactory(sessionFactory().getObject());
		return transactionManager;
	}

	private final Properties hibernateProperties() {
		Properties hibernateProperties = new Properties();
		hibernateProperties.setProperty("hibernate.show_sql","true");
		return hibernateProperties;
	}
}

使用可扩展标记语言的 Hibernate 配置

如果您想使用一个 XML 文件,那么使用这个 XML 代码来配置 Spring 应用的 hibernate。

<?xml version="1.0" encoding="UTF-8"?>
<beans >

    <bean id="sessionFactory" 
      class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <property name="dataSource" 
          ref="dataSource"/>
        <property name="packagesToScan" 
          value="com.studytonight.models"/>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.hbm2ddl.auto">
                    create-drop
                </prop>
                <prop key="hibernate.dialect">
                    org.hibernate.dialect.MySQL5Dialect
                </prop>
            </props>
        </property>
    </bean>

    <bean id="dataSource" 
      class="org.apache.tomcat.dbcp.dbcp2.BasicDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/db_name?useSSL=false"/>
        <property name="username" value="db_user"/>
        <property name="password" value="db_password"/>
    </bean>

    <bean id="txManager" 
      class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
</beans>

配置之后,现在我们可以通过添加下面的行在应用的任何地方使用它。我们主要将其与 DAO 实现类一起使用。

@Autowired
private SessionFactory sessionFactory;

会话工厂是 Hibernate 的一个组件,用于为应用创建会话对象。然而SessionFactory是一个提供多种方法处理会话的界面。

数据库方言

以下是 Mysql、Oracle 等各种数据库的方言。

| 数据库 | 方言名称 |
| 微软 SQL Server 2008 | org . hibernate . quality . SQLServer 2008 quality |
| 关系型数据库 | org . hibernate . flavoice . MySQL flavoice |
| 神谕 | org . hibernate . flavoice . Oracle flavoice |
| 一种数据库系统 | org . hibernate . quality . PostgreSqldialect |
| DB2 | org . hibernate . flavoice . db 2 dialect |

在下一个主题中,我们将学习使用 hibernate 将数据连接并保存到 Mysql 数据库中。



Spring Hibernate 集成

原文:https://www.studytonight.com/spring-framework/spring-hibernate-integration

在我们的上一篇文章中,我们已经了解了 hibernate 框架和配置方法。现在,我们将学习配置和实现 hibernate 并执行操作。

这里,我们使用 Java 代码和注释来配置 Spring 应用的 hibernate。我们创建了一个 maven 项目,如下图所示。

项目结构

该项目包含多个包,如com study nightcom study night . Daocom study night . modelscom study night . service等,对 Java 文件进行分类。

该项目包含以下源文件。

//App.java

该文件包含为我们的应用创建 IOC 容器的代码。AnnotationConfigApplicationContext 类用于为应用上下文创建对象。

package com.studytonight;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.studytonight.service.UserService;
import com.studytonight.service.UserServiceImpl;

public class App {

	public static void main(String[] args) {

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		UserService userService = context.getBean("userServiceImpl",UserServiceImpl.class);
		userService.save();
		// Close the context
		context.close();
	}
}

//app config . Java

这是一个 Java 配置文件,它是我们为基于 xml 的配置示例创建的 applicationContext.xml 文件的替代文件。@Configuration注释表示这不是一个简单的类,而是一个配置类,@ComponentScan 注释用于表示我们 spring 项目中组件类的位置。

package com.studytonight;

import java.util.Properties;
import javax.sql.DataSource;
import org.apache.tomcat.dbcp.dbcp2.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@ComponentScan("com.studytonight")
@EnableTransactionManagement
public class AppConfig {

	@Bean
	public LocalSessionFactoryBean sessionFactory() {
		LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
		sessionFactory.setDataSource(dataSource());
		sessionFactory.setPackagesToScan("com.studytonight.models");
		sessionFactory.setHibernateProperties(hibernateProperties());
		return sessionFactory;
	}

	@Bean
	public DataSource dataSource() {
		BasicDataSource dataSource = new BasicDataSource();
		dataSource.setDriverClassName("com.mysql.jdbc.Driver");
		dataSource.setUrl("jdbc:mysql://localhost:3306/springwithdb?useSSL=false");
		dataSource.setUsername("user-name");
		dataSource.setPassword("password");
		return dataSource;
	}

	@Bean
	public PlatformTransactionManager hibernateTransactionManager() {
		HibernateTransactionManager transactionManager
		= new HibernateTransactionManager();
		transactionManager.setSessionFactory(sessionFactory().getObject());
		return transactionManager;
	}

	private final Properties hibernateProperties() {
		Properties hibernateProperties = new Properties();
		hibernateProperties.setProperty("hibernate.show_sql","true");
		return hibernateProperties;
	}
}

//user Dao . Java

这是一个为数据访问对象(DAO)声明方法的接口。

package com.studytonight.dao;

public interface UserDao {
	void save();
}

//user daimple . Java

这是一个 DAO 实现类,它实现了 UserDao 接口,并用于执行数据库操作。这里,我们将用户数据保存到用户表中。

package com.studytonight.dao;

import javax.transaction.Transactional;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.studytonight.models.User;

@Repository
public class UserDaoImpl implements UserDao{

	@Autowired
	private SessionFactory sessionFactory;

	@Transactional
	public void save() {
		Session session = sessionFactory.getCurrentSession();
		User user = new User(101,"Sam","Jacob","sam@studytonight.com");
		session.save(user);
	}
}

//User.java

这是一个实体类,表示数据库中的用户表。它使用@实体@表注解将一个类作为一个实体类。它包含设置器和获取器方法来设置和获取数据库中的数据。

package com.studytonight.models;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "user")
public class User {
	@Id 
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	int id;
	String name;
	String lastName;
	String email;

	public User(int id, String name, String lastName, String email) {
		//super();
		this.id = id;
		this.name = name;
		this.lastName = lastName;
		this.email = email;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
}

//user service . Java

package com.studytonight.service;

public interface UserService {

	void save();
}

//user service impl . Java

它是一个调用 DAO 类方法的服务类。

package com.studytonight.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.studytonight.dao.UserDao;

@Service
public class UserServiceImpl implements UserService{

	@Autowired
	private UserDao userDao;

	public void save() {
		userDao.save();
	}
}

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>springhibernate</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<dependencies>
		<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- Hibernate -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>${hibernate.version}</version>
		</dependency>

		<!-- MySQL -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>${mysql.connector.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.tomcat</groupId>
			<artifactId>tomcat-dbcp</artifactId>
			<version>9.0.1</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<version>1.4.195</version>
		</dependency>
	</dependencies>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
		<hibernate.version>5.4.1.Final</hibernate.version>
		<mysql.connector.version>5.1.45</mysql.connector.version>

	</properties>
</project>

运行应用

成功完成项目并添加依赖项后,运行应用,它会将数据保存到表中,您可以通过登录数据库来验证该表。



Spring Security

Spring Security 攻略

原文:https://www.studytonight.com/spring-framework/spring-security-introduction

Spring Security 是为保护基于 Spring 的应用而设计和开发的 Spring 项目之一。这是一个标准框架,可以用来保护 Spring 应用。它有助于解决创建非安全性 Spring 应用过程中出现的所有安全问题。它是在 2008 年作为 Spring Security 2.0.0】首次发布的

它侧重于验证和授权,以保护应用的安全。认证是了解和识别想要访问的用户的过程,授权是允许权限执行操作和访问 Spring 应用中的资源的过程。它包含几个模块来处理各种领域,如远程、网络等。请参见下面的模块列表。

Spring Security 模块

Spring Security 由核心、授权、测试等几个独立的模块组成。我们列出了一些模块名称:

  • 核心:包括 Spring Security 与认证和应用访问控制相关的核心类和接口。

  • Remoting: 它用于处理 Spring Remoting 应用,并包含必要的类。

  • 方面:用于在 Spring Security 中包含面向方面编程(AOP)支持。

  • 配置:使用 XML 和 Java 配置 Spring Security 应用。

  • Crypto: 该模块包含用于加密支持的类和接口。

  • 数据:用于集成 Spring Security 和 Spring Data。

  • 消息传递:在应用中实现消息传递是有帮助的。

  • OAuth2: 它包括 Spring Security 中 OAuth 2.x 的类和接口:

  • OpenID: 提供集成 OpenID 网络认证的支持。

  • CAS: CAS(中央认证服务)客户端集成。

  • 标签库:它包含几个关于 Spring Security 的标签库。

  • 测试:在 Spring Security 中增加了测试支持。

  • Web: 它包含 Web 安全代码,比如过滤器和 Servlet API 依赖关系。

您可以将 Spring Security 看作是一个工具,它充当用户和应用之间的桥梁,以保护应用免受非授权用户的攻击。查看 spring 安全性在应用中是如何分层的。

Spring Security 的优势

  • 认证和授权支持
  • 防范恶意程序
  • 可扩张的
  • 与 Spring MVC 的集成
  • 轻便
  • CSRF 保护
  • Java 配置支持
  • 易于维护
  • 适当的文件

先决条件

我们正在使用 Spring Security 5.4.2,它需要 Java 8 或更高版本以及以下工具和库的知识。我们建议您在开始之前了解 Spring 框架。

Spring Security 性的 Maven 依赖关系

以下是将在示例教程中使用的依赖项。你可以使用这些或者在你的网络应用中选择最新的官方专家

<!-- spring-security-core -->
<dependency>
	<groupId>org.springframework.security</groupId>
	<artifactId>spring-security-web</artifactId>
	<version>5.4.2</version>
</dependency>
<!-- spring-security-config -->
<dependency>
	<groupId>org.springframework.security</groupId>
	<artifactId>spring-security-config</artifactId>
	<version>5.4.2</version>
</dependency>

在下一个主题中,我们将通过一个简单的基本示例学习 spring security,稍后还将学习其他特性。



Spring Security 基本示例

原文:https://www.studytonight.com/spring-framework/spring-security-basic-example

在我们之前的文章中,我们解释了 Spring Security 以及用于开发可扩展应用的各种工具。

在本文中,我们将学习在 web 应用中实现基本的 Spring Security。

在开始编写代码之前,让我们快速浏览一下给定的图像,该图像显示了 Spring security 如何对用户进行认证,以及如何检查资源授权。

Spring Security 工作

请注意,Spring Security 首先检查用户的认证,然后检查其访问应用资源的授权。如果像 JSP 页面这样的资源没有受到保护,那么它将不会执行认证,而只是让用户访问资源,但是如果资源受到保护,那么它将首先执行认证,然后让用户访问。如果用户不可信,简单地抛出一个消息访问被拒绝。

让我们通过一个例子来理解它,我们创建了一个基于 maven 的 Spring MVC 应用,并实现了 Spring Security 来制作一个安全的 web 应用。

项目源代码

以下是该项目的文件。您可以在项目中使用这些来测试应用。

//app config . Java

这是我们的应用配置文件,它实现了WebMvcConfugurer接口来制作这个 MVC 应用,并创建了一个方法 viewResolver 来映射我们的视图文件(JSP)。

package com.studytonight;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@EnableWebMvc
@Configuration
@ComponentScan("com.studytonight.controller")
public class AppConfig implements WebMvcConfigurer{
	@Bean
	public ViewResolver viewResolver() {
		InternalResourceViewResolver irvr = new InternalResourceViewResolver();
		irvr.setPrefix("WEB-INF/views/");
		irvr.setSuffix(".jsp");
		irvr.setOrder(0);
		return irvr;
	}
}

//main app . Java

这个类初始化我们的网络应用,并通过注册我们的 AppConfig 类(上面的文件)来创建ServletContext

package com.studytonight;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
public class MainApp implements WebApplicationInitializer {

	@Override
	public void onStartup(ServletContext servletContext) throws ServletException {
		System.out.println("started");
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
		context.register(AppConfig.class);
		context.setServletContext(servletContext);
		ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
		servlet.setLoadOnStartup(1);
		servlet.addMapping("/");
		context.close();	
	}
}

//securityappnitizer . Java

这是扩展抽象安全应用初始化器的安全初始化器类,我们传递了我们的安全配置类,以便它可以读取安全配置。

package com.studytonight;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityAppInitializer extends AbstractSecurityWebApplicationInitializer {

	public SecurityAppInitializer() {
		super(SecurityConfig.class);
	}
}

// SecurityConfig.java

这是我们的安全配置文件,扩展了WebSecurityConfigurerAdapter类,提供了configure()等几种方法来配置安全性。Spring Security 提供了作为认证管理器的AuthenticationManagerBuilder类,并提供了几种方法来验证用户。这里,我们使用inMemoryAuthentication概念,它允许映射硬编码的用户值。我们将在下一个教程中讨论使用数据库的用户认证,但是现在,让我们来看一个简单的例子。

package com.studytonight;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.User.UserBuilder;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{

	@Autowired
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		UserBuilder user = User.withDefaultPasswordEncoder();
		auth.inMemoryAuthentication()
		.withUser(user.username("studytonight").password("abc123").roles("admin"));
	}
}

//user controller . Java

这是我们的控制器类,它作为用户请求处理程序工作,将用户请求与资源进行映射,并相应地返回响应。我们创建了 home()方法来显示 index.jsp 页面,course()方法来显示 course.jsp 页面。

package com.studytonight.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class UserController {

	@GetMapping("/")  
	public String home() {
		return "index";
	}

	@GetMapping("/java-course")
	public String course() {
		return "course";
	}

	@GetMapping("/premium-courses")
	public String premiumCourse() {
		return "premium-courses";
	}
}

查看文件

这些是显示在浏览器中的项目视图文件。查看代码。

//course.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Course Page</title>
</head>
<body>
	<h2>List of Courses</h2>
	<ul>
		<li>Java</li>
		<li>Python</li>
		<li>C++</li>
		<li>Linux</li>
	</ul>
</body>
</html>

//index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Home Page</title>
</head>
<body>
	<h2>Welcome to Studytonight!</h2>
	<h3><a href="java-course">Study Java</a></h3>
	<h2><a href="premium-courses">Study Premium Courses</a></h2>
</body>
</html>

//特级 courses.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Course Page</title>
</head>
<body>
	<h2>List of Premium Courses</h2>
	<ul>
		<li>Spring Framework</li>
		<li>Pandas</li>
		<li>Spring Security</li>
	</ul>
</body>
</html>

//POM/XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>springwithsecurity</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
		<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>4.0.1</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.3.3</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
		<dependency>
			<groupId>javax.servlet.jsp.jstl</groupId>
			<artifactId>jstl-api</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.3.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>5.4.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>5.4.2</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.3</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.5.1</version>
				<configuration>
					<source>11</source>
					<target>11</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

项目结构

创建这些文件后,我们的项目将如下所示。你可以参考这个来了解项目的目录结构。

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

注意:在我们的应用中,我们没有创建这个登录页面,而是配置了 Spring Security。这是一个由框架本身提供的内置登录页面,用于对用户进行认证。

它会将用户名和密码与SecurityConfig.java文件中提供的凭据进行匹配。

提供错误的用户名和密码

认证错误:错误的凭据

如果提供的用户名和密码错误,则会显示一条错误消息。见下面截图。

提供正确的用户名和密码

主页

现在,您已成功登录到应用。这是我们的index.jsp文件渲染为浏览器的主页。

至此,我们已经学会了在 Spring web 应用中实现 Spring Security。在下一个主题中,我们将学习呈现我们自己的登录页面,而不是框架提供的内置页面。



Spring Security 自定义登录表单

原文:https://www.studytonight.com/spring-framework/spring-security-custom-login-form

在之前的教程中,我们了解了Spring Security并创建了一个基本 Spring Security应用。现在,我们将学习创建自己的登录页面来验证用户。

默认情况下,Spring Security 框架提供了自己的登录页面获取用户凭据,但也允许我们设置自己的自定义登录页面。当我们想要呈现与公司网站主题相匹配的登录页面时,它非常有用。我们将通过创建一个login.jsp页面来实现,该页面包含一个带有两个输入字段和一个提交按钮的表单。它将提交到"/认证用户"操作,然后 Spring Security 将根据提供的输入执行认证。

自定义登录表单

这是我们自己的登录页面,将在我们的应用中使用,并呈现给浏览器以验证用户。我们使用 Spring Tag-lib 库来创建表单,但是您也可以使用简单的 HTML 表单,并且pageContext是一个隐式对象,用于在运行时获取该页面的上下文网址。

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Login Page</title>
</head>
<body>
	<form:form
		action="${pageContext.request.contextPath}/authenticateTheUser"
		method="post">
		<label for="name">Enter User Name</label>
		<input type="text" name="username">
		<br>
		<br>
		<label for="password">Enter Password</label>
		<input type="password" name="password">
		<br>
		<br>
		<input type="submit" value="Login">
	</form:form>
</body>
</html>

//app config . Java

这是我们的应用配置文件,它实现了WebMvcConfugurer接口来制作这个 MVC 应用,并创建了一个方法 viewResolver 来映射我们的视图文件(JSP)。

package com.studytonight;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@EnableWebMvc
@Configuration
@ComponentScan("com.studytonight.controller")
public class AppConfig implements WebMvcConfigurer{
	@Bean
	public ViewResolver viewResolver() {
		InternalResourceViewResolver irvr = new InternalResourceViewResolver();
		irvr.setPrefix("WEB-INF/views/");
		irvr.setSuffix(".jsp");
		irvr.setOrder(0);
		return irvr;
	}
}

//main app . Java

这个类初始化我们的网络应用,并通过注册我们的 AppConfig 类(上面的文件)来创建ServletContext

package com.studytonight;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
public class MainApp implements WebApplicationInitializer {

	@Override
	public void onStartup(ServletContext servletContext) throws ServletException {
		System.out.println("started");
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
		context.register(AppConfig.class);
		context.setServletContext(servletContext);
		ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
		servlet.setLoadOnStartup(1);
		servlet.addMapping("/");
		context.close();	
	}
}

//securityappnitizer . Java

这是扩展AbstractSecurityWebApplicationInitializer的安全初始化器类,我们传递了SecurityConfig类,这样它就可以读取安全配置。

package com.studytonight;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityAppInitializer  extends AbstractSecurityWebApplicationInitializer {

	public SecurityAppInitializer() {
		super(SecurityConfig.class);
	}
}

// SecurityConfig.java

这是我们的安全配置文件,扩展了WebSecurityConfigurerAdapter类,提供了configure()等几种方法来配置安全性。Spring Security 提供了作为认证管理器的AuthenticationManagerBuilder类,并提供了几种方法来验证用户。这里,我们使用inMemoryAuthentication概念,它允许映射硬编码的用户值。

我们使用HttpSecurity类来配置登录页面。loginPage()用于指定我们的login.jsp页面。我们还可以使用任何其他名称作为登录表单,如 login-form.jsp 或 user-login.jsp,然后指定到该方法的映射。这里传递的"/登录"值将映射到控制器的动作,然后呈现 JSP 页面。

package com.studytonight;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.User.UserBuilder;

@Configuration
@EnableWebSecurity	
public class SecurityConfig extends WebSecurityConfigurerAdapter{

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {

		UserBuilder users = User.withDefaultPasswordEncoder();		
		auth.inMemoryAuthentication()
			.withUser(users.username("studytonight").password("abc123").roles("admin"));
	}

	@Autowired
	protected void configure(HttpSecurity hs) throws Exception {
		hs.authorizeRequests().anyRequest()
		.authenticated()
		.and()
		.formLogin()
		.loginPage("/login")
		.loginProcessingUrl("/authenticateTheUser")
		.permitAll();
	}
}

//user controller . Java

这是我们的控制器类,它作为用户请求处理程序工作,将用户请求与资源进行映射,并相应地返回响应。我们创建了 home()方法来显示index.jsp页面,当然()方法来显示course.jsp页面。

package com.studytonight.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class UserController {

	@GetMapping("/login")
	public String login() {
		return "login";
	}

	@GetMapping("/")  
	public String home() {
		return "index";
	}

	@GetMapping("/java-course")
	public String course() {
		return "course";
	}

	@GetMapping("/premium-courses")
	public String premiumCourse() {
		return "premium-courses";
	}
}

查看文件

这些是显示在浏览器中的项目视图文件。查看代码。

//特级 courses.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Course Page</title>
</head>
<body>
	<h2>List of Premium Courses</h2>
	<ul>
		<li>Spring Framework</li>
		<li>Pandas</li>
		<li>Spring Security</li>
	</ul>
</body>
</html>

//course.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Course Page</title>
</head>
<body>
	<h2>List of Courses</h2>
	<ul>
		<li>Java</li>
		<li>Python</li>
		<li>C++</li>
		<li>Linux</li>
	</ul>
</body>
</html>

//index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Home Page</title>
</head>
<body>
	<h2>Welcome to Studytonight!</h2>
	<h3><a href="java-course">Study Java</a></h3>
	<h2><a href="premium-courses">Study Premium Courses</a></h2>
</body>
</html>

//POM/XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>springwithsecurity</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
		<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>4.0.1</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/jstl/jstl -->
<dependency>
    <groupId>jstl</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>

		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.3.3</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
		<dependency>
			<groupId>javax.servlet.jsp.jstl</groupId>
			<artifactId>jstl-api</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.3.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>5.4.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>5.4.2</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.3</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.5.1</version>
				<configuration>
					<source>11</source>
					<target>11</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

项目结构

创建这些文件后,我们的项目将如下所示。你可以参考这个来了解项目的目录结构。

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

注意:在我们的应用中,我们创建了一个 login.jsp 页面,并配置了 Spring Security。现在,当我们运行应用时,它会呈现一个登录页面,这是我们自己的页面。

它会将用户名和密码与SecurityConfig.java文件中提供的凭据进行匹配。

提供正确的用户名和密码

主页

现在,您已成功登录到应用。这是我们的index.jsp文件渲染为浏览器的主页。

至此,我们已经学会了呈现自己的自定义登录页面来验证用户。这是我们自己的自定义登录页面,它可以正常工作,但是如果用户提供了错误的凭据,它将不会显示任何错误。我们将在下一个话题中处理这种情况。



Spring Security 应用中的自定义错误消息

原文:https://www.studytonight.com/spring-framework/custom-error-message-in-spring-security-application

在上一个主题中,我们已经学会了在 Spring Security 中使用一个自定义登录页面,而不是框架内置的登录页面。有了这个登录页面,如果用户传递了错误的凭据,我们就不会显示错误消息。现在,我们将创建一个显示错误消息的登录页面。

为了实现这个特性,Spring 提供了一个 JSTL 核心库,帮助编写表达式语言。将下面的代码放在登录页面的顶部。

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

将上面的行添加到 JSP 页面后,使用下面的代码,如果错误参数被附加到 URL,该代码将显示一条错误消息。如果用户输入了错误的凭据,那么 Spring Security 会通过将错误参数附加到 URL 来响应。

<c:if test="${param.error!=null}">
    <p style="color: red">You entered wrong credentials!</p>
</c:if>

项目源代码

以下是该项目的文件。您可以在项目中使用这些来测试应用。

//app config . Java

这是我们的应用配置文件,它实现了WebMvcConfugurer接口来制作这个 MVC 应用,并创建了一个方法 viewResolver 来映射我们的视图文件(JSP)。

package com.studytonight;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@EnableWebMvc
@Configuration
@ComponentScan("com.studytonight.controller")
public class AppConfig implements WebMvcConfigurer{
	@Bean
	public ViewResolver viewResolver() {
		InternalResourceViewResolver irvr = new InternalResourceViewResolver();
		irvr.setPrefix("WEB-INF/views/");
		irvr.setSuffix(".jsp");
		irvr.setOrder(0);
		return irvr;
	}
}

//main app . Java

这个类初始化我们的网络应用,并通过注册我们的 AppConfig 类来创建ServletContext(上图文件)。

package com.studytonight;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
public class MainApp implements WebApplicationInitializer {

	@Override
	public void onStartup(ServletContext servletContext) throws ServletException {
		System.out.println("started");
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
		context.register(AppConfig.class);
		context.setServletContext(servletContext);
		ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
		servlet.setLoadOnStartup(1);
		servlet.addMapping("/");
		context.close();	
	}
}

//securityappnitizer . Java

这是扩展AbstractSecurityWebApplicationInitializer的安全初始化器类,我们传递了SecurityConfig类,这样它就可以读取安全配置。

package com.studytonight;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityAppInitializer  extends AbstractSecurityWebApplicationInitializer {

	public SecurityAppInitializer() {
		super(SecurityConfig.class);
	}
}

// SecurityConfig.java

这是我们的安全配置文件,扩展了WebSecurityConfigurerAdapter类,提供了configure()等几种方法来配置安全性。Spring Security 提供了作为认证管理器的AuthenticationManagerBuilder类,并提供了几种方法来验证用户。这里,我们使用inMemoryAuthentication概念,它允许映射硬编码的用户值。

我们使用HttpSecurity类来配置登录页面。loginPage()方法用于指定我们的login.jsp页面。我们还可以为登录表单使用任何其他名称,如 login-form.jsp 或 user-login.jsp,然后指定到该方法的映射。这里传递的"/登录"值将映射到控制器的动作,然后呈现 JSP 页面。

package com.studytonight;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.User.UserBuilder;

@Configuration
@EnableWebSecurity	
public class SecurityConfig extends WebSecurityConfigurerAdapter{

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {

		UserBuilder users = User.withDefaultPasswordEncoder();		
		auth.inMemoryAuthentication()
			.withUser(users.username("studytonight").password("abc123").roles("admin"));
	}

	@Autowired
	protected void configure(HttpSecurity hs) throws Exception {
		hs.authorizeRequests().anyRequest()
		.authenticated()
		.and()
		.formLogin()
		.loginPage("/login")
		.loginProcessingUrl("/authenticateTheUser")
		.permitAll();
	}
}

//user controller . Java

这是我们的控制器类,它作为用户请求处理程序工作,将用户请求与资源进行映射,并相应地返回响应。我们创建了 login()方法来呈现登录页面,home()方法来显示index.jsp页面,当然()方法来显示course.jsp页面。

package com.studytonight.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class UserController {

	@GetMapping("/login")
	public String login() {
		return "login";
	}

	@GetMapping("/")  
	public String home() {
		return "index";
	}

	@GetMapping("/java-course")
	public String course() {
		return "course";
	}

	@GetMapping("/premium-courses")
	public String premiumCourse() {
		return "premium-courses";
	}
}

查看文件

这些是显示在浏览器中的项目视图文件。查看代码。

//特级 courses.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Course Page</title>
</head>
<body>
	<h2>List of Premium Courses</h2>
	<ul>
		<li>Spring Framework</li>
		<li>Pandas</li>
		<li>Spring Security</li>
	</ul>
</body>
</html>

//course.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Course Page</title>
</head>
<body>
	<h2>List of Courses</h2>
	<ul>
		<li>Java</li>
		<li>Python</li>
		<li>C++</li>
		<li>Linux</li>
	</ul>
</body>
</html>

//index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Home Page</title>
</head>
<body>
	<h2>Welcome to Studytonight!</h2>
	<h3><a href="java-course">Study Java</a></h3>
	<h2><a href="premium-courses">Study Premium Courses</a></h2>
</body>
</html>

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>springwithsecurity</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
		<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>4.0.1</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/jstl/jstl -->
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.3.3</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
		<dependency>
			<groupId>javax.servlet.jsp.jstl</groupId>
			<artifactId>jstl-api</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.3.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>5.4.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>5.4.2</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.3</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.5.1</version>
				<configuration>
					<source>11</source>
					<target>11</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

项目结构

创建这些文件后,我们的项目将如下所示。你可以参考这个来了解项目的目录结构。

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

注意:在我们的应用中,我们创建了一个 login.jsp 页面,并配置了 Spring Security。现在,当我们运行应用时,它会呈现一个登录页面,这是我们自己的页面。

它会将用户名和密码与SecurityConfig.java文件中提供的凭据进行匹配。

提供错误的用户名和密码

自定义错误消息

这个错误信息实际上是我们添加到 login.jsp 页面的信息。您可以再次查看登录页面来验证此消息。

提供正确的用户名和密码

主页

现在,您已成功登录到应用。这是我们的index.jsp文件渲染为浏览器的主页。

到这里为止,我们已经学会了如果用户输入了错误的用户名和密码,将显示自定义错误消息。这是我们自己的自定义登录页面,我们将在下一个主题中添加注销功能。



Spring Security 应用中的注销用户

原文:https://www.studytonight.com/spring-framework/logout-user-in-spring-security-application

在上一个主题中,我们已经学习了在登录页面中添加一条自定义错误消息。现在,我们将看到如何在我们的应用中实现注销功能,以便成功登录的用户也可以注销。

要实现此功能,请执行以下步骤

  • 添加注销按钮

  • 配置安全性

  • 显示消息

添加注销按钮

首先,在 JSP 页面中添加一个按钮,允许用户注销。该按钮是一个提交按钮,它向将由 Spring Security 处理的注销 URL 提交表单请求。放在 JSP 首页。

<form:form
	action="${pageContext.request.contextPath}/logout"
	method="post">
	<input type="submit" value="logout">
</form:form>

配置安全性

现在,通过添加 logout()和 permitAll()方法来更新安全配置类。logout()方法将注销用户,permitAll()方法允许所有用户使用注销功能。

.logout()
		.permitAll();

显示消息

现在,设置一条消息,在用户成功注销时向用户显示。将其添加到登录页面,以便在成功注销后向用户显示注销消息。

<c:if test="${param.logout!=null}">
	<p style="color: green">You have successfully logged out.!</p>
</c:if>

举个例子

现在,将所有步骤合并到这个项目中,创建一个应用,允许登录、注销,并在单击注销按钮时给出正确的注销消息。请参见以下文件和源代码。

//app config . Java

这是我们的应用配置文件,它实现了WebMvcConfugurer接口来制作这个 MVC 应用,并创建了一个方法 viewResolver 来映射我们的视图文件(JSP)。

package com.studytonight;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@EnableWebMvc
@Configuration
@ComponentScan("com.studytonight.controller")
public class AppConfig implements WebMvcConfigurer{
	@Bean
	public ViewResolver viewResolver() {
		InternalResourceViewResolver irvr = new InternalResourceViewResolver();
		irvr.setPrefix("WEB-INF/views/");
		irvr.setSuffix(".jsp");
		irvr.setOrder(0);
		return irvr;
	}
}

//main app . Java

这个类初始化我们的网络应用,并通过注册我们的 AppConfig 类来创建ServletContext(上图文件)。

package com.studytonight;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
public class MainApp implements WebApplicationInitializer {

	@Override
	public void onStartup(ServletContext servletContext) throws ServletException {
		System.out.println("started");
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
		context.register(AppConfig.class);
		context.setServletContext(servletContext);
		ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
		servlet.setLoadOnStartup(1);
		servlet.addMapping("/");
		context.close();	
	}
}

//securityappnitizer . Java

这是扩展AbstractSecurityWebApplicationInitializer的安全初始化器类,我们传递了SecurityConfig类,这样它就可以读取安全配置。

package com.studytonight;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityAppInitializer  extends AbstractSecurityWebApplicationInitializer {

	public SecurityAppInitializer() {
		super(SecurityConfig.class);
	}
}

// SecurityConfig.java

这是我们的安全配置文件,扩展了WebSecurityConfigurerAdapter类,提供了configure()等几种方法来配置安全性。Spring Security 提供了作为认证管理器的AuthenticationManagerBuilder类,并提供了几种方法来验证用户。这里,我们使用inMemoryAuthentication概念,它允许映射硬编码的用户值。

我们使用HttpSecurity类来配置登录页面。loginPage()方法用于指定我们的login.jsp页面。我们还可以为登录表单使用任何其他名称,如 login-form.jsp 或 user-login.jsp,然后指定到该方法的映射。这里传递的"/登录"值将映射到控制器的动作,然后呈现 JSP 页面。

我们使用注销()方法在我们的应用中启用注销功能。

package com.studytonight;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.User.UserBuilder;

@Configuration
@EnableWebSecurity	
public class SecurityConfig extends WebSecurityConfigurerAdapter{

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {

		UserBuilder users = User.withDefaultPasswordEncoder();		
		auth.inMemoryAuthentication()
		.withUser(users.username("studytonight").password("abc123").roles("admin"));
	}

	@Autowired
	protected void configure(HttpSecurity hs) throws Exception {
		hs.authorizeRequests().anyRequest()
		.authenticated()
		.and()
		.formLogin()
		.loginPage("/login")
		.loginProcessingUrl("/authenticateTheUser")
		.permitAll()
		.and()
		.logout()
		.permitAll();
	}
}

//user controller . Java

这是我们的控制器类,它作为用户请求处理程序工作,将用户请求与资源进行映射,并相应地返回响应。我们创建了 login()方法来呈现登录页面,home()方法来显示index.jsp页面,当然()方法来显示course.jsp页面。

package com.studytonight.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class UserController {

	@GetMapping("/login")
	public String login() {
		return "login";
	}

	@GetMapping("/")  
	public String home() {
		return "index";
	}

	@GetMapping("/java-course")
	public String course() {
		return "course";
	}

	@GetMapping("/premium-courses")
	public String premiumCourse() {
		return "premium-courses";
	}
}

查看文件

这些是显示在浏览器中的项目视图文件。查看代码。

//course.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Course Page</title>
</head>
<body>
	<h2>List of Courses</h2>
	<ul>
		<li>Java</li>
		<li>Python</li>
		<li>C++</li>
		<li>Linux</li>
	</ul>
</body>
</html>

//index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
	<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Home Page</title>
</head>
<body>
	<h2>Welcome to Studytonight!</h2>
	<h3>
		<a href="java-course">Study Java</a>
	</h3>
	<h2>
		<a href="premium-courses">Study Premium Courses</a>
	</h2><br><br>
	<form:form
		action="${pageContext.request.contextPath}/logout"
		method="post">
		<input type="submit" value="logout">
	</form:form>
</body>
</html>

//login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Login Page</title>
</head>
<body>
	<form:form
		action="${pageContext.request.contextPath}/authenticateTheUser"
		method="post">
		<c:if test="${param.error!=null}">
			<p style="color: red">You entered wrong credentials!</p>

		</c:if>
		<c:if test="${param.logout!=null}">
			<p style="color: green">You have successfully logged out.!</p>
		</c:if>
		<label for="name">Enter User Name</label>
		<input type="text" name="username">
		<br>
		<br>
		<label for="password">Enter Password</label>
		<input type="password" name="password">
		<br>
		<br>
		<input type="submit" value="Login">
	</form:form>
</body>
</html>

//premium-course.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Course Page</title>
</head>
<body>
	<h2>List of Premium Courses</h2>
	<ul>
		<li>Spring Framework</li>
		<li>Pandas</li>
		<li>Spring Security</li>
	</ul>
</body>
</html>

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>springwithsecurity</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
		<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>4.0.1</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/jstl/jstl -->
<dependency>
    <groupId>jstl</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>

		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.3.3</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
		<dependency>
			<groupId>javax.servlet.jsp.jstl</groupId>
			<artifactId>jstl-api</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.3.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>5.4.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>5.4.2</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.3</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.5.1</version>
				<configuration>
					<source>11</source>
					<target>11</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

项目结构

创建这些文件后,我们的项目将如下所示。你可以参考这个来了解项目的目录结构。

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

这是我们自己的自定义登录页面,将用户名和密码与SecurityConfig.java文件中提供的凭据进行匹配。

提供正确的用户名和密码

主页

现在,您已成功登录到应用。这是我们的index.jsp文件渲染为浏览器的主页。看,它有一个注销按钮,我们添加到了index.jsp页面。

注销成功

如果用户点击注销按钮,那么它将在关闭所有会话后被重定向到登录页面,并向登录页面显示一条消息。



Spring Security 处理 CSRF 令牌

原文:https://www.studytonight.com/spring-framework/spring-security-handling-csrf-tokens

在本主题中,我们将了解 CSRF 令牌及其在 Spring 应用中的使用。CSRF(跨站点请求伪造)令牌是在客户端生成并发送到服务器以在客户端和服务器之间建立安全通信的唯一令牌。这些令牌对于安全目的很重要,因此当我们使用 spring security 时,我们必须确保我们的表单包含 CSRF 令牌。

如果我们使用 spring 的表单标签库来创建表单,那么默认情况下,spring 会自动这样做,并使用 spring 表单添加 CSRF 令牌。这是一个隐藏的类型字段,因此它不会显示在浏览器中,但是您可以通过浏览页面源来查看它,它看起来类似于下面的内容。

<input type="hidden" name="_csrf" value="194438e4-b903-4d1a-8b86-295bca37227c" /> 

如果我们不使用 Spring 形式的标签库怎么办,那么我们需要手动将这些标记添加到 HTML 表单中。

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}">

如果我们没有使用 HTML 形式的 CSRF 令牌,那么服务器拒绝授权请求,并抛出禁止的错误。

因此,将这个标记添加到您的 HTML 表单中,或者简单地使用 Spring 表单标签库来创建表单。请看下面的例子,我们使用了 HTML 表单并手动添加了 CSRF 令牌。

举个例子

项目源代码

以下是该项目的文件。您可以在项目中使用这些来创建一个 Spring Security 应用。

//app config . Java

这是我们的应用配置文件,它实现了WebMvcConfugurer接口来制作这个 MVC 应用,并创建了一个方法 viewResolver 来映射我们的视图文件(JSP)。

package com.studytonight;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@EnableWebMvc
@Configuration
@ComponentScan("com.studytonight.controller")
public class AppConfig implements WebMvcConfigurer{
	@Bean
	public ViewResolver viewResolver() {
		InternalResourceViewResolver irvr = new InternalResourceViewResolver();
		irvr.setPrefix("WEB-INF/views/");
		irvr.setSuffix(".jsp");
		irvr.setOrder(0);
		return irvr;
	}
}

//main app . Java

这个类初始化我们的网络应用,并通过注册我们的 AppConfig 类来创建ServletContext(上图文件)。

package com.studytonight;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
public class MainApp implements WebApplicationInitializer {

	@Override
	public void onStartup(ServletContext servletContext) throws ServletException {
		System.out.println("started");
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
		context.register(AppConfig.class);
		context.setServletContext(servletContext);
		ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
		servlet.setLoadOnStartup(1);
		servlet.addMapping("/");
		context.close();	
	}
}

//securityappnitizer . Java

这是扩展AbstractSecurityWebApplicationInitializer的安全初始化器类,我们传递了SecurityConfig类,这样它就可以读取安全配置。

package com.studytonight;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityAppInitializer  extends AbstractSecurityWebApplicationInitializer {

	public SecurityAppInitializer() {
		super(SecurityConfig.class);
	}
}

// SecurityConfig.java

这是我们的安全配置文件,扩展了WebSecurityConfigurerAdapter类,提供了configure()等几种方法来配置安全性。Spring Security 提供了作为认证管理器的AuthenticationManagerBuilder类,并提供了几种方法来验证用户。这里,我们使用inMemoryAuthentication概念,它允许映射硬编码的用户值。

我们使用HttpSecurity类来配置登录页面。loginPage()方法用于指定我们的login.jsp页面。我们还可以为登录表单使用任何其他名称,如 login-form.jsp 或 user-login.jsp,然后指定到该方法的映射。这里传递的"/登录"值将映射到控制器的动作,然后呈现 JSP 页面。

package com.studytonight;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.User.UserBuilder;

@Configuration
@EnableWebSecurity	
public class SecurityConfig extends WebSecurityConfigurerAdapter{

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {

		UserBuilder users = User.withDefaultPasswordEncoder();		
		auth.inMemoryAuthentication()
		.withUser(users.username("studytonight").password("abc123").roles("admin"));
	}

	@Autowired
	protected void configure(HttpSecurity hs) throws Exception {
		hs.authorizeRequests().anyRequest()
		.authenticated()
		.and()
		.formLogin()
		.loginPage("/login")
		.loginProcessingUrl("/authenticateTheUser")
		.permitAll()
		.and()
		.logout()
		.permitAll();
	}
}

//user controller . Java

这是我们的控制器类,它作为用户请求处理程序工作,将用户请求与资源进行映射,并相应地返回响应。我们创建了 login()方法来呈现登录页面,home()方法来显示index.jsp页面,当然()方法来显示course.jsp页面。

package com.studytonight.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class UserController {

	@GetMapping("/login")
	public String login() {
		return "login";
	}

	@GetMapping("/")  
	public String home() {
		return "index";
	}

	@GetMapping("/java-course")
	public String course() {
		return "course";
	}

	@GetMapping("/premium-courses")
	public String premiumCourse() {
		return "premium-courses";
	}
}

查看文件

这些是显示在浏览器中的项目视图文件。查看代码。

//courses.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Course Page</title>
</head>
<body>
	<h2>List of Courses</h2>
	<ul>
		<li>Java</li>
		<li>Python</li>
		<li>C++</li>
		<li>Linux</li>
	</ul>
</body>
</html>

//index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
	<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Home Page</title>
</head>
<body>
	<h2>Welcome to Studytonight!</h2>
	<h3>
		<a href="java-course">Study Java</a>
	</h3>
	<h2>
		<a href="premium-courses">Study Premium Courses</a>
	</h2><br><br>
	<form:form
		action="${pageContext.request.contextPath}/logout"
		method="post">
		<input type="submit" value="logout">
	</form:form>
</body>
</html>

//login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Login Page</title>
</head>
<body>
	<form
		action="${pageContext.request.contextPath}/authenticateTheUser"
		method="post">
		<c:if test="${param.error!=null}">
			<p style="color: red">You entered wrong credentials!</p>

		</c:if>
		<c:if test="${param.logout!=null}">
			<p style="color: green">You have successfully logged out.!</p>
		</c:if>
		<label for="name">Enter User Name</label>
		<input type="text" name="username">
		<br>
		<br>
		<label for="password">Enter Password</label>
		<input type="password" name="password">
		<br>
		<br>
		<input type="submit" value="Login">

		<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}">		

	</form>
</body>
</html>

//premium-courses.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Course Page</title>
</head>
<body>
	<h2>List of Premium Courses</h2>
	<ul>
		<li>Spring Framework</li>
		<li>Pandas</li>
		<li>Spring Security</li>
	</ul>
</body>
</html>

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>springwithsecurity</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
		<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>4.0.1</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/jstl/jstl -->
<dependency>
    <groupId>jstl</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>

		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.3.3</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
		<dependency>
			<groupId>javax.servlet.jsp.jstl</groupId>
			<artifactId>jstl-api</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.3.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>5.4.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>5.4.2</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.3</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.5.1</version>
				<configuration>
					<source>11</source>
					<target>11</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

项目结构

创建这些文件后,我们的项目将如下所示。你可以参考这个来了解项目的目录结构。

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

注意:在我们的应用中,我们创建了一个 login.jsp 页面,并手动添加了 CSRF 令牌来创建一个安全表单。

它会将用户名和密码与SecurityConfig.java文件中提供的凭据进行匹配。

提供正确的用户名和密码

主页

现在,您已成功登录到应用。这是我们的index.jsp文件渲染为浏览器的主页。

注意:如果我们添加的 CSRF 令牌不起作用,那么我们会得到一个我们在文章开头提到的错误。



在 JSP 页面上获取用户信息

原文:https://www.studytonight.com/spring-framework/fetch-user-information-on-jsp-page

在本主题中,我们将学习在 JSP 页面中获取登录用户的信息。Spring 提供了一个标签库,其中包含几个标签,包括认证标签认证标签可以用来获取当前用户的信息,比如显示其权限的姓名和角色。

要实现这一点,我们需要做的就是将 Spring 标签库依赖添加到 pom.xml 文件中,在 JSP 页面顶部声明标签库,在 JSP 页面中使用 <认证> 标签。因此,只需按照以下步骤在 Spring Security 项目中实现这一点。

添加相关性

我们需要将这个标签库依赖项添加到 POM.xml 文件中,这样我们就可以使用认证标签了。

<dependency>
	<groupId>org.springframework.security</groupId>
	<artifactId>spring-security-taglibs</artifactId>
	<version>5.4.1</version>
</dependency>

声明库

要使用这个标签,我们必须在 JSP 页面的顶部声明这个库。

<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags"%>

添加标签

最后,在 JSP 页面的任何地方使用这个标签向浏览器显示用户信息。例如,我们想要获取用户名及其权限,然后在 JSP 页面中使用下面的行。

<security:authentication property="principal.username"/>
<security:authentication property="principal.authorities"/>

举个例子

现在,让我们通过例子来理解。我们创建了一个基于 maven 的 Spring Security 项目,其中包含以下文件。

//app config . Java

这是我们的应用配置文件,它实现了WebMvcConfugurer接口来制作这个 MVC 应用,并创建了一个方法 viewResolver 来映射我们的视图文件(JSP)。

@EnableWebMvc 注释用于使我们的应用成为具有 Mvc 模式的 web 应用。

@Configuration 注释用于将这个类声明为一个配置类, @ComponentScan 注释用于扫描我们应用的组件类。

package com.studytonight;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@EnableWebMvc
@Configuration
@ComponentScan("com.studytonight.controller")
public class AppConfig implements WebMvcConfigurer{
	@Bean
	public ViewResolver viewResolver() {
		InternalResourceViewResolver irvr = new InternalResourceViewResolver();
		irvr.setPrefix("WEB-INF/views/");
		irvr.setSuffix(".jsp");
		irvr.setOrder(0);
		return irvr;
	}
}

//main app . Java

这个类初始化我们的网络应用,并通过注册我们的 AppConfig 类来创建ServletContext(上图文件)。

package com.studytonight;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
public class MainApp implements WebApplicationInitializer {

	@Override
	public void onStartup(ServletContext servletContext) throws ServletException {
		System.out.println("started");
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
		context.register(AppConfig.class);
		context.setServletContext(servletContext);
		ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
		servlet.setLoadOnStartup(1);
		servlet.addMapping("/");
		context.close();	
	}
}

//securityappnitizer . Java

这是扩展AbstractSecurityWebApplicationInitializer的安全初始化器类,我们传递了SecurityConfig类,这样它就可以读取安全配置。

package com.studytonight;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityAppInitializer  extends AbstractSecurityWebApplicationInitializer {

	public SecurityAppInitializer() {
		super(SecurityConfig.class);
	}
}

// SecurityConfig.java

这是我们的安全配置文件,扩展了WebSecurityConfigurerAdapter类,提供了configure()等几种方法来配置安全性。Spring Security 提供了作为认证管理器的AuthenticationManagerBuilder类,并提供了几种方法来验证用户。这里,我们使用inMemoryAuthentication概念,它允许映射硬编码的用户值。

我们使用HttpSecurity类来配置登录页面。loginPage()方法用于指定我们的login.jsp页面。我们还可以为登录表单使用任何其他名称,如 login-form.jsp 或 user-login.jsp,然后指定到该方法的映射。这里传递的"/登录"值将映射到控制器的动作,然后呈现 JSP 页面。

package com.studytonight;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.User.UserBuilder;

@Configuration
@EnableWebSecurity	
public class SecurityConfig extends WebSecurityConfigurerAdapter{

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {

		UserBuilder users = User.withDefaultPasswordEncoder();		
		auth.inMemoryAuthentication()
		.withUser(users.username("studytonight").password("abc123").roles("admin"));
	}

	@Autowired
	protected void configure(HttpSecurity hs) throws Exception {
		hs.authorizeRequests().anyRequest()
		.authenticated()
		.and()
		.formLogin()
		.loginPage("/login")
		.loginProcessingUrl("/authenticateTheUser")
		.permitAll()
		.and()
		.logout()
		.permitAll();
	}
}

//user controller . Java

这是我们的控制器类,它作为用户请求处理程序工作,将用户请求与资源进行映射,并相应地返回响应。我们创建了 login()方法来呈现登录页面,home()方法来显示index.jsp页面,当然()方法来显示course.jsp页面。

package com.studytonight.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class UserController {

	@GetMapping("/login")
	public String login() {
		return "login";
	}

	@GetMapping("/")  
	public String home() {
		return "index";
	}

	@GetMapping("/java-course")
	public String course() {
		return "course";
	}

	@GetMapping("/premium-courses")
	public String premiumCourse() {
		return "premium-courses";
	}
}

查看文件

这些是显示在浏览器中的项目视图文件。查看代码。

//course.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Course Page</title>
</head>
<body>
	<h2>List of Courses</h2>
	<ul>
		<li>Java</li>
		<li>Python</li>
		<li>C++</li>
		<li>Linux</li>
	</ul>
</body>
</html>

//index.jsp

这里,我们使用认证标签来显示登录用户的用户名和权限。

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
	<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
	<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Home Page</title>
</head>
<body>
	<h2>Welcome to Studytonight!</h2>
	<h3>
		<a href="java-course">Study Java</a>
	</h3>
	<h2>
		<a href="premium-courses">Study Premium Courses</a>
	</h2>
	<br><br>
	User: <security:authentication property="principal.username"/> <br><br>
	Role: <security:authentication property="principal.authorities"/>
	<br><br>
	<form:form
		action="${pageContext.request.contextPath}/logout"
		method="post">
		<input type="submit" value="logout">
	</form:form>
</body>
</html>

//login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Login Page</title>
</head>
<body>
	<form:form
		action="${pageContext.request.contextPath}/authenticateTheUser"
		method="post">
		<c:if test="${param.error!=null}">
			<p style="color: red">You entered wrong credentials!</p>

		</c:if>
		<c:if test="${param.logout!=null}">
			<p style="color: green">You have successfully logged out.!</p>
		</c:if>
		<label for="name">Enter User Name</label>
		<input type="text" name="username">
		<br>
		<br>
		<label for="password">Enter Password</label>
		<input type="password" name="password">
		<br>
		<br>
		<input type="submit" value="Login">
	</form:form>
</body>
</html>

//premium-courses.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Course Page</title>
</head>
<body>
	<h2>List of Premium Courses</h2>
	<ul>
		<li>Spring Framework</li>
		<li>Pandas</li>
		<li>Spring Security</li>
	</ul>
</body>
</html>

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>springwithsecurity</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
		<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>4.0.1</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/jstl/jstl -->
		<dependency>
			<groupId>jstl</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.3.3</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
		<dependency>
			<groupId>javax.servlet.jsp.jstl</groupId>
			<artifactId>jstl-api</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.3.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>5.4.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>5.4.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-taglibs -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-taglibs</artifactId>
			<version>5.4.1</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.3</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.5.1</version>
				<configuration>
					<source>11</source>
					<target>11</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

项目结构

创建这些文件后,我们的项目将如下所示。你可以参考这个来了解项目的目录结构。

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

这是我们自己的登录页面,将提交至/authenticatheuserURL,并将用户名和密码与SecurityConfig.java文件中提供的凭据进行匹配。

提供正确的用户名和密码

主页

现在,您已成功登录到应用。这是我们的index.jsp文件渲染为浏览器的主页。

注意,因为我们使用了 authenticate 标签,所以它显示了用户名和用户角色等用户详细信息。



在 JSP 页面上显示基于用户角色的用户数据

原文:https://www.studytonight.com/spring-framework/display-user-data-based-on-user-role-on-jsp-page

在本主题中,我们将学习根据用户角色显示数据。这意味着访客用户看不到管理员或任何其他角色的数据。当应用处理多个用户层次结构时,这很有用。例如,经理可以访问管理相关数据,但不能访问管理相关数据。

Spring 提供了一个标签库,其中包含一个用于检查用户权限的授权标签。要了解如何将 Spring 标签库添加到我们的项目中,您可以参考我们之前的主题。在这里,我们将看到如何实现它的 authorize 标签。下面给出了这个标签的一般语法。

<security:authorize access="hasRole('GUEST')">
</security:authorize>

举个例子

现在,让我们通过例子来理解。我们创建了一个基于 maven 的 Spring Security 项目,其中包含以下文件。

//app config . Java

这是我们的应用配置文件,它实现了WebMvcConfugurer接口来制作这个 MVC 应用,并创建了一个方法 viewResolver 来映射我们的视图文件(JSP)。

@EnableWebMvc 注释用于使我们的应用成为具有 Mvc 模式的 web 应用。

@Configuration 注释用于将这个类声明为一个配置类, @ComponentScan 注释用于扫描我们应用的组件类。

package com.studytonight;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@EnableWebMvc
@Configuration
@ComponentScan("com.studytonight.controller")
public class AppConfig implements WebMvcConfigurer{
	@Bean
	public ViewResolver viewResolver() {
		InternalResourceViewResolver irvr = new InternalResourceViewResolver();
		irvr.setPrefix("WEB-INF/views/");
		irvr.setSuffix(".jsp");
		irvr.setOrder(0);
		return irvr;
	}
}

//main app . Java

这个类初始化我们的网络应用,并通过注册我们的 AppConfig 类来创建ServletContext(上图文件)。

package com.studytonight;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
public class MainApp implements WebApplicationInitializer {

	@Override
	public void onStartup(ServletContext servletContext) throws ServletException {
		System.out.println("started");
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
		context.register(AppConfig.class);
		context.setServletContext(servletContext);
		ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
		servlet.setLoadOnStartup(1);
		servlet.addMapping("/");
		context.close();	
	}
}

//securityappnitizer . Java

这是扩展AbstractSecurityWebApplicationInitializer的安全初始化器类,我们传递了SecurityConfig类,这样它就可以读取安全配置。

package com.studytonight;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityAppInitializer  extends AbstractSecurityWebApplicationInitializer {

	public SecurityAppInitializer() {
		super(SecurityConfig.class);
	}
}

// SecurityConfig.java

这是我们的安全配置文件,扩展了WebSecurityConfigurerAdapter类,提供了configure()等几种方法来配置安全性。Spring Security 提供了作为认证管理器的AuthenticationManagerBuilder类,并提供了几种方法来验证用户。这里,我们使用inMemoryAuthentication概念,它允许映射硬编码的用户值。

我们使用roles()方法设置用户角色。在这里,我们设置了一个用户 GUEST 角色,另一个是 REGESTERED 角色。

我们使用HttpSecurity类来配置登录页面。loginPage()方法用于指定我们的login.jsp页面。我们还可以为登录表单使用任何其他名称,如 login-form.jsp 或 user-login.jsp,然后指定到该方法的映射。这里传递的"/登录"值将映射到控制器的动作,然后呈现 JSP 页面。

package com.studytonight;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.User.UserBuilder;

@Configuration
@EnableWebSecurity	
public class SecurityConfig extends WebSecurityConfigurerAdapter{

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {

		UserBuilder users = User.withDefaultPasswordEncoder();		
		auth.inMemoryAuthentication()
		.withUser(users.username("studytonight").password("abc123").roles("GUEST"))
		.withUser(users.username("pro-studytonight").password("abc123").roles("REGISTERED"));
	}

	@Autowired
	protected void configure(HttpSecurity hs) throws Exception {
		hs.authorizeRequests()
		.antMatchers("/").hasAnyRole("GUEST","REGISTERED")
		.antMatchers("/java-course").hasRole("GUEST")
		.antMatchers("/premium-courses").hasRole("REGISTERED")
		.and()
		.formLogin()
		.loginPage("/login")
		.loginProcessingUrl("/authenticateTheUser")
		.permitAll()
		.and()
		.logout()
		.permitAll()
		.and()
		.exceptionHandling().accessDeniedPage("/unauthorized");
	}
}

//user controller . Java

这是我们的控制器类,它作为用户请求处理程序工作,将用户请求与资源进行映射,并相应地返回响应。我们创建了 login()方法来呈现登录页面,home()方法来显示index.jsp页面,当然()方法来显示course.jsp页面。

package com.studytonight.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class UserController {

	@GetMapping("/login")
	public String login() {
		return "login";
	}

	@GetMapping("/")  
	public String home() {
		return "index";
	}

	@GetMapping("/java-course")
	public String course() {
		return "course";
	}

	@GetMapping("/premium-courses")
	public String premiumCourse() {
		return "premium-courses";
	}

	@GetMapping("/unauthorized")
	public String unauthorized() {
		return "unauthorized-user";
	}
}

查看文件

这些是显示在浏览器中的项目视图文件。查看代码。

//course.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Course Page</title>
</head>
<body>
	<h2>List of Courses</h2>
	<ul>
		<li>Java</li>
		<li>Python</li>
		<li>C++</li>
		<li>Linux</li>
	</ul>
</body>
</html>

//index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
	<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
	<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Home Page</title>
</head>
<body>
	<h2>Welcome to Studytonight!</h2>
	<security:authorize access="hasRole('GUEST')">
	<h3>
		<a href="java-course">Study Java</a>
	</h3>
	</security:authorize>
	<security:authorize access="hasRole('REGISTERED')">
	<h2>
		<a href="premium-courses">Study Premium Courses</a>
	</h2>
	</security:authorize>
	<br><br>
	<form:form
		action="${pageContext.request.contextPath}/logout"
		method="post">
		<input type="submit" value="logout">
	</form:form>
</body>
</html>

//login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Login Page</title>
</head>
<body>
	<form:form
		action="${pageContext.request.contextPath}/authenticateTheUser"
		method="post">
		<c:if test="${param.error!=null}">
			<p style="color: red">You entered wrong credentials!</p>

		</c:if>
		<c:if test="${param.logout!=null}">
			<p style="color: green">You have successfully logged out.!</p>
		</c:if>
		<label for="name">Enter User Name</label>
		<input type="text" name="username">
		<br>
		<br>
		<label for="password">Enter Password</label>
		<input type="password" name="password">
		<br>
		<br>
		<input type="submit" value="Login">
	</form:form>
</body>
</html>

//premium-course.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Course Page</title>
</head>
<body>
	<h2>List of Premium Courses</h2>
	<ul>
		<li>Spring Framework</li>
		<li>Pandas</li>
		<li>Spring Security</li>
	</ul>
</body>
</html>

//unautherized-user.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Unauthorized Page</title>
</head>
<body>
<h2>Error: You are not Authorized to access this Page</h2>
</body>
</html>

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>springwithsecurity</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
		<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>4.0.1</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/jstl/jstl -->
		<dependency>
			<groupId>jstl</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.3.3</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
		<dependency>
			<groupId>javax.servlet.jsp.jstl</groupId>
			<artifactId>jstl-api</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.3.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>5.4.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>5.4.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-taglibs -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-taglibs</artifactId>
			<version>5.4.1</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.3</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.5.1</version>
				<configuration>
					<source>11</source>
					<target>11</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

项目结构

创建这些文件后,我们的项目将如下所示。你可以参考这个来了解项目的目录结构。

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

这是我们自己的登录页面,将提交至/authenticatheuserURL,并将用户名和密码与SecurityConfig.java文件中提供的凭据进行匹配。

提供正确的用户名和密码

来宾访问

这是包含 GUEST 和 REGISTERED 用户信息的主页,但现在它只显示 GUEST 部分,因为该用户具有 GUEST 角色。

登录另一个用户

这次用户的角色是 REGISTERED,所以只能看到高级课程。



JDBC 的 Spring Security 配置

原文:https://www.studytonight.com/spring-framework/spring-security-configuration-with-jdbc

在本主题中,我们将创建一个使用数据库表的数据登录的应用,而不是像我们在前面的文章和示例中所做的那样使用硬编码的值。这是一个简单的过程,我们只需要创建一个数据库,并用我们的项目配置它。创建一个项目对我们来说并不新鲜,因为我们在之前的主题中已经创建了很多次。在这里,我们将用一个数据库配置我们的项目。让我们一步一步来理解它。

  1. 创建数据库和表

  2. 添加数据库依赖项

  3. 提供数据库详细信息

1.创建数据库和表

创建一个数据库 spring_security_db 和其中的两个表,并存储数据。使用下面的 SQL 转储创建数据库和表。

// db.sql

CREATE DATABASE  IF NOT EXISTS `spring_security_db`;
USE `spring_security_db`;

--
-- Table structure for table `users`
--

CREATE TABLE `users` (
  `username` varchar(50) NOT NULL,
  `password` varchar(50) NOT NULL,
  `enabled` tinyint(1) NOT NULL,
  PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Inserting data for table `users`
--

INSERT INTO `users` 
VALUES 
('studytonight','{noop}abc123',1),
('pro-studytonight','{noop}abc123',1);

--
-- Table structure for table `authorities`
--

CREATE TABLE `authorities` (
  `username` varchar(50) NOT NULL,
  `authority` varchar(50) NOT NULL,
  UNIQUE KEY `authorities_idx_1` (`username`,`authority`),
  CONSTRAINT `authorities_ibfk_1` FOREIGN KEY (`username`) REFERENCES `users` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Inserting data for table `authorities`
--

INSERT INTO `authorities` 
VALUES 
('studytonight','ROLE_GUEST'),
('pro-studytonight','ROLE_REGISTERED'); 

执行这些 SQL 查询后,它将创建一个数据库和表,如下所示。

2.添加依赖项

将这些依赖项添加到您的 pom.xml 文件中,以便我们可以配置 Mysql 数据库。

<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>5.1.45</version>
</dependency>
<dependency>
	<groupId>com.mchange</groupId>
	<artifactId>c3p0</artifactId>
	<version>0.9.5.2</version>
</dependency>

3.提供数据库详细信息

在资源目录中创建一个名为persistence-MySQL . properties的属性文件,并将数据库的详细信息如数据库名称和用户凭据放在这里。

#
# JDBC connection properties
#
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_security_db?useSSL=false
jdbc.user=user_name
jdbc.password=db_password

#
# Connection pool properties
#
connection.pool.initialPoolSize=5
connection.pool.minPoolSize=5
connection.pool.maxPoolSize=20
connection.pool.maxIdleTime=3000

并通过在AppConfig.java文件中配置数据源来获取项目中的这些属性值。

@Bean
	public DataSource securityDataSource() {
		ComboPooledDataSource securityDataSource
		= new ComboPooledDataSource();
		try {
			securityDataSource.setDriverClass(env.getProperty("jdbc.driver"));
		} catch (PropertyVetoException exc) {
			throw new RuntimeException(exc);
		}
		logger.info(">>> jdbc.url=" + env.getProperty("jdbc.url"));
		logger.info(">>> jdbc.user=" + env.getProperty("jdbc.user"));
		securityDataSource.setJdbcUrl(env.getProperty("jdbc.url"));
		securityDataSource.setUser(env.getProperty("jdbc.user"));
		securityDataSource.setPassword(env.getProperty("jdbc.password"));
		securityDataSource.setInitialPoolSize(
				getIntProperty("connection.pool.initialPoolSize"));
		securityDataSource.setMinPoolSize(
				getIntProperty("connection.pool.minPoolSize"));
		securityDataSource.setMaxPoolSize(
				getIntProperty("connection.pool.maxPoolSize"));
		securityDataSource.setMaxIdleTime(
				getIntProperty("connection.pool.maxIdleTime"));
		return securityDataSource;
	}

	private int getIntProperty(String propName) {

		String propVal = env.getProperty(propName);
		int intPropVal = Integer.parseInt(propVal);
		return intPropVal;
	}

举个例子

做完这些配置后。让我们创建一个使用 MySQL 数据库验证用户身份的项目。

我们创建了一个基于 maven 的 Spring Security 项目,其中包含以下文件。

//app config . Java

这是我们的应用配置文件,它实现了WebMvcConfugurer接口来制作这个 MVC 应用,并创建了一个方法 viewResolver 来映射我们的视图文件(JSP)。我们又创建了一个方法 securityDataSource() ,它从persistence-MySQL . properties文件中读取数据库详细信息,并返回一个Datasource引用。我们使用@PropertySource注释来指定文件位置。

package com.studytonight;

import java.beans.PropertyVetoException;
import java.util.logging.Logger;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import com.mchange.v2.c3p0.ComboPooledDataSource;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages={"com.studytonight","com.studytonight.controller"})
@PropertySource("classpath:persistence-mysql.properties")
public class AppConfig {

	@Autowired
	private Environment env;	
	private Logger logger = Logger.getLogger(getClass().getName());

	@Bean
	public ViewResolver viewResolver() {

		InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
		viewResolver.setPrefix("/WEB-INF/views/");
		viewResolver.setSuffix(".jsp");
		return viewResolver;
	}

	@Bean
	public DataSource securityDataSource() {
		ComboPooledDataSource securityDataSource
		= new ComboPooledDataSource();
		try {
			securityDataSource.setDriverClass(env.getProperty("jdbc.driver"));
		} catch (PropertyVetoException exc) {
			throw new RuntimeException(exc);
		}
		logger.info(">>> jdbc.url=" + env.getProperty("jdbc.url"));
		logger.info(">>> jdbc.user=" + env.getProperty("jdbc.user"));
		securityDataSource.setJdbcUrl(env.getProperty("jdbc.url"));
		securityDataSource.setUser(env.getProperty("jdbc.user"));
		securityDataSource.setPassword(env.getProperty("jdbc.password"));
		securityDataSource.setInitialPoolSize(
				getIntProperty("connection.pool.initialPoolSize"));
		securityDataSource.setMinPoolSize(
				getIntProperty("connection.pool.minPoolSize"));
		securityDataSource.setMaxPoolSize(
				getIntProperty("connection.pool.maxPoolSize"));
		securityDataSource.setMaxIdleTime(
				getIntProperty("connection.pool.maxIdleTime"));
		return securityDataSource;
	}

	private int getIntProperty(String propName) {

		String propVal = env.getProperty(propName);
		int intPropVal = Integer.parseInt(propVal);
		return intPropVal;
	}
} 

【t0///my pringgmvcdisperservicinitiator . Java

这个类初始化我们的网络应用,并通过注册我们的 AppConfig 类来创建ServletContext(上图文件)。

package com.studytonight;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class MySpringMvcDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

	@Override
	protected Class<?>[] getRootConfigClasses() {
		return null;
	}

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

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

// SecurityConfig.java

这是我们的安全配置文件,扩展了WebSecurityConfigurerAdapter类,提供了configure()等几种方法来配置安全性。Spring Security 提供了作为认证管理器的AuthenticationManagerBuilder类,并提供了几种方法来验证用户。这里,我们使用inMemoryAuthentication概念,它允许映射硬编码的用户值。

我们使用HttpSecurity类来配置登录页面。loginPage()方法用于指定我们的login.jsp页面。我们还可以为登录表单使用任何其他名称,如 login-form.jsp 或 user-login.jsp,然后指定到该方法的映射。这里传递的"/登录"值将映射到控制器的动作,然后呈现 JSP 页面。

package com.studytonight;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	private DataSource securityDataSource;

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.jdbcAuthentication().dataSource(securityDataSource);
	}
	@Override
	protected void configure(HttpSecurity hs) throws Exception {
		hs.authorizeRequests()
		.antMatchers("/").hasAnyRole("GUEST","REGISTERED")
		.antMatchers("/java-course").hasAnyRole("GUEST","REGISTERED")
		.antMatchers("/premium-courses").hasRole("REGISTERED")
		.and()
		.formLogin()
		.loginPage("/login")
		.loginProcessingUrl("/authenticateTheUser")
		.permitAll()
		.and()
		.logout()
		.permitAll()
		.and()
		.exceptionHandling().accessDeniedPage("/unauthorized");
	}
}

//SecurityWebApplicationInitializer.java

这是扩展AbstractSecurityWebApplicationInitializer的安全初始化器类,我们传递了SecurityConfig类,这样它就可以读取安全配置。

package com.studytonight;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;

public class SecurityWebApplicationInitializer 
						extends AbstractSecurityWebApplicationInitializer {

} 

//user controller . Java

这是我们的控制器类,它作为用户请求处理程序工作,将用户请求与资源进行映射,并相应地返回响应。我们创建了 login()方法来呈现登录页面,home()方法来显示index.jsp页面,当然()方法来显示course.jsp页面。

package com.studytonight.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class UserController {

	@GetMapping("/login")
	public String login() {
		return "login";
	}

	@GetMapping("/")  
	public String home() {
		return "index";
	}

	@GetMapping("/java-course")
	public String course() {
		return "course";
	}

	@GetMapping("/premium-courses")
	public String premiumCourse() {
		return "premium-courses";
	}

	@GetMapping("/unauthorized")
	public String unauthorized() {
		return "unauthorized-user";
	}
}

查看文件

这些是显示在浏览器中的项目视图文件。查看代码。

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Course Page</title>
</head>
<body>
	<h2>List of Courses</h2>
	<ul>
		<li>Java</li>
		<li>Python</li>
		<li>C++</li>
		<li>Linux</li>
	</ul>
</body>
</html>

//index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
	<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
	<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Home Page</title>
</head>
<body>
	<h2>Welcome to Studytonight!</h2>
	<security:authorize access="hasRole('GUEST')">
	<h3>
		<a href="java-course">Study Java</a>
	</h3>
	</security:authorize>
	<security:authorize access="hasRole('REGISTERED')">
	<h2>
		<a href="premium-courses">Study Premium Courses</a>
	</h2>
	</security:authorize>
	<br><br>
	<form:form
		action="${pageContext.request.contextPath}/logout"
		method="post">
		<input type="submit" value="logout">
	</form:form>
</body>
</html>

//login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Login Page</title>
</head>
<body>
	<form:form
		action="${pageContext.request.contextPath}/authenticateTheUser"
		method="post">
		<c:if test="${param.error!=null}">
			<p style="color: red">You entered wrong credentials!</p>

		</c:if>
		<c:if test="${param.logout!=null}">
			<p style="color: green">You have successfully logged out.!</p>
		</c:if>
		<label for="name">Enter User Name</label>
		<input type="text" name="username">
		<br>
		<br>
		<label for="password">Enter Password</label>
		<input type="password" name="password">
		<br>
		<br>
		<input type="submit" value="Login">
	</form:form>
</body>
</html>

//premium-courses.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Course Page</title>
</head>
<body>
	<h2>List of Premium Courses</h2>
	<ul>
		<li>Spring Framework</li>
		<li>Pandas</li>
		<li>Spring Security</li>
	</ul>
</body>
</html>

//unauthorized-user.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Unauthorized Page</title>
</head>
<body>
<h2>Error: You are not Authorized to access this Page</h2>
</body>
</html>

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.studytonight</groupId>
	<artifactId>spring-security-db</artifactId>
	<version>1.0</version>
	<packaging>war</packaging>

	<name>spring-security-db</name>

	<properties>
		<springframework.version>5.0.2.RELEASE</springframework.version>
		<springsecurity.version>5.0.0.RELEASE</springsecurity.version>

		<maven.compiler.source>1.8</maven.compiler.source>
		<maven.compiler.target>1.8</maven.compiler.target>
	</properties>

	<dependencies>

		<!-- Spring MVC support -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${springframework.version}</version>
		</dependency>

		<!-- Spring Security -->
		<!-- spring-security-web and spring-security-config -->

		<dependency>
		    <groupId>org.springframework.security</groupId>
		    <artifactId>spring-security-web</artifactId>
		    <version>${springsecurity.version}</version>
		</dependency>

		<dependency>
		    <groupId>org.springframework.security</groupId>
		    <artifactId>spring-security-config</artifactId>
		    <version>${springsecurity.version}</version>
		</dependency>	

		<!-- Add Spring Security Taglibs support -->
		<dependency>
		    <groupId>org.springframework.security</groupId>
		    <artifactId>spring-security-taglibs</artifactId>
		    <version>${springsecurity.version}</version>
		</dependency>	

		<!-- Add MySQL and C3P0 support -->

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.45</version>
		</dependency>

		<dependency>
			<groupId>com.mchange</groupId>
			<artifactId>c3p0</artifactId>
			<version>0.9.5.2</version>
		</dependency>

		<!-- Servlet, JSP and JSTL support -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.1.0</version>
		</dependency>

		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.3.1</version>
		</dependency>

		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>

	</dependencies>

	<!-- TO DO: Add support for Maven WAR Plugin -->

	<build>
		<finalName>spring-security-db</finalName>

		<pluginManagement>
			<plugins>
				<plugin>
					<!-- Add Maven coordinates (GAV) for: maven-war-plugin -->
				    <groupId>org.apache.maven.plugins</groupId>
				    <artifactId>maven-war-plugin</artifactId>
				    <version>3.2.0</version>					
				</plugin>						
			</plugins>
		</pluginManagement>
	</build>

</project> 

项目结构

创建这些文件后,我们的项目将如下所示。你可以参考这个来了解项目的目录结构。

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

它会将用户名和密码与我们在上面创建的数据库中提供的凭据进行匹配。

主页

现在,您已成功登录到应用。这是我们的index.jsp文件渲染为浏览器的主页。



带有“记住我”功能的用户登录

原文:https://www.studytonight.com/spring-framework/user-login-with-remember-me-feature

在本主题中,我们将学习使用 Spring Security 的记住我功能。它允许用户即使在会话关闭后也能记忆。它使用存储的 cookies 执行自动登录。

一个具有“记住我”功能的应用,在浏览器中存储一个 cookie,用于识别用户并避免每次登录时输入用户凭据。所以我们需要做的只是简单的使用 SecurityConfig 类的 configure()方法中的rememberMe()方法。将它添加到 spring 安全项目的配置文件中。

.rememberMe()  
   .key("rem-me-key")  
   .rememberMeParameter("remember")  
   .rememberMeCookieName("rememberlogin")  
   .tokenValiditySeconds(200) 

举个例子

现在,让我们通过例子来理解。我们创建了一个基于 maven 的 Spring Security 项目,其中包含以下文件。

//app config . Java

这是我们的应用配置文件,它实现了WebMvcConfugurer接口来制作这个 MVC 应用,并创建了一个方法 viewResolver 来映射我们的视图文件(JSP)。

@EnableWebMvc 注释用于使我们的应用成为具有 Mvc 模式的 web 应用。

@Configuration 注释用于将这个类声明为一个配置类, @ComponentScan 注释用于扫描我们应用的组件类。

package com.studytonight;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@EnableWebMvc
@Configuration
@ComponentScan("com.studytonight.controller")
public class AppConfig implements WebMvcConfigurer{
	@Bean
	public ViewResolver viewResolver() {
		InternalResourceViewResolver irvr = new InternalResourceViewResolver();
		irvr.setPrefix("WEB-INF/views/");
		irvr.setSuffix(".jsp");
		irvr.setOrder(0);
		return irvr;
	}
}

//main app . Java

这个类初始化我们的网络应用,并通过注册我们的 AppConfig 类来创建ServletContext(上图文件)。

package com.studytonight;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
public class MainApp implements WebApplicationInitializer {

	@Override
	public void onStartup(ServletContext servletContext) throws ServletException {
		System.out.println("started");
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
		context.register(AppConfig.class);
		context.setServletContext(servletContext);
		ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
		servlet.setLoadOnStartup(1);
		servlet.addMapping("/");
		context.close();	
	}
}

//securityappnitizer . Java

这是扩展AbstractSecurityWebApplicationInitializer的安全初始化器类,我们传递了SecurityConfig类,这样它就可以读取安全配置。

package com.studytonight;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityAppInitializer extends AbstractSecurityWebApplicationInitializer {

	public SecurityAppInitializer() {
		super(SecurityConfig.class);
	}
}

// SecurityConfig.java

这是我们的安全配置文件,扩展了WebSecurityConfigurerAdapter类,提供了configure()等几种方法来配置安全性。Spring Security 提供了作为认证管理器的AuthenticationManagerBuilder类,并提供了几种方法来验证用户。这里,我们使用inMemoryAuthentication概念,它允许映射硬编码的用户值。

我们在应用中使用HttpSecurity类来配置 memory-me。rememberMe()方法用于在tokenValiditySeconds()方法指定的时间内记住用户。rememberMeParameter()方法指的是用于 TIC as memory me 的复选框的名称,rememberMeCookieName()方法指的是存储在浏览器中的 cookie 的名称,可以在浏览器中使用该名称进行搜索。

package com.studytonight;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.User.UserBuilder;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{

	@Autowired
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		UserBuilder user = User.withDefaultPasswordEncoder();
		auth.inMemoryAuthentication()
		.withUser(user.username("studytonight").password("abc123").roles("USER"));
	}

	@Autowired
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests().anyRequest()
		.authenticated()
		.and()
		.formLogin().permitAll()
		.and()
		.rememberMe()  
		   .key("rem-me-key")  
		   .rememberMeParameter("remember")  
		   .rememberMeCookieName("rememberlogin")  
		   .tokenValiditySeconds(200);
	}
}

//user controller . Java

这是我们的控制器类,它作为用户请求处理程序工作,将用户请求与资源进行映射,并相应地返回响应。我们创建了 login()方法来呈现登录页面,home()方法来显示index.jsp页面,当然()方法来显示course.jsp页面。

package com.studytonight.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class UserController {

	@GetMapping("/")  
	public String home() {
		return "index";
	}

	@GetMapping("/java-course")
	public String course() {
		return "course";
	}

	@GetMapping("/premium-courses")
	public String premiumCourse() {
		return "premium-courses";
	}
}

查看文件

这些是显示在浏览器中的项目视图文件。查看代码。

//course.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Course Page</title>
</head>
<body>
	<h2>List of Courses</h2>
	<ul>
		<li>Java</li>
		<li>Python</li>
		<li>C++</li>
		<li>Linux</li>
	</ul>
</body>
</html>

//index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
	<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Home Page</title>
</head>
<body>
	<h2>Welcome to Studytonight!</h2>

	<h3>
		<a href="java-course">Study Java</a>
	</h3>

	<h2>
		<a href="premium-courses">Study Premium Courses</a>
	</h2>

	<br><br>
	<form:form
		action="${pageContext.request.contextPath}/logout"
		method="post">
		<input type="submit" value="logout">
	</form:form>
</body>
</html>

//premium-course.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Course Page</title>
</head>
<body>
	<h2>List of Premium Courses</h2>
	<ul>
		<li>Spring Framework</li>
		<li>Pandas</li>
		<li>Spring Security</li>
	</ul>
</body>
</html>

//unauthorized-user.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Unauthorized Page</title>
</head>
<body>
<h2>Error: You are not Authorized to access this Page</h2>
</body>
</html>

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>SpringSecurityRememberMe</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
		<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>4.0.1</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.3.3</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
		<dependency>
			<groupId>javax.servlet.jsp.jstl</groupId>
			<artifactId>jstl-api</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.3.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>5.4.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>5.4.2</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.3</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.5.1</version>
				<configuration>
					<source>11</source>
					<target>11</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

项目结构

创建这些文件后,我们的项目将如下所示。你可以参考这个来了解项目的目录结构。

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

这是我们自己的登录页面,将提交至/authenticatheuserURL,并将用户名和密码与SecurityConfig.java文件中提供的凭据进行匹配。

验证 Cookies

它存储了我们在 SecurityConfig 文件中设置的 cookie。它与我们设置的名称相同,并且有一个加密形式的令牌和过期的 cookie。



Spring Security HTTP 基本认证

原文:https://www.studytonight.com/spring-framework/spring-security-http-basic-authentication

在本主题中,我们将学习在 Spring 应用中使用 HTTP 基本认证。Spring Security 提供 HTTP 基本认证,在客户端对用户进行认证,并将带有请求头的用户凭据发送到服务器。服务器接收这些凭证,从标题中提取它们,并将它们与现有记录映射以验证用户。

BasicAuthenticationFilter处理请求,检查请求是否包含认证头。httpBasic()方法在我们的应用中启用了基本的 HTTP 安全性。让我们创建一个项目并实现 HTTP 安全性。

举个例子

现在,让我们通过例子来理解。我们创建了一个基于 maven 的 Spring Security 项目,其中包含以下文件。

//app config . Java

这是我们的应用配置文件,它实现了WebMvcConfugurer接口来制作这个 MVC 应用,并创建了一个方法 viewResolver 来映射我们的视图文件(JSP)。

@EnableWebMvc 注释用于使我们的应用成为具有 Mvc 模式的 web 应用。

@Configuration 注释用于将这个类声明为一个配置类, @ComponentScan 注释用于扫描我们应用的组件类。

package com.studytonight;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@EnableWebMvc
@Configuration
@ComponentScan("com.studytonight.controller")
public class AppConfig implements WebMvcConfigurer{
	@Bean
	public ViewResolver viewResolver() {
		InternalResourceViewResolver irvr = new InternalResourceViewResolver();
		irvr.setPrefix("WEB-INF/views/");
		irvr.setSuffix(".jsp");
		irvr.setOrder(0);
		return irvr;
	}
}

//main app . Java

这个类初始化我们的网络应用,并通过注册我们的 AppConfig 类来创建ServletContext(上图文件)。

package com.studytonight;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
public class MainApp implements WebApplicationInitializer {

	@Override
	public void onStartup(ServletContext servletContext) throws ServletException {
		System.out.println("started");
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
		context.register(AppConfig.class);
		context.setServletContext(servletContext);
		ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
		servlet.setLoadOnStartup(1);
		servlet.addMapping("/");
		context.close();	
	}
}

//securityappnitizer . Java

这是扩展AbstractSecurityWebApplicationInitializer的安全初始化器类,我们传递了SecurityConfig类,这样它就可以读取安全配置。

package com.studytonight;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityAppInitializer  extends AbstractSecurityWebApplicationInitializer {

	public SecurityAppInitializer() {
		super(SecurityConfig.class);
	}
}

// SecurityConfig.java

这是我们的安全配置文件,扩展了WebSecurityConfigurerAdapter类,提供了configure()等几种方法来配置安全性。Spring Security 提供了作为认证管理器的AuthenticationManagerBuilder类,并提供了几种方法来验证用户。这里,我们使用inMemoryAuthentication概念,它允许映射硬编码的用户值。

我们在应用中使用HttpSecurity类来配置基本认证。httpBasic()方法用于在 HTTP 请求期间启用该功能对用户进行认证。

package com.studytonight;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.User.UserBuilder;

@Configuration
@EnableWebSecurity	
public class SecurityConfig extends WebSecurityConfigurerAdapter{

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {

		UserBuilder users = User.withDefaultPasswordEncoder();		
		auth.inMemoryAuthentication()
		.withUser(users.username("studytonight").password("abc123").roles("GUEST"))
		.withUser(users.username("pro-studytonight").password("abc123").roles("REGISTERED"));
	}

	@Autowired
	protected void configure(HttpSecurity hs) throws Exception {
		 hs.csrf().disable()
         .authorizeRequests().anyRequest().authenticated()
         .and().httpBasic();
	}
}

//user controller . Java

这是我们的控制器类,它作为用户请求处理程序工作,将用户请求与资源进行映射,并相应地返回响应。我们创建了 login()方法来呈现登录页面,home()方法来显示index.jsp页面,当然()方法来显示course.jsp页面。

package com.studytonight.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class UserController {

	@GetMapping("/")  
	public String home() {
		return "index";
	}

	@GetMapping("/java-course")
	public String course() {
		return "course";
	}
}

查看文件

这些是显示在浏览器中的项目视图文件。查看代码。

//course.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Course Page</title>
</head>
<body>
	<h2>List of Courses</h2>
	<ul>
		<li>Java</li>
		<li>Python</li>
		<li>C++</li>
		<li>Linux</li>
	</ul>
</body>
</html>

//index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
	<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
	<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Home Page</title>
</head>
<body>
	<h2>Welcome to Studytonight!</h2>
	<h3>
		<a href="java-course">Study Java</a>
	</h3>
</body>
</html>

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>springwithsecurity</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
		<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>4.0.1</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/jstl/jstl -->
		<dependency>
			<groupId>jstl</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.3.3</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
		<dependency>
			<groupId>javax.servlet.jsp.jstl</groupId>
			<artifactId>jstl-api</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.3.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>5.4.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>5.4.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-taglibs -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-taglibs</artifactId>
			<version>5.4.1</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.3</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.5.1</version>
				<configuration>
					<source>11</source>
					<target>11</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

在加载页面时,它会要求用户提供凭据。它是一个自动生成的输入框,由 Spring Security 创建,用于在用户发出 HTTP 请求时验证用户。在此输入的凭据将被附加到请求头,并在服务器端进行验证。

提供正确的用户名和密码

主页

现在,您已成功登录到应用。这是我们的index.jsp文件渲染为浏览器的主页。



Spring Security 的 XML 配置

原文:https://www.studytonight.com/spring-framework/spring-security-configuration-using-xml

可以通过使用 XML 或 Java 注释来配置 Spring Security。我们已经在上一篇文章中看到了带有 Java 和注释的 Spring Security 配置。现在,我们将学习使用 XML 配置应用。如果您使用 java 或 XML,两者都很好,没有区别,但是在现代,使用基于 Java 的配置比使用 XML 更好。

让我们通过例子来理解。创建一个基于 maven 的 spring 应用,它将包含以下源文件。

项目源代码

//user controller . Java

这是我们的控制器类,它作为用户请求处理程序工作,将用户请求与资源进行映射,并相应地返回响应。我们创建了 home()方法来显示 index.jsp 页面,course()方法来显示 course.jsp 页面。

package com.studytonight.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class UserController {

	@GetMapping("/")  
	public String home() {
		return "index";
	}

	@GetMapping("/java-course")
	public String course() {
		return "course";
	}
}

//应用-上下文. xml

该文件用于配置视图页面、组件和控制器类。它类似于 Java 配置项目的 AppConfig.java 文件。

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

	<!-- Step 3: Add support for component scanning -->
	<context:component-scan base-package="com.studytonight.controller" />

	<!-- Step 4: Add support for conversion, formatting and validation support -->
	<mvc:annotation-driven/>

	<!-- Step 5: Define Spring MVC view resolver -->
	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/views/" />
		<property name="suffix" value=".jsp" />
	</bean>
</beans>

// spring-security.xml

该文件用于配置用户及其角色。在用户服务标签中,我们设置用户的登录凭证。这种配置类似于 Java 配置项目的 SecurityConfig.java 文件。

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

	<http>
		<intercept-url pattern="/" access="hasRole('GUEST')" />
		<intercept-url pattern="/java-courses/**" access="hasAnyRole('GUEST', 'REGISTERED')" />		
		<form-login 
		   login-processing-url="/login"
		   username-parameter="username"
		   password-parameter="password"
		   default-target-url="/"/>
	</http>
	<authentication-manager>
		<authentication-provider>
		    <user-service>
		        <user name="studytonight" password="{noop}abc123" authorities="ROLE_GUEST" />
		        <user name="pro-studytonight" password="{noop}abc123" authorities="ROLE_REGISTERED" />		        
		    </user-service>	
		</authentication-provider>
	</authentication-manager>

</b:beans>

// web.xml

它用于配置 web 应用。这里,我们设置 application-context.xml 和 spring-security.xml,以便应用可以在执行过程中找到它们。

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
  https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet
		</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/application-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener
		</listener-class>
	</listener>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			/WEB-INF/spring-security.xml
		</param-value>
	</context-param>
	<filter>
		<filter-name>springSecurityFilterChain</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy
		</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>springSecurityFilterChain</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener
		</listener-class>
	</listener>
</web-app>

查看文件

这些是显示在浏览器中的项目视图文件。查看代码。

//course.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Course Page</title>
</head>
<body>
	<h2>List of Courses</h2>
	<ul>
		<li>Java</li>
		<li>Python</li>
		<li>C++</li>
		<li>Linux</li>
	</ul>
</body>
</html>

//index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
	<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
	<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Home Page</title>
</head>
<body>
	<h2>Welcome to Studytonight!</h2>

	<h3>
		<a href="java-course">Study Java</a>
	</h3>
</body>
</html>

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>springwithsecurityXML</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
		<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>4.0.1</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/jstl/jstl -->
		<dependency>
			<groupId>jstl</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.3.3</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
		<dependency>
			<groupId>javax.servlet.jsp.jstl</groupId>
			<artifactId>jstl-api</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.3.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>5.4.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>5.4.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-taglibs -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-taglibs</artifactId>
			<version>5.4.1</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.3</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.5.1</version>
				<configuration>
					<source>11</source>
					<target>11</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

项目结构

创建这些文件后,我们的项目将如下所示。你可以参考这个来了解项目的目录结构。

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。它呈现一个登录页面来验证用户。

它会将用户名和密码与 spring-security.xml 文件中提供的凭据进行匹配。

提供正确的用户名和密码

主页

现在,您已成功登录到应用。这是我们的index.jsp文件渲染为浏览器的主页。

看,应用也可以很好地使用 XML 配置。因此,您可以为您的应用使用任何配置。



在 Spring Security 应用中创建自定义拒绝访问页面

原文:https://www.studytonight.com/spring-framework/create-custom-access-denied-page-in-spring-security-application

在 spring Security 应用中,当用户输入错误的登录凭据时,Spring 会向浏览器返回自动生成的消息“错误的凭据”,如果用户试图访问任何他无法访问的资源,那么 Spring 会返回一个异常,如访问被拒绝或 HTTP 状态 403 -禁止。这是 Spring Security 的内部错误处理机制。除了给用户提供一个更有意义或者有点花哨的信息,让用户理解错误之外,我们不能做更多的事情。

在这里,我们将向项目添加我们自己的自定义错误页面,这样当用户试图访问任何未授权的资源时,就会得到一条自定义错误消息。

举个例子

现在,让我们通过例子来理解。我们创建了一个基于 maven 的 Spring Security 项目,其中包含以下文件。

//app config . Java

这是我们的应用配置文件,它实现了WebMvcConfugurer接口来制作这个 MVC 应用,并创建了一个方法 viewResolver 来映射我们的视图文件(JSP)。

@EnableWebMvc 注释用于使我们的应用成为具有 Mvc 模式的 web 应用。

@Configuration 注释用于将这个类声明为一个配置类, @ComponentScan 注释用于扫描我们应用的组件类。

package com.studytonight;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@EnableWebMvc
@Configuration
@ComponentScan("com.studytonight.controller")
public class AppConfig implements WebMvcConfigurer{
	@Bean
	public ViewResolver viewResolver() {
		InternalResourceViewResolver irvr = new InternalResourceViewResolver();
		irvr.setPrefix("WEB-INF/views/");
		irvr.setSuffix(".jsp");
		irvr.setOrder(0);
		return irvr;
	}
}

//main app . Java

这个类初始化我们的网络应用,并通过注册我们的 AppConfig 类来创建ServletContext(上图文件)。

package com.studytonight;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
public class MainApp implements WebApplicationInitializer {

	@Override
	public void onStartup(ServletContext servletContext) throws ServletException {
		System.out.println("started");
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
		context.register(AppConfig.class);
		context.setServletContext(servletContext);
		ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
		servlet.setLoadOnStartup(1);
		servlet.addMapping("/");
		context.close();	
	}
}

//securityappnitizer . Java

这是扩展AbstractSecurityWebApplicationInitializer的安全初始化器类,我们传递了SecurityConfig类,这样它就可以读取安全配置。

package com.studytonight;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityAppInitializer  extends AbstractSecurityWebApplicationInitializer {

	public SecurityAppInitializer() {
		super(SecurityConfig.class);
	}
}

// SecurityConfig.java

这是我们的安全配置文件,扩展了WebSecurityConfigurerAdapter类,提供了configure()等几种方法来配置安全性。Spring Security 提供了作为认证管理器的AuthenticationManagerBuilder类,并提供了几种方法来验证用户。这里,我们使用inMemoryAuthentication概念,它允许映射硬编码的用户值。

我们使用roles()方法设置用户角色。在这里,我们设置了一个用户 GUEST 角色,另一个是 REGESTERED 角色。

我们使用HttpSecurity类来配置登录页面。loginPage()方法用于指定我们的login.jsp页面。我们还可以为登录表单使用任何其他名称,如 login-form.jsp 或 user-login.jsp,然后指定到该方法的映射。这里传递的"/登录"值将映射到控制器的动作,然后呈现 JSP 页面。

这里,我们使用accessDeniedPage()方法来配置我们的自定义错误处理页面。

package com.studytonight;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.User.UserBuilder;

@Configuration
@EnableWebSecurity	
public class SecurityConfig extends WebSecurityConfigurerAdapter{

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {

		UserBuilder users = User.withDefaultPasswordEncoder();		
		auth.inMemoryAuthentication()
		.withUser(users.username("studytonight").password("abc123").roles("GUEST"))
		.withUser(users.username("pro-studytonight").password("abc123").roles("REGISTERED"));
	}

	@Autowired
	protected void configure(HttpSecurity hs) throws Exception {
		hs.authorizeRequests()
		.antMatchers("/").hasAnyRole("GUEST","REGISTERED")
		.antMatchers("/java-course").hasRole("GUEST")
		.antMatchers("/premium-courses").hasRole("REGISTERED")
		.and()
		.formLogin()
		.loginPage("/login")
		.loginProcessingUrl("/authenticateTheUser")
		.permitAll()
		.and()
		.logout()
		.permitAll()
		.and()
		.exceptionHandling().accessDeniedPage("/unauthorized");
	}
}

//user controller . Java

这是我们的控制器类,它作为用户请求处理程序工作,将用户请求与资源进行映射,并相应地返回响应。我们创建了 login()方法来呈现登录页面,home()方法来显示index.jsp页面,当然()方法来显示course.jsp页面。

package com.studytonight.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class UserController {

	@GetMapping("/login")
	public String login() {
		return "login";
	}

	@GetMapping("/")  
	public String home() {
		return "index";
	}

	@GetMapping("/java-course")
	public String course() {
		return "course";
	}

	@GetMapping("/premium-courses")
	public String premiumCourse() {
		return "premium-courses";
	}

	@GetMapping("/unauthorized")
	public String unauthorized() {
		return "unauthorized-user";
	}
}

查看文件

这些是显示在浏览器中的项目视图文件。查看代码。

//course.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Course Page</title>
</head>
<body>
	<h2>List of Courses</h2>
	<ul>
		<li>Java</li>
		<li>Python</li>
		<li>C++</li>
		<li>Linux</li>
	</ul>
</body>
</html>

//index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
	<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
	<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Home Page</title>
</head>
<body>
	<h2>Welcome to Studytonight!</h2>
	<h3>
		<a href="java-course">Study Java</a>
	</h3>
	<h2>
		<a href="premium-courses">Study Premium Courses</a>
	</h2>
	<br><br>
	<form:form
		action="${pageContext.request.contextPath}/logout"
		method="post">
		<input type="submit" value="logout">
	</form:form>
</body>
</html>

//login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Login Page</title>
</head>
<body>
	<form:form
		action="${pageContext.request.contextPath}/authenticateTheUser"
		method="post">
		<c:if test="${param.error!=null}">
			<p style="color: red">You entered wrong credentials!</p>

		</c:if>
		<c:if test="${param.logout!=null}">
			<p style="color: green">You have successfully logged out.!</p>
		</c:if>
		<label for="name">Enter User Name</label>
		<input type="text" name="username">
		<br>
		<br>
		<label for="password">Enter Password</label>
		<input type="password" name="password">
		<br>
		<br>
		<input type="submit" value="Login">
	</form:form>
</body>
</html>

//premium-courses.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Course Page</title>
</head>
<body>
	<h2>List of Premium Courses</h2>
	<ul>
		<li>Spring Framework</li>
		<li>Pandas</li>
		<li>Spring Security</li>
	</ul>
</body>
</html>

//unauthorize-user.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Unauthorized Page</title>
</head>
<body>
<h2>Error: You are not Authorized to access this Page</h2>
</body>
</html>

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>springwithsecurity</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
		<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>4.0.1</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/jstl/jstl -->
		<dependency>
			<groupId>jstl</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.3.3</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
		<dependency>
			<groupId>javax.servlet.jsp.jstl</groupId>
			<artifactId>jstl-api</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.3.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>5.4.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>5.4.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-taglibs -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-taglibs</artifactId>
			<version>5.4.1</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.3</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.5.1</version>
				<configuration>
					<source>11</source>
					<target>11</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

项目结构

创建这些文件后,我们的项目将如下所示。你可以参考这个来了解项目的目录结构。

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

这是我们自己的登录页面,将提交至/authenticatheuserURL,并将用户名和密码与SecurityConfig.java文件中提供的凭据进行匹配。

提供正确的用户名和密码

主页

现在,您已成功登录到应用。这是我们的index.jsp文件渲染为浏览器的主页。

点击第一个链接“学习 Java”,下面的网页将会打开。

拒绝访问

如果用户访客用户试图访问高级课程,那么他会收到拒绝访问的消息。这是我们在配置文件中使用 accessDeniedPage() 方法创建和配置的页面。



Spring Security 中基于角色的访问控制

原文:https://www.studytonight.com/spring-framework/role-based-access-control-in-spring-security

在这篇关于 Spring Security 的文章中,我们将学习实现 RBAC(基于角色的访问控制)。RBAC 是一个主要用于企业应用的概念,其中多个用户正在访问资源,但资源受到限制。

假设一个应用包含几个模块,包括一个管理模块和一个用户模块,那么开发人员的职责就是只为管理用户提供一个管理模块。除管理员以外的任何用户都将被拒绝访问管理模块。

因此,为了实现它,我们需要指定用户规则和用户在安全配置类中配置用户时可以访问的资源。

Spring 提供roles()方法指定用户角色,hasRole()方法检查用户是否具有访问资源的角色。

让我们通过一个简单的例子来理解它。

举个例子

我们创建了一个基于 maven 的 Spring Security 项目,其中包含以下文件。

//app config . Java

这是我们的应用配置文件,它实现了WebMvcConfugurer接口来制作这个 MVC 应用,并创建了一个方法 viewResolver 来映射我们的视图文件(JSP)。

@EnableWebMvc 注释用于使我们的应用成为具有 Mvc 模式的 web 应用。

@Configuration 注释用于将这个类声明为一个配置类, @ComponentScan 注释用于扫描我们应用的组件类。

package com.studytonight;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@EnableWebMvc
@Configuration
@ComponentScan("com.studytonight.controller")
public class AppConfig implements WebMvcConfigurer{
	@Bean
	public ViewResolver viewResolver() {
		InternalResourceViewResolver irvr = new InternalResourceViewResolver();
		irvr.setPrefix("WEB-INF/views/");
		irvr.setSuffix(".jsp");
		irvr.setOrder(0);
		return irvr;
	}
}

//main app . Java

这个类初始化我们的网络应用,并通过注册我们的 AppConfig 类来创建ServletContext(上图文件)。

package com.studytonight;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
public class MainApp implements WebApplicationInitializer {

	@Override
	public void onStartup(ServletContext servletContext) throws ServletException {
		System.out.println("started");
		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
		context.register(AppConfig.class);
		context.setServletContext(servletContext);
		ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
		servlet.setLoadOnStartup(1);
		servlet.addMapping("/");
		context.close();	
	}
}

//securityappnitizer . Java

这是扩展AbstractSecurityWebApplicationInitializer的安全初始化器类,我们传递了SecurityConfig类,这样它就可以读取安全配置。

package com.studytonight;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityAppInitializer  extends AbstractSecurityWebApplicationInitializer {

	public SecurityAppInitializer() {
		super(SecurityConfig.class);
	}
}

// SecurityConfig.java

这是我们的安全配置文件,扩展了WebSecurityConfigurerAdapter类,提供了configure()等几种方法来配置安全性。Spring Security 提供了作为认证管理器的AuthenticationManagerBuilder类,并提供了几种方法来验证用户。这里,我们使用inMemoryAuthentication概念,它允许映射硬编码的用户值。

借助 roles()方法,我们使用AuthenticationManagerBuilder类来设置用户角色,通过使用HttpSecurity类,我们指定了资源及其可访问性,因此只有授权用户才能访问资源。

package com.studytonight;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.User.UserBuilder;

@Configuration
@EnableWebSecurity	
public class SecurityConfig extends WebSecurityConfigurerAdapter{

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {

		UserBuilder users = User.withDefaultPasswordEncoder();		
		auth.inMemoryAuthentication()
		.withUser(users.username("studytonight").password("abc123").roles("GUEST"))
		.withUser(users.username("pro-studytonight").password("abc123").roles("REGISTERED"));
	}

	@Autowired
	protected void configure(HttpSecurity hs) throws Exception {
		hs.authorizeRequests()
		.antMatchers("/").hasAnyRole("GUEST","REGISTERED")
		.antMatchers("/java-course").hasRole("GUEST")
		.antMatchers("/premium-courses").hasRole("REGISTERED")
		.and()
		.formLogin()
		.loginPage("/login")
		.loginProcessingUrl("/authenticateTheUser")
		.permitAll()
		.and()
		.logout()
		.permitAll();
	}
}

//user controller . Java

这是我们的控制器类,它作为用户请求处理程序工作,将用户请求与资源进行映射,并相应地返回响应。我们创建了 login()方法来呈现登录页面,home()方法来显示index.jsp页面,当然()方法来显示course.jsp页面。

package com.studytonight.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class UserController {

	@GetMapping("/login")
	public String login() {
		return "login";
	}

	@GetMapping("/")  
	public String home() {
		return "index";
	}

	@GetMapping("/java-course")
	public String course() {
		return "course";
	}

	@GetMapping("/premium-courses")
	public String premiumCourse() {
		return "premium-courses";
	}
}

查看文件

这些是显示在浏览器中的项目视图文件。查看代码。

//course.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Course Page</title>
</head>
<body>
	<h2>List of Courses</h2>
	<ul>
		<li>Java</li>
		<li>Python</li>
		<li>C++</li>
		<li>Linux</li>
	</ul>
</body>
</html>

//index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
	<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
	<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Home Page</title>
</head>
<body>
	<h2>Welcome to Studytonight!</h2>
	<h3>
		<a href="java-course">Study Java</a>
	</h3>
	<h2>
		<a href="premium-courses">Study Premium Courses</a>
	</h2>
	<br><br>
	<form:form
		action="${pageContext.request.contextPath}/logout"
		method="post">
		<input type="submit" value="logout">
	</form:form>
</body>
</html>

//login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Login Page</title>
</head>
<body>
	<form:form
		action="${pageContext.request.contextPath}/authenticateTheUser"
		method="post">
		<c:if test="${param.error!=null}">
			<p style="color: red">You entered wrong credentials!</p>

		</c:if>
		<c:if test="${param.logout!=null}">
			<p style="color: green">You have successfully logged out.!</p>
		</c:if>
		<label for="name">Enter User Name</label>
		<input type="text" name="username">
		<br>
		<br>
		<label for="password">Enter Password</label>
		<input type="password" name="password">
		<br>
		<br>
		<input type="submit" value="Login">
	</form:form>
</body>
</html>

//premium-course.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Course Page</title>
</head>
<body>
	<h2>List of Premium Courses</h2>
	<ul>
		<li>Spring Framework</li>
		<li>Pandas</li>
		<li>Spring Security</li>
	</ul>
</body>
</html>

//POM . XML

这个文件包含这个项目的所有依赖项,比如 spring jars、servlet jars 等。将这些依赖项放入项目中以运行应用。

<project 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.studytonight</groupId>
	<artifactId>springwithsecurity</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<properties>
		<spring.version>5.2.8.RELEASE</spring.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
		<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>4.0.1</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/jstl/jstl -->
		<dependency>
			<groupId>jstl</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.3.3</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
		<dependency>
			<groupId>javax.servlet.jsp.jstl</groupId>
			<artifactId>jstl-api</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.3.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>5.4.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>5.4.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-taglibs -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-taglibs</artifactId>
			<version>5.4.1</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.3</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.5.1</version>
				<configuration>
					<source>11</source>
					<target>11</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

项目结构

创建这些文件后,我们的项目将如下所示。你可以参考这个来了解项目的目录结构。

运行应用

成功完成项目并添加依赖项后,运行应用,您将获得如下输出。

这是我们自己的登录页面,将提交至/authenticatheuserURL,并将用户名和密码与SecurityConfig.java文件中提供的凭据进行匹配。

提供正确的用户名和密码

主页

现在,我们已成功登录到应用。这是我们的index.jsp文件渲染为浏览器的主页。

由于用户是客人,并且具有客人用户的角色,因此可以访问非高级课程。

由于用户是客人,并且具有客人用户的角色,因此只能访问第一个课程链接。如果用户点击高级课程,就会出现一个被禁止的错误,这意味着他无权访问这些资源。

您也可以尝试用另一个用户登录,看看您是否能够看到 java 课程列表。



Spring Security 标签库

原文:https://www.studytonight.com/spring-framework/spring-security-tag-library

在本文中,我们将讨论内置标签库。Spring Security 提供了一个内置的标签库,其中包含几个用于管理 JSP 页面内容的标签,并有助于访问安全信息和在 JSP 页面上应用安全约束。例如,如果我们想向普通用户显示 JSP 的一部分,向管理员用户显示其他部分,那么这个库会有更大的帮助。

要将这个库添加到我们的项目中,我们需要遵循以下步骤

  • 添加依赖项

  • 声明标签库

  • 使用标签

添加依赖项

我们应该将这些依赖项添加到 spring 安全项目的 pom.xml 文件中。这是一个 maven 项目,你也可以从官方 maven 网站获得最新消息。

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-taglibs</artifactId>
    <version>5.4.1</version>
</dependency> 

声明标记库

添加了上面的依赖项后,我们必须将它包含在 JSP 页面的顶部。它将提供该页面上的所有标签。它类似于 Java 中的 import 语句,可以访问导入包的所有类。

<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>

验证项目中是否存在依赖关系

pom.xml 文件中添加依赖项后,首先更新您的项目,然后您可以验证所有标签库 JARs 在库- > maven 文件夹中可用。

在 JSP 页面中使用标签

在 JSP 页面的顶部声明标记库之后,我们可以使用它的标记。它提供了几个标签,例如

  • 授权标签

  • 认证标签

  • Accesscontrollist 标记

  • 输入标签

  • 标签

授权标签

Spring 使用这个标签来检查是否应该根据用户授权显示内容。例如,管理员用户只能看到包含在具有管理员角色的授权标签中的内容。非管理员用户将看不到此内容部分。它使用各种属性,例如:

授权标签属性

| 属性名称 | 描述 |
| 全球资源定位器(Uniform Resource Locator) | 它用于指定在用户被授予访问此 URL 的权限时呈现给用户的 URL。 |
| 方法 | 它用于指定获取或发布的 HTTP 方法 |
| 定义变量 | 它用于声明页面范围变量。 |
| 接近 | 它用于设置访问权限 |

授权标签示例

我们可以像在这里一样,在 JSP 页面的任何地方使用这个标签。

<security:authorize access="hasRole('admin')">
    <p>This content section is visible only for ADMIN</p>
</sec:authorize>

认证标签

我们可以使用这个标签来访问存储在安全上下文中的当前认证对象。它有助于获取 JSP 文件中对象的属性。例如,如果我们有一个学生对象,并想得到它的属性,如用户名,那么我们使用它作为

<security:authentication property="principal.username" />

它将呈现当前学生的用户名。

访问控制列表标签

此标记用于检查以逗号分隔的所需权限列表。如果用户拥有此标签中列出的所有这些权限,则标签主体将被评估,否则将跳过执行。只有当 Spring Security 的 ACL ( A 访问 C 控制 L ist)模块被激活时,我们才能使用此标签。该标签具有以下属性。

| 属性名称 | 描述 |
| hasPermission | 它用于指定要针对域对象检查的权限列表。 |
| domainObject | 它用于指定要检查权限的对象。 |
| 定义变量 | 它用于声明页面范围变量。 |

男主角

该标签用于插入一个隐藏的表单字段,该字段保存 CSRF 保护令牌。它对浏览器不可见,但包含令牌。虽然如果我们像

一样使用 spring 的表单标签库,那么我们不需要添加这个,如果我们使用普通的 HTML 表单,那么我们需要把这个放到我们的表单中。

如果启用了 CSRF 保护,则该标记会插入令牌,否则该标记不会执行任何操作。

输入标签示例

<form action="${pageContext.request.contextPath}/authenticateTheUser" method="post">
    <sec:csrfInput />
    <input type="text" name="username" />
    ...
</form>

csrfmetatags 标记

如果启用了 CSRF 保护,此标签将插入包含 CSRF 保护令牌表单字段和标头名称以及 CSRF 保护令牌值的元标签。这些元标签对于在应用中使用 JavaScript 中的 CSRF 保护非常有用。

我们应该将这个标签放入 HTML 头部标签中。使用 JavaScript 可以很容易地获得表单字段名、标题名和标记值。请看下面的例子。

标签示例

<security:csrfMetaTags />
<script type="text/javascript" language="javascript">
    var csrfParameter = $("meta[name='_csrf_parameter']").attr("content");
    var csrfHeader = $("meta[name='_csrf_header']").attr("content");
    var csrfToken = $("meta[name='_csrf']").attr("content");
</script>

比如可以参考我们已有的文章: 第 1 条第 2 条



Spring Boot

Spring Boot 基础

Spring Boot 简介

原文:https://www.studytonight.com/spring-boot/introduction-to-spring-boot

应用开发非常重要,因为它有助于我们的日常工作。例如,支持在线订购的食品订购应用必须使用前端用户界面、后端(服务器端编程)和数据库来保存数据。自 90 年代中期以来,Java 一直是许多程序员设计软件的流行选择,因此,许多框架的开发都是为了使用 Java 来简化软件开发。

为了使开发变得简单有效,引入了几个框架,如 StrutsSpring 和 ORM 工具,如 HibernateToplink 等。用于数据库操作。

近年来,Spring 有了很大的发展,出现了许多新模块,如Spring 靴Spring SecuritySpring 云等。在这一系列教程中,我们将学习 spring-boot 框架及其提供的各种特性,使其成为应用开发的流行选择。Spring 靴由 PIVOTAL 团队开发。

先决条件:

  • java 编程知识。
  • 动手 REST 网络服务
  • 依赖管理工具,如 Maven 或 Gradle,将是一个额外的优势。

Spring Boot 的优势:

  1. SpringBoot 的主要优势是为项目启用自动配置。这减轻了程序员的负担,节省了大量时间。

  2. 它使使用非常简单的注释,并取代了 spring MVC 中典型的基于 XML 的配置设置。

  3. 提供一个嵌入式 servlet 容器,并帮助轻松引导(快速运行)准备好生产的应用。

  4. 它支持为 spring 应用创建胖 Jar,其中包含所有的依赖项,因此您可以直接运行它。

  5. 微服务架构可以通过 spring-boot 框架有效地构建,它还为依赖关系管理提供了 spring-boot-starter 等概念。

类路径依赖关系:

建立一个项目需要大量的外部库(核心 Java 和其他相关框架)。如前所述,spring-boot 支持自动配置,这取决于类路径中可用的 jar。我们将在开始设置项目时查看自动配置。

spring-boot-starter 有助于有效地管理所有依赖关系,不像 spring-MVC 那样没有 starter 的概念。

什么是 SpringBoot 装置?

Starters 为基于 spring 的项目提供了有效的依赖管理。例如,如果我们想使用 hibernate 作为 ORM 工具,我们需要 hibernate maven 脚本(要包含在项目的 pom.xml 文件中),如下所示。

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>5.4.2.Final</version>
</dependency>

Spring-boot 提供了诸如spring-boot-starter-data-JPA这样的启动器,当包含在 maven 项目中时,它提供了上面提到的 hibernate 依赖关系以及 spring-data-jpa 依赖关系

简而言之,启动器是多个依赖项的组合,通过在您的 pom.xml (适用于 maven 项目)或 ivy.xml (适用于 IVY/ANT 项目)或 build.gradle 文件(适用于 gradle 项目)中指定它们的名称,可以轻松解决并减少手动包含每个依赖项的任务。一些例子是:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>

请注意,与上面的代码不同,上面的启动脚本没有提到版本,因为版本是从spring-boot-starter-parent导入的,这将在后面进一步讨论。

什么是应用属性?

这个文件帮助我们使用简单的属性来管理应用的配置。根据所提供的配置,spring-boot 会自动配置一些 beans(由 spring 直接管理并在应用启动时初始化的对象)。

它还有助于启用用户提供的其他配置。比如嵌入式 tomcat 的默认端口为 8080 ,可以通过应用.属性文件中提到的 server.port 属性进行更改。下面的属性在端口 9000 上运行 tomcat。

server.port=9000

以上属性文件可以替换为 yml 文件(application.yml) 。Spring-boot 使我们能够为不同的环境维护多个属性文件。我们可以在应用启动时选择所需的配置。当我们开始开发应用时,我们将详细讨论这个主题。

结论:在本教程中,我们了解了 spring-boot,并看到了它的重要性以及它为更容易开发提供的优势。



安装 Spring Boot 和其他软件

原文:https://www.studytonight.com/spring-boot/installing-spring-boot-and-other-software

我们将使用 spring-boot 框架开发一个 web 应用,它需要一些软件来开始开发。我们希望您在获得其他软件之前先拥有 Java 环境设置。它使用依赖管理技术,例如 maven,当与 Eclipse 等集成开发环境一起使用时,这非常容易。

在接下来的教程中,我们将使用 Java 8Maven(依赖管理)、Eclipse IDE 作为开发示例。

Maven 安装:

虽然我们使用 Eclipse IDE 中的 maven,但是当项目作为 JAR 文件导出以从 CMD(命令行提示符)运行时,我们可能需要安装。

  1. 下载 Maven ZIP 文件后,将其解压缩到驱动器上的某个文件夹,然后切换到 bin 目录。

  2. 点击mvn -v命令,切换到 maven 安装文件夹内的 bin 目录后查看版本。installing maven for spring boot

  3. 上图分别显示了 maven 和 java 版本。建议将 maven bin 文件夹的环境路径设置为与 java 环境设置相同。

Spring Boot 国家牵头倡议:

作为生产就绪的基于 spring 的应用的一个快速示例,让我们看看 Spring-boot CLI(命令行界面)。我们需要下载 spring-boot CLI。提取 ZIP 文件后,从命令行切换到 bin 目录,输入命令spring --version.

installing spring boot CLI

上图显示了 spring-boot CLI 的版本,在切换到 spring-boot CLI 的 bin 目录后一定要检查版本。现在,让我们在 bin 目录中创建一个文件study now . groovy。将下面的代码放入 groovy 文件并保存。

@RestController
class StudyTonight
{
  @RequestMapping(value="/study-tonight",method=RequestMethod.GET)
  public String displayWelcomeMessage()
  {
  return "Welcome to spring-boot tutorials!!";
  }
}

在 CMD 中,在 bin 目录路径下,运行命令spring run study south . groovy,该命令在端口 8080 上的嵌入式 tomcat 上运行应用。

running spring boot application

在上图中,我们收到了 spring-boot 自动配置的嵌入式 tomcat 的响应。需要注意的重要一点是,即使我们没有在 groovy 文件中包含任何导入语句,但是 Spring-Boot CLI 已经为我们解决了依赖关系。

REST 客户端安装:

为了测试 RESTful 网络服务,我们需要一个 REST 客户端,用于发送请求和接收响应。这样的 REST 客户之一是邮递员。由于使用它的简单方便的方法,它变得非常重要。

对于 GET 请求,只需在浏览器中输入网址就可以访问应用编程接口。对于 POST 请求,需要使用一些 REST CLIENT,因为不可能通过在浏览器中粘贴 URL 来命中 API。

  • 下载并启动邮差后,可以看到类似下图 2.4 的 UI。

Postman setup for spring boot app

结论:在本教程中,我们已经看到了使用 spring-boot 进行 web 应用开发所需软件的安装。除了创建 web 应用,我们还将创建简单的控制台应用。在下一个教程中,我们将设置项目并将其导入到 Eclipse IDE 中。



使用 Spring Boot 创建网络应用的设置

原文:https://www.studytonight.com/spring-boot/setup-for-creating-a-web-application-with-spring-boot

我们已经看到了 spring-boot 的重要性以及它在开发中提供的灵活配置。在本教程中,我们将使用Spring 初始化器设置项目(它为我们生成项目设置)。

使用 Spring 初始化工具

它有助于快速设置可以轻松引导(快速运行)的 spring-boot 应用。这里可以找到这个: start.spring.io

using spring boot intializer tool

上面的快照是 PIVOTAL 团队托管的 spring initializer 的典型布局。生成我们选择的项目,需要输入组、神器等细节(可以在上面的快照中看到),组合在一起得到包名。编写本教程时的当前版本是 2.1.7 (2.1.7 仍然是最稳定的版本,但您也可以选择 2.2.5 或以上版本)。对于我们的 web 应用,我们选择了依赖管理工具作为 MAVEN ,语言作为 Java

using spring boot intializer tool

我们需要从依赖项部分选择项目所需的依赖项,如上图所示。我们可以从显示给我们的搜索建议中进行选择。对于这个项目,我们选择了以下依赖项列表。

  1. Spring 网起动器

  2. spring-data-jpa

  3. 春海棠(消歧义)

  4. h2 数据库(内存数据库)

当进一步需要时,我们可以添加更多的依赖项。选择所有内容后,点击生成项目按钮,下载一个包含项目的 ZIP 文件。

导入项目:

ZIP 文件需要解压到某个文件夹,然后我们将它作为一个 maven 项目导入到您的 Eclipse IDE 中。如果您是第一次导入 maven 项目,可能需要一些时间来解决依赖关系。

using spring boot intializer tool

上图显示了 spring initializer 为我们生成的典型 maven 项目结构。它被解压并作为 Maven 项目导入到 eclipse 中。

在上图中, src/main/java 是所有 java 源代码的去向路径。观察我们在 spring initializer 中输入的包名,它是 groupid 和 artifact 的组合。包 src/main/resourcesapplication.properties 文件和 src/test/java 包含我们需要运行单元测试用例的类。

pom.xml 文件是包含依赖脚本的地方,我们在使用 spring initializer 工具创建项目时选择了这个文件。

将项目导入 Eclipse 的步骤:

在 eclipse 中点击文件选项(左上角)下的导入选项后,我们必须导入,如下所示。请注意图 3.4、3.5、3.6 中的进一步步骤。

文件= >导入= > Maven = >现有 Maven 项目

import maven project to Eclipse

import maven project to Eclipse

import maven project to Eclipse

图 3.7 显示了从 spring initializer 解压 ZIP 文件后,文件系统中的项目。

粘贴需要导入的项目的根目录路径(如上图 pom.xml 所在的目录),继续点击向导上的下一步选项(如图 3.6 所示)。

Pom.xml:

它负责向项目添加依赖项。例如,如果我们检查 project 下的 maven dependencies 部分,我们可以看到 hibernate 相关的 jar,它们是因为 spring 初始化器中的 spring-data-jpa 依赖关系而添加的。

Spring-boot 继承了名为spring-boot-starter-parent的父项目的大部分配置,在 spring-boot 中启用了自动配置功能。它还取决于类路径中可用的 JARs。所有项目元数据都可以在 pom.xml 文件中找到。

结论:在本教程中,我们从 spring initializer 创建了一个 spring-boot maven 项目,并将其导入到 eclipse IDE 中。我们还讨论了项目组件和依赖关系管理。



Spring Boot 自动配置和项目结构

原文:https://www.studytonight.com/spring-boot/spring-boot-autoconfiguration-and-project-structure

在本教程中,我们将详细了解自动配置和 web 项目的结构。有必要遵循编码约定,例如使用命名包而不是默认包。spring-boot 将扫描这些包,以识别项目中定义的 beans 和实体。下面是目录结构以及我们将要创建的 Java 类文件。

根包的重要性

  • 为了启动应用,我们将使用 main 方法运行类(通常放在根包中),并用@SpringBootApplication进行注释。

  • @SpringBootApplication注释负责引导应用。

  • 如果我们对比一下上面的项目结构,Application.java是用@SpringBootApplication注解的文件,在包com . study south . tutory(根包)中。

  • 学生老师这样的实体会被 Spring 开机扫描,因为它们的包在根包里面,如下所示。

    • Application.java(网上教程今晚学习

    • Student.java(com . tutorial . study south . POJO)

    • Teacher.java(com . tutorial . study south . POJO)

我们可以观察到今晚在Student.javaTeacher.java班很常见。任何放置在根包下的组件都会被 spring-boot 自动扫描。

什么是自动配置?

它在扫描类路径后启用。@EnableAutoConfiguration等注解负责自动配置。例如,当项目具有诸如spring-boot-starter-data-JPA之类的依赖项时,spring-boot 期望用户名、密码、url 之类的数据库详细信息,如果没有这些信息,应用将无法启动,因为 spring-boot 会扫描类路径中的spring-boot-starter-data-JPA依赖项,并假设项目将使用数据库。请记住,我们已经在项目设置中添加了 H2 依赖项(spring boot 会自动配置 H2 的数据库属性)。

在某些情况下,为了测试应用,我们更喜欢在最终部署到生产中之前使用内存数据库和关系数据库。

豆子是什么?

  1. 这些对象构成了 spring 应用的主干。有些 beans 是 spring 自己在启动时根据自动配置创建的。

  2. 程序员也可以使用注释@Bean定义他/她自己的 beans,这将在后面讨论。

  3. 需要时,这些 beans 可以用于自动装配。自动连接只不过是将 beans 注入到其他 java 类文件中,这是 spring 自己完成的。

例如,每个学生都与一个老师相关联,在下面的班级中,我们在班级学生中实例化班级老师,这是紧耦合的一个例子。

class Teacher {

   private String name;
   private String subject;

   //setter and获取器methods

}

class Student {

   private String name;
   private int age;
   private Teacher teacher = new Teacher();

   //setter and获取器methods

}

要自动连接教师 bean ,我们需要创建一个教师类的 bean(将由 spring 管理)。

@Configuration
class BeanList{

    @Bean
    public Teacher teacherBean(){
         Teacher teacher = new Teacher();
         return teacher;
    }
}

上面的类用@Configuration注解,这样 spring boot 就会在类内查找任何配置。创建的 bean 将由 spring 管理,当学生类中需要自动连接时,它将被注入。

class Student {

    private String name;
    private int age;

    @Autowired
    private Teacher teacher;   //Instance will be autowired by spring

}

条件自动配置:

在某些情况下,我们可以通过使用注释来限制自动配置。让我们假设,我们需要创建一个学生的 bean,但是我们需要首先创建教师类的 bean,因此,如果教师 bean 可用,则创建学生 bean。让我们使用注释来实现这一点。

@Bean
@ConditionalOnBean(Teacher.class)
public Student studentBean() {
    Student student = new Student();
    return student;
}

只有当教师程序可用时,上面的代码片段才会创建学生豆。同样,当缺少一个 bean 时,可以使用@ConditionalOnMissingBean来创建一个 bean。

结论:在本教程中,我们已经看到了 spring-boot 中可用的项目布局和自动配置功能。



启动 Spring Boot 应用

原文:https://www.studytonight.com/spring-boot/launching-spring-boot-application

在本教程中,我们将讨论可用的 spring boot 注释以及如何启动 spring boot 应用。常见 Spring 靴注释:

  • @回弹应用:是应用启动的入口点,通常在类中用 main 方法注解。

  • @ components scan:扫描所有可用的@Component或其专业(@Service@Repository等。)在包和子包中。

  • @EnableAutoConfiguration :它通过扫描类路径中可用的 JARs 来启用自动配置。

  • @配置:将类中可用的 beans 注册到 Spring 应用上下文中。

Spring ApplicationContext 负责管理应用中创建的所有 beans。在下面的例子中,我们将显示应用中注册的所有 beans。

以上三个注解都可以用@SpringBootApplication代替。

SpringApplication 类提供了一个静态方法run(class <T>,String[]),返回 ApplicationContext 的引用。它管理所有的 beans,可以显示如下:

package com.tutorial.studytonight;

public class Application {
    static ApplicationContext context;
    public static void main(String a[]) {
        context  =SpringApplication.run(Application.class,a);
        String beans[] = context.getBeanDefinitionNames();
        for(String bean : beans)
            System.out.println(bean);
    }
}

在上图中,我们可以观察到创建的 beans 与自动配置相关。上面的截图突出显示了在项目设置过程中选择的与 H2、hateoas 依赖项相关的 beans。

从项目生成版本:

让我们从文件系统运行 JAR 文件。JAR 文件将被放在目标文件夹下,它需要被复制到您系统上的某个文件夹中。让我们为测试和生产环境创建两个概要文件。

1.创建一个名为application-test . properties的文件,并将下面的属性放置并保存该文件。

server.port=9000

2.创建另一个名为应用-产品属性的文件,并将下面的属性放置并保存该文件。

server.port=8000

我们可以在启动应用时选择所需的属性。在此之前,让我们了解一下马文。要获得项目的构建(以 JAR 或 WAR 格式),我们需要运行命令mvn install,然而在 IDE 中我们有一个选项。以上两个文件都是在 src/main/resources 下创建的。

3。然后右击项目,点击运行为,然后点击 Maven 安装。

在上图中,我们看到构建成功,并且生成了 JAR 文件。它位于项目的目标文件夹下。

运行构建并选择配置:

我们将遵循一些步骤来运行上面从文件系统生成的 JAR,它们是:

1。将上面生成的 JAR 从目标文件夹复制到任意文件夹,并在该文件夹中打开CMD

2。在 CMD java -jar studytonight-0.0.1-SNAPSHOT.jar中运行以下命令

Running the build and choosing the configuration for spring boot app

上图显示应用已启动,默认情况下,使用应用.属性

3。我们还有两个配置文件,分别是测试和生产环境。为了选择特定的配置文件,我们需要提供将要应用的程序参数。记住班级Spring 应用中的静态方法run(class<T>, String [])

SpringApplication.run(Class<T>,String[])

4。其中一个参数是String[],不过是主方法的程序参数。主方法中的 String[]参数可以访问程序参数。

public static void main(String[] args)

5。应该将相同的引用传递给 SpringApplication 中的静态运行方法,因此,这就是在应用启动时如何使用程序参数来选择配置。

6。 Spring 提供了一个命令 spring.profiles.active,作为程序参数传递。

Running the build and choosing the configuration for spring boot app

7。上面的命令是用 spring.profiles.active 运行的,在这里选择了测试环境配置文件配置,并且为服务器运行设置的属性是 9000,如下图所示

Running the build and choosing the configuration for spring boot app

8。同样,运行以下命令来应用生产环境属性

Running the build and choosing the configuration for spring boot app

Running the build and choosing the configuration for spring boot app

Uing Application.yml 文件:

代替属性文件,我们也可以使用 YML 文件来指定属性。例如,在 src/main/resources 下创建一个文件 application.yml ,并添加以下属性,因为它在文件中具有相同的缩进。

spring:
profiles:
active : test
server:
port : 2000
---
spring:
profiles:
active : linux
server:
port : 1000

现在,在构建另一个构建后运行 JAR 时指定 Linux 配置文件。

Running the build and choosing the configuration for spring boot app

上面的命令在端口 1000 上运行应用,如 application.yml 中所述。

Running the build and choosing the configuration for spring boot app

结论:在本教程中,我们已经看到了重要的 spring-boot 注释、application.properties 的概要文件选择、application.yml 的用法以及从 CMD 启动的应用。重要的一点是,我们没有像不同配置文件的 application.properties 那样为 application.yml 使用多个文件。



Spring Boot 进阶

Spring Boot UberJAR

原文:https://www.studytonight.com/spring-boot/spring-boot-uber-fat-jar

在本教程中,我们将讨论 Spring 靴项目的UberJAR 创建。UberJAR 是一个 JAR,其中所有应用的编译代码和依赖项被组合在一起,这样,如果程序员需要将它部署到某个地方,他可能会发现很容易,因为依赖项是和 JAR 一起出现的。UberJAR就是也叫就是肥 JAR。让我们研究一下生成 UberJAR 的技术。

为我们的项目创建 UberJAR:

为 spring boot 项目生成一个 UberJAR 非常简单,因为你所要做的就是为 maven 添加一个插件。默认情况下,spring-boot 的最新版本已经包含了这个插件,但是如果在 pom.xml 下找不到它,那么复制下面的脚本并将其包含在您的 pom.xml 文件中。

<project>
    <!-- This is used to define a comment in XML file -->
    <!--  Other maven script like dependencies section -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

令我们惊讶的是,我们已经自动生成了 UberJAR(如果插件是默认包含的话)。观察下面的截图。

UberJAR 是一个 JAR,其中所有的应用代码和依赖项(依赖的 JAR 文件)被组合在一起。作为一个更实用的视图,我们在我们的文件系统上使用 WinRAR 等软件提取了 JAR 文件,请看下面的截图。

上图有一个文件夹 org ,这里所有 spring 框架相关的依赖都是可用的,上图是 UberJAR 的提取。在 UberJAR 里,在元信息文件夹里,我们有清单。MF 文件保存项目的基本元信息, BOOT-INF 文件夹保存带有@SpringBootApplication注释的类的信息,该注释是执行开始的类。

结论:在本教程中,我们已经看到了 UberJAR(又名 Fat JAR)的重要性以及如何在 Spring 开机时生成它。



在 tomcat servlet 容器上运行 SpringBoot 应用

原文:https://www.studytonight.com/spring-boot/running-springboot-application-on-tomcat-servlet-container

在本教程中,我们将在 tomcat servlet 容器上部署 SpringBoot 应用。

部署程序

我们需要在 pom.xml 文件中添加一个属性,将项目打包为 WAR 。生成的 WAR 将部署在 tomcat 中。

观察上面 pom.xml 文件中<packaging>war</packaging>的属性,该属性允许我们在目标文件夹下生成 WAR 文件。Application.java 需要扩展类SpringBootServletInitializer
右键点击项目,点击运行为,然后 Maven 安装即可在 WAR 中获取项目构建。

在上面的图中我们可以看到,WAR 生成了并将部署在 tomcat 安装的 webapps 文件夹下。如前所述,Spring 应用 beans 通常由 ApplicationContext管理,但是为了在 Tomcat 中部署 spring 应用时初始化 ServletContext ,需要扩展SpringBootServletInitializer.

@SpringBootApplication
public class Application extends SpringBootServletInitializer{

        //main method body

}

如果机器上没有安装 tomcat,从https://tomcat.apache.org/download-80.cgi下载。解压缩 zip 文件夹后,安装目录将如下所示

将 WAR(在目标文件夹中生成)放置在 web 应用中(注意上面的图 7.3)。现在导航到 bin 文件夹并打开 cmd。为了启动 Tomcat,必须确保环境变量设置正确,我们在前面的教程中讨论过这一点。

环境变量是根据 JAVA 的安装路径设置的。在 Tomcat 安装的 web 应用目录中部署 WAR 文件。运行以下命令启动服务器。Tomcat 将在单独提示后启动,如图 7.6 所示。



我们可以使用 postman 如下测试部署在 tomcat 上的应用。

在上图中,请注意在 tomcat 中部署了具有 WAR 名称的 URL,并且返回的状态是 200 OK。这是 tomcat 中 WAR 部署的整个过程。到目前为止,我们一直在使用嵌入式 tomcat 从 IDE 启动应用。让我们再次回顾一下集成开发环境中的应用启动,因为它与这个主题相关。

右键单击项目 - > 运行方式 - > Java 应用

上图显示了应用控制台,并且是从 IDE 启动的。

结论:在本教程中,我们讨论了将 spring-boot 应用 WAR 部署到 servlet 容器,以及从 IDE 启动。



使用 Spring Boot 创建 REST 应用

原文:https://www.studytonight.com/spring-boot/creating-a-rest-application-with-spring-boot

在本教程中,我们将开发一个 Rest 网络服务,并测试 Rest 客户端的应用编程接口。

什么是 REST API?

  • REST 代表表征状态转移,这是一种有效利用 http 协议的架构风格。

  • 数据传输主要以两种格式进行( JSON / XML )。

  • JSON ( Javascript 对象符号)遵循键:值对的模式,而 XML ( 可扩展标记语言)遵循根和分支(标签)模式。

  • 每个应用都处理数据,它可能是用户配置文件、用户订单、产品信息(对于电子商务应用)等。因此,有一个需要有效处理的数据仓库。

  • 应用需要一些可以处理的输入来生成输出。输出需要返回给请求数据的客户端。

  • 网络服务只不过是通过网络提供的服务。REST 有助于构建称为 RESTful 网络服务的网络服务。下图分别显示了 JSON 和 XML 结构。

  • REST API 文档可以由 Swagger 生成,这将在接下来的教程中讨论。

REST 应用编程接口的开发:

将使用注释@RestController扫描所有 REST 端点。

需要用端点能够处理的请求类型(GET、POST、DELETE 等)来标记您的端点。

让我们创建一些名为学生老师的 POJOs,如下所示。这两个班级都被放在“T4”网站.教程.今晚学习. pojo 包下

Student.javaT3】

public class Student{
    private int id;
    private String name;
    private String institute;
    private LocalDate birthdate;
    private String city;

    //Setters and Getters
}

Teacher.javaT3】

public class Teacher{
    private int id;
    private String name;
    private String subject;
    private String institute;
    private String city;

    //Setters and Getters
}

上面的类是创建的 POJOs,我们需要一个 RestController 类来扫描可用的 REST 端点。在 POJOs 中,设置器和获取器可以在右击 Java 文件后从 IDE 自动生成。(如图 8.1 所示)。

让我们创建资源控制器类,它将有@RestController注释,

@RestController
public class ResourceController{

    @Autowired
    ResourceService resourceService;

    @PostMapping("/saveTeacher")
    public void saveTeacher(@RequestBody Teacher  teacher){
        resourceService.saveTeacher(teacher);
    }

    @GetMapping("/getTeacherDetails/{id}")
    public Teacher getTeacherDetails(@PathVariable("id") int id){
        return resourceService.getTeacherDetails(id);
    }
} 

上面的类是用@RestController注释的 ResourceController,用来扫描 REST 端点。

通常在开发中,我们遵循分层架构,其中我们有用于定义端点的 RestController、所有操作发生的服务层和存储数据的存储库层。

让我们创建一个服务层(T2】业务逻辑所在的地方)和一个存储库层(用于数据库事务)。在本例中,我们不使用任何数据库来存储值,我们将在即将到来的教程中使用内存数据库(H2)。

我们将把值存储在一个哈希表中,并使用一个获取请求从其中检索,而不是数据库。

@Service
public class ResourceService{

    @Autowired
    ResourceRepository repository;

    public void saveTeacher(Teacher teacher){
        repository.saveTeacher(teacher);
    }

    public Teacher getTeacherDetails(int id ){
        return repository.getTeacherDetails(id);
    }
}

现在让我们创建存储库层类,

?@Service
public class ResourceService{

    @Autowired
    ResourceRepository repository;

    public void saveTeacher(Teacher teacher){
        repository.saveTeacher(teacher);
    }

    public Teacher getTeacherDetails(int id ){
        return repository.getTeacherDetails(id);
    }
}

以上两个类显示了服务和存储库层,分别在com . tutorial . study now . Servicecom . tutorial . study now . Repository包中创建。

已开发项目设置的结构:

让我们探究一下目前为止我们项目的结构,

上图 8.2 显示了开发的设置的结构。要运行该应用,右键单击Application.java,然后单击作为 Java 应用运行

上图 8.3 显示了应用已经启动并准备好接收请求。让我们使用 Rest 客户端 Postman 测试应用。

上图是 POSTMAN 观察到的截图,URL 作为localhost:8080/saveTeacher传递,用于保存教师详细信息(参考 ResourceController 类中的端点)。

选择 Body 选项卡,然后选择单选按钮 raw,将上面的 JSON 结构放置在 POSTMAN 中,并点击发送按钮(右上角)。我们可以看到收到的状态是右下角的 200 OK ,表示请求成功。

JSON 结构将被映射到教师实例,该实例是端点中的参数(参见资源控制器类)。@RequestBody是帮助将 JSON 结构绑定到教师类实例的注释。

请注意,我们不是使用数据库,而是将详细信息存储在哈希表中,整数是我们在上面声明的关键字,它应该是一个唯一的值。因此,当发出多个请求时,请确保整数值是唯一的。
T3】

上图显示了来自 POST MAN 的 GET 请求,并观察到 ID 值在 URL 中作为路径变量传递。

要描述路径变量,请参考上面创建的 ResourceController 类,它有端点/getTeacherDetails/{id}。这里的 PathVariable 是包含在大括号中的 id。Spring-boot 提供了一个注释@PathVariable,用于捕获网址中的路径变量。

我们将这个标识传递给存储库,并从地图中获取值。请注意,该值只不过是返回的教师类的一个实例,可以在邮递员的响应正文中看到。

结论:在本教程中,我们已经看到了使用 spring-boot 的 REST-API 开发和使用 Rest-client 的测试的开发。



使用内存数据库的 Spring Boot 应用

原文:https://www.studytonight.com/spring-boot/spring-boot-application-with-inmemory-database

在本教程中,我们将学习内存数据库 (H2)与 spring boot 的用法。在许多情况下,h2 不是使用关系数据库,而是用来测试开发功能,因为它不需要程序员进行配置。

使用 H2 数据库开发应用:

  • 在项目设置期间选择了 H2 依赖项,它提供了启用内存数据库所需的 JARs。

  • 我们在上一个教程中创建了 pojo,作为com . tutorial . study south . POJO包下的Teacher.javaStudent.java

  • 我们需要将 pojo 的字段与内存数据库中创建的表的列进行映射。所以用下面的代码修改Teacher.java文件。

    @Entity
    @Table(name="TEACHER")
    public class Teacher {
        @Id
        @Column(name="ID")
        private int id;
        @Column(name="NAME")
        private String name;
        @Column(name="SUBJECT")
        private String subject;
        @Column(name="INSTITUTE")
        private String institute;
        @Column(name="CITY")
        private String city;
    
        //Setters and Getters
    
    }
    
  • @Entity:这个注释用来将类标记为一个能够参与数据库事务的实体。

  • @Table:该注解用于将类与数据库中创建的表进行映射。它有一个名为 name 的属性(可以在上面的代码中看到),用于命名数据库中的表。

  • @Id:该注解用于唯一标识数据库中的记录。它充当主键。在上面的代码字段中,id 标有这个注释,这样每个教师记录都是唯一的。

  • @Column:该注解用于将实体中的每个字段映射到数据库的列。

这样,类和字段分别映射到表和列。

更新我们的 REST 项目代码:

我们已经在java.util.HashMap中创建了端点、服务层、存储库层来保存教师详细信息。

代码在控制器和服务层保持不变,但是我们需要更改存储库细节,将值存储在数据库中,而不是哈希表中。观察不同层的代码。

@RestController
public class ResourceController {

    @Autowired
    ResourceService resourceService;

    @PostMapping("/saveTeacher")
    public void saveTeacher(@RequestBody Teacher teacher){
        resourceService.saveTeacher(teacher);
    }
}

@Service
public class ResourceService {

    @Autowired
    ResourceRepository repository;

    public void saveTeacher(Teacher teacher){
        repository.saveTeacher(teacher);
    }
}

@Repository
public class ResourceRepository {

    @PersistenceContext
    EntityManager entityManager;

    @Transactional
    public void saveTeacher(Teacher teacher){
        entityManager.persist(teacher);
    }
}

在存储库层,我们使用EntityManager来帮助管理实体,该方法用javax.persistence.Transactional进行注释,并帮助管理数据库事务,同时将教师对象保存在内存数据库中。

用 POSTMAN 测试:

1。运行应用并发送POST请求将实体保存在数据库中。

2。上图显示客户端发送的POST请求,将详细信息保存在数据库中。收到的响应代码是200 OK,可以在右下角看到。

3。为了启用H2-控制台,我们需要应用中的以下属性。

spring.h2.console.enabled=true

4。我们再次请求将实体保存在数据库中,h2-console 浏览到网址本地主机:8080/h2-console ,该网址将重定向到类似于下面截图的 JSP 页面。

5。默认情况下,以上字段会填写用户名、URL,我们只需要点击连接即可,无需输入任何字段。它将重定向到类似下图的另一个屏幕。

6。请注意,上图中有一个名为教师创建的表,因为该类被映射到名为教师的表(参见Teacher.java)。

7。上表包含客户端保存的教师实体。

结论:在本教程中,我们讨论了 spring boot 应用,它使用内存中的 H2 数据库将数据存储到数据库中,这与 HashMap 不同。需要注意的一点是,内存数据库是一个临时数据库,每次启动服务器时,记录都会被删除。在生产环境中,如果选择了关系数据库管理系统,我们需要提供数据源网址、用户名和密码等详细信息。



Spring Boot 高级

SpringBoot HATEOAS

原文:https://www.studytonight.com/spring-boot/spring-boot-hateoas

在本教程中,我们将讨论 Spring boot HATEOAS(从这里 了解 HATEOAS),它代表超媒体作为应用状态的引擎。每当我们访问一个 web 应用时,我们也会发现一些超链接,允许我们进行多种活动。比如在任何一个网银网站的首页,我们都可以找到查看交易查看余额进行交易添加收款人等多个选项。所有这些超链接提供了多种信息。让我们在本教程中实现一个 HATEOAS 技术。

创建符合 Spring Boot HATEOS 的 REST 应用编程接口

我们正在开发一个允许我们保存与学生相关的细节的应用编程接口。

在前面的例子中,我们在包中创建了名为Teacher.javaStudent.java的 pojo。

我们将在java.util.Map中保存学生的详细信息,并将从另一个 GET 端点获取学生的详细信息。

当用户请求任何学生数据时,我们将提供所请求的数据以及所有学生的链接,作为附加信息的一部分。

将下面的代码添加到我们之前创建的ResourceController.java中。为了强调这个例子,有目的地删除了前面的代码。

@RestController
public class ResourceController {

    @PostMapping("/saveStudent")
    public void saveStudent(@RequestBody Student student){
        resourceService.saveStudent(student);
    }

    @GetMapping("/getAllStudents")
    public Map<Integer,Student> allStudents(){
        return resourceService.allStudents();
    }

    @GetMapping("/getStudentDetails/{id}")
    public Resource<Student> getStudentDetails(@PathVariable("id") int id){
        Student student=resourceService.getStudentDetails(id);
        ControllerLinkBuilder link=linkTo(methodOn(this.getClass()).allStudents());
        Resource<Student> resource=new Resource<Student>(student);
        resource.add(link.withRel("all-students"));
        return resource;
    }
}

上述资源控制器类中定义的端点用于保存学生数据,并从地图中检索学生的详细信息。

Spring HATEOS 提供了像 ControllerLinkBuilder 这样的类,帮助我们在使用 spring boot 开发 REST 服务时启用 HATEOAS 原则。

我们需要使用import static语句导入 ControllerLinkBuilder 类的静态方法。让我们举一个简单的例子来解释我们如何以及何时使用import static语句。

package com.airline;

Class Airline{

    public static String airLicense;
    public static String headQuarters;

    public static String getLicense() {
        return airLicense;
    }

    public void getData(){
        //  Statements
    }

}

要导入上述航空公司等级的静态成员,我们需要使用如下import static语句:import static com.airline.Airline.*;

在上面指定的端点中,我们有从ControllerLinkBuilder开始的方法,如methodOnlinkTo等,它们是静态的。

methodOn(Class<T>)返回class<T>引用,该引用作为参数传递,然后传递给linkTo(Class<T>)方法,该方法返回ControllerLinkBuilder的引用。

资源是另一个类,用于添加ControllerLinkBuilder返回的链接,并为链接提供自定义名称,我们使用来自ControllerLinkBuilder类的方法withRel(String name)

资源是包含请求的单个学生详细信息以及与所有学生相关的 HATEOAS 链接的实例。

我们还需要在服务层和存储库层进行更改。将下面的代码添加到我们之前创建的ResourceService.java中。

public class ResourceService {

    public void saveStudent(Student student){
        repository.saveStudent(student);
    }

    public Map<Integer,Student> allStudents(){
        return repository.allStudents();
    }

    public Student getStudentDetails(int id){
        return repository.getStudentDetails(id);
    }
}

将下面的代码添加到我们之前创建的ResourceRepository.java中。

@Repository
public class ResourceRepository {              

    public void saveStudent(Student student){
        studentMap.put(student.getId(),student);
    }

    public Map<Integer,Student> allStudents(){
        return studentMap;
    }

    public Student getStudentDetails(int id){
        return studentMap.get(id);
    }
}

测试应用编程接口

让我们保存学生的详细信息,如下图所示。

testing HATEOAS compliant REST service in spring boot

开机自检请求成功,右下角可以看到 200 OK 状态。

我们可以再创建一个 POST 请求来存储详细信息,这样我们就可以查看多个学生数据。

现在让我们获取一个单独的学生信息,该信息还返回所有可用学生的 HATEOAS 链接

testing HATEOAS compliant REST service in spring boot

结论:在本教程中,我们已经看到了 spring HATEOAS 的重要性,并使用一个示例实现了它。这里需要注意的一点是,spring boot 在 HATEOAS 和 URIs 之间提供了松散的耦合,这些耦合是用端点映射的。这是因为我们不关心 URI 模式是否会改变,因为我们正在从它被映射到的端点捕获 HATEOAS 链接。



Spring Boot Swagger 服务

原文:https://www.studytonight.com/spring-boot/spring-boot-swagger-service

在本教程中,我们将使用 Swagger 实现已开发的 REST APIs 的服务定义。

Spring Boot·Swagger-服务定义:

Web 应用为其正常功能定义了许多 API。随着 API 数量的增加,为客户端提供一个通用的服务定义是至关重要的,这样客户端就可以详细了解 API。它提供关于各种端点、参数、请求类型、响应类型等的信息。swaggle是由 SmartBear 软件开发的开源软件框架,最常用于自动化文档,RESTful Web Services 的代码生成和测试用例生成。

Spring Boot·Swagger-实施:

我们需要在我们的 pom.xml 文件中添加一些 maven 依赖脚本来开发 swagger 服务定义。将以下 maven 脚本添加到 pom.xml 文件中:

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.6.1</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.6.1</version>
</dependency>

添加上述脚本后,右键点击项目选择选项 Maven = >更新项目。Swagger 是由显示 web 应用中可用服务的脚本提供的。我们需要添加一些豆子来实现这一点。让我们将下面的代码添加到我们之前创建的BeansConfiguration.java中。

@Configuration
@EnableSwagger2
public class BeansConfiguration {

    @Bean
    public Docket docket() {
        Docket docket = new Docket(DocumentationType.SWAGGER_2);
        return docket;
    }
}

以上代码启用了项目中的 swag 用法,要查看 spring boot 的 swagger dependecy 提供的 swag UI,请键入 URL *http://localhost:8080/swagger-ui.html*,如下图所示:

Swagger UI for spring boot REST application

在上图中请注意提供的两个控制器, BasicErrorController 由 spring boot 自动提供,将用于向客户端显示白标错误等错误信息

另一个控制器是资源控制器,由我们创建,由几个用于数据访问的 GETPOST 端点组成。点击swagger-ui.html页面的上述资源控制器,会显示下图。

Swagger UI for spring boot REST application

Swagger UI for spring boot REST application

上图分别显示了 GET 和 POST 端点的服务定义。对于 post 请求,它还提供了一种测试 API 的方法,如上所示。它还提供了输入请求结构和可能显示的输出响应消息。

结论:在本教程中,我们已经看到了 swag 在理解已开发 REST APIs 的各种服务定义中的重要性。



Spring Boot 日志记录

原文:https://www.studytonight.com/spring-boot/spring-boot-logging

在本教程中,我们将讨论 Spring boot 中可用的日志选项。

Spring Boot 文件记录:

在任何应用运行和执行某些操作时,跟踪其正在进行的活动是非常重要的,而最有效的方法是通过日志记录。日志有助于我们更好地理解应用中发生的事情。日志还可以帮助我们跟踪应用的性能,并帮助我们了解优化的范围。也可以将它们发送到其他专用服务器进行进一步的处理和分析。可以通过在应用中添加简单属性来启用。

logging.path=D:

![](https://gitee.com/OpenDocCN/studytonight-zh/raw/master/docs/spring/img/858a7e7fe2f0db21204f0972f156f891.png)

上述属性启用自动创建的名为SpringD 驱动器的默认文件登录。

Spring Boot 控制台日志记录:

这样可以登录控制台,并注意下面的代码。我们需要使用由 Spring 靴配置的 slf4j 来遵循以下程序。

@SpringBootApplication
public class Application {

    public static void main(String a[]){
        // initialise the logger
        Logger logger = LoggerFactory.getLogger(Application.class);
        // use the logger
        logger.info("Application about to start");
        SpringApplication.run(Application.class, a);
    } 
}

using console logger for spring boot application

上图显示了应用启动前的控制台日志记录。它显示时间、线程名称和消息。SpringBoot 自动配置org.slf4j.Logger,可以按照上面的代码使用。

我们也可以在应用中使用属性。例如,如果您想查看内部 springframework 运行的日志,可以通过添加以下属性来实现:

logging.level.org.springframework=debug

上述属性允许在 DEBUG 模式下运行 spring 框架,这意味着我们将能够看到由 spring 完成的实例自动连接和为我们生成的自动配置报告。

上图显示了应用启动期间实例的自动连接描述。

我们还可以通过在应用中指定少量属性来更改日志的模式。要更改控制台的日志模式,请使用logging.pattern.console属性;要更改文件的日志模式,请使用logging.pattern.file属性。

# Logging pattern for the console
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} - %msg%n

# Logging pattern for file
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n

测井级别可以是TRACEDEBUGINFOWARNERRORFATALOFF中的一个。最常用的日志记录级别是:

INFO: 用于基础信息记录

DEBUG: 用于记录有助于应用调试的附加信息

错误:用于记录错误情况。

结论:在本教程中,我们看到了 spring boot 应用的日志记录,这一点非常重要,尤其是在生产环境中。



Spring Boot 过滤器

原文:https://www.studytonight.com/spring-boot/spring-boot-filtering

在本教程中,我们将讨论 pojos 中的属性过滤及其使用 spring boot 的实现。在某些情况下,我们不会向客户发送完整的信息,如密码、许可证等机密信息,以避免系统的任何漏洞。在这种情况下,需要过滤数据。在 spring boot 中,过滤可以有两种类型:

  • 静态过滤
  • 动态过滤

Spring Boot -静态过滤:

让我们在套餐com.tutorial.studytonight.pojo下创建一个等级航空公司

public class Airline {

    private String name;
    @JsonIgnore   //annotation used to ignore the field
    private String license;
    private LocalDate establishedDate;

    public Airline(String name,String license,LocalDate establishedDate){
        this.name = name;
        this.license = license;
        this.establishedDate = establishedDate;
    }

    //Setters and Getters
}

让我们将ResourceController.java更改如下:

@RestController
public class ResourceController {

    @GetMapping("/staticFiltering")
    public Airline staticFiltering() {

        LocalDate establishedDate=LocalDate.parse("1888-09-04"); 
        AirlineairLine = new Airline("Super Aviation","AS23OIP8", establishedDate );
        return airLine;
    }
}

我们在Airline.java中用@JsonIgnore注解了字段许可证,因此该字段在发送到客户端时会被忽略。启动应用来测试这个应用编程接口。

上图显示了发送的静态过滤请求,响应主体没有“许可证字段,因为它在 pojo 类中用@JsonIgnore进行了注释。

Spring Boot -动态过滤:

我们可以通过分别修改Airline.javaResourceController.java来实现动态级别的过滤,如下图所示:

@JsonFilter("dynamicfilter")
public class Airline {

    private String name;
    private String license;
    private LocalDate establishedDate;

    public Airline(String name, String license, LocalDate establishedDate){
        this.name = name;
        this.license = license;
        this.establishedDate = establishedDate;
    }

    //Setters and Getters
}

@RestController
public class ResourceController {

    @GetMapping("/dynamicFiltering")
    public MappingJacksonValue dynamicFiltering() {

        LocalDate date = LocalDate.parse("1888-09-04");

        SimpleBeanPropertyFilter propertyFilter = SimpleBeanPropertyFilter.filterOutAllExcept("license");
        // Adding filter using a id name
        FilterProvider filter = new SimpleFilterProvider().addFilter("dynamicfilter", propertyFilter);    

        Airline airLine = new Airline("Super Aviation", "AS23", date);
        // Setting a filter
        MappingJacksonValue value = new MappingJacksonValue(airLine);
value.setFilters(filter);    
        return value;    
    }
}

SimpleBeanPropertFilter是提供如filterOutAllExcept等方法的类,用于过滤 pojo 中的字段。在上述方法中,字段许可证作为参数被传递,这意味着过滤除许可证之外的所有字段。

FilterProvider是另一个类,它在上面的代码中添加了一个唯一的 id 名为dynamicfilterSimpleBeanPropertyFilter

请注意,上面的 pojo 也被注释为@JsonFilter传递与dynamicfilter相同的 Id 名称。

MappingJacksonValue将被反序列化以向客户端返回响应。启动要测试的应用。

上图显示为动态过滤发送的 GET 请求。请注意,由于在此字段上设置了简单属性过滤器方法过滤除以外的所有字段。

结论:这样,从使用 spring boot 发送到客户端就可以完成对机密信息的过滤。



读取 Spring 配置的方法

原文:https://www.studytonight.com/spring-boot/methods-to-read-spring-configuration

在本教程中,我们将学习阅读 spring boot 配置的方法。我们已经了解到,spring boot 会根据项目设置时选择的依赖关系自动配置项目。编写自定义配置的另一种方式是使用 application.properties 文件,在该文件中可以定义用户属性。

我们将在应用中编写一些自定义属性。属性将创建一个组件来读取应用中的细节。

让我们在 application.properties 文件中添加以下属性。

custom.property.security=enabled
custom.property.validation=enabled
custom.property.spring=boot

在根包下创建一个类,如下所示:

@Component
@ConfigurationProperties("custom.property")
public class ApplicationConfiguration {

    private String security;
    private String validation;
    private String spring;

    //Setters and Getters

}

该类用@Component@ConfigurationProperties注解。@Component注释用于标记类而不是方法,而@Bean用于方法。上面创建的类将由 spring 作为一个组件来管理。我们已经讨论了用于扫描所有可用组件的@ComponentScan。它可以用@SpringBootApplication代替,因为它也可以执行@ComponentScan功能。@ConfigurationProperties提供了一个字符串,其格式类似于 application.properties 中提到的属性,这些属性的最后一个前缀被声明为上述类中的字段(比较 application.properties 和 ApplicationConfiguration 类)。

我们现在将开发一个小的应用编程接口,允许我们使用上面的@Component注释类显示配置。

Spring boot 允许我们自动连接应用配置类,并观察下面的应用编程接口代码。

public class ResourceController {
    @Autowired
    ApplicationConfiguration applicationConfiguration;

    @GetMapping("/getConfiguration")
    public ApplicationConfiguration getConfiguration(){
        return applicationConfiguration;
    }
}

上面的类返回由 spring boot 自动连接的 ApplicationConfiguration 的引用。由于请求是一个 GET 请求,让我们从浏览器点击应用编程接口:

具有上述配置的应用配置字段已返回浏览器。

使用注释获取应用配置:

读取配置的另一种方法是使用@Value注解。@Value根据传递的字符串读取配置,观察下面的代码:

public class ResourceController{ 

    @Value("${custom.property.spring}")
    String val;

        @GetMapping("/getConfigurationProperty")
        public String getConfigurationProperty() {
            return val;
        }
} 

上面的代码读取指定的custom.property.spring属性,并将该值绑定到字符串变量。

上面的代码有一个 GET 请求处理程序,它将值返回给客户端。

当应用需要一些初始化参数,如安全令牌验证时间等时,它非常有用。例如,让我们假设用户发送了一个 JWT 令牌,并且它应该在 24 小时内有效。我们可以在我们的应用中设置属性。属性文件可以在用户尝试使用 JWT 令牌进行认证时使用。Spring Security 模块提供了一种处理 JWT 的方法。当遵循微服务架构时,处理配置管理是非常重要的。

结论:在本教程中,我们已经看到了用户在 application.properties 中定义的自定义配置,以及使用 ConfigurationProperties 类和@Value注释读取应用配置的方法。



Spring Boot 全局异常处理

原文:https://www.studytonight.com/spring-boot/spring-boot-global-exception-handling

在本教程中,我们将讨论 spring boot 提供的定制异常处理。在 Java 中,异常处理是由 try,catch 块完成的,但是 spring boot 也允许我们提供定制的全局异常处理,在这里我们不需要添加 try catch 块 everwhere,我们可以创建一个单独的类来处理异常,它还将异常处理代码与业务逻辑代码分开。

Spring Boot 的全局异常处理:

我们需要创建一些类来实现 spring 启动异常处理。我们的ResourceController.java文件有许多端点,我们在之前的教程中使用 Rest 客户端测试了这些端点。其中一个端点允许我们在 Id 的基础上获取教师详细信息,该 Id 作为路径变量传递。在某些情况下,如果 Id 没有存储在我们的java.util.HashMap (在我们的存储库层中使用)中,它返回空引用,状态为 200 Ok。让我们返回 404 未找到的响应状态,并在找不到教师时显示一条定制的异常消息。

com . tutorial . study south . exception包中创建以下类。

TeacherNotFoundException.java 类:这是一个用户定义的类,扩展了Java . lang . runtimeexception类。

public class TeacherNotFoundException extends RuntimeException {
    // Exception class 
}

ExceptionResponse.java 类:该类属性将作为定制异常处理的一部分返回给客户端。

public class ExceptionResponse {

    private String message;
    private LocalDateTime dateTime;

    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public LocalDateTime getDateTime() {
        return dateTime;
    }
    public void setDateTime(LocalDateTime dateTime) {
        this.dateTime = dateTime;
    }    
}

CustomizedExceptionHandling.java 类:该类用@ControllerAdvice注解,这意味着该类将能够处理任何控制器发生的异常(不仅限于ResourceController.java)。它扩展了类ResponseEntityExceptionHandler,公开了实现该特性所需的功能。需要@ExceptionHandler注释来处理抛出的异常类型,相应的方法将能够处理异常。

@ControllerAdvice
public class CustomizedExceptionHandling extends ResponseEntityExceptionHandler {

    @ExceptionHandler(TeacherNotFoundException.class)
    public ResponseEntity<Object> handleExceptions( TeacherNotFoundException exception, WebRequest webRequest) {
        ExceptionResponse response = new ExceptionResponse();
        response.setDateTime(LocalDateTime.now());
        response.setMessage("Not found");
        ResponseEntity<Object> entity = new ResponseEntity<>(response,HttpStatus.NOT_FOUND);
        return entity;
    }
}

Spring boot 提供了响应实体****HttpResponse等类,用于设置响应代码,可以将异常实体作为消息发送给客户端。在上面的代码中,用@ExceptionHandler注释的方法足以处理示教不发现异常。创建了响应实体对象,并传递了异常响应和 HttpStatus,这将反映在定制消息中。

让我们测试一下我们之前创建的getTeacherDetails服务方法,注意下面分别在控制器、服务和存储库层的代码。

@RestController
public class ResourceController {

    @Autowired
    ResourceService resourceService;

    @GetMapping("/getTeacherDetails/{id}")
    public Teacher getTeacherDetails(@PathVariable("id") int id){
        Teacher teacher = resourceService.getTeacherDetails(id);
        if(teacher == null)
            throw new TeacherNotFoundException();

        return teacher;
    }
}

@Service
public class ResourceService {

    @Autowired
    ResourceRepository repository;

    public Teacher getTeacherDetails(int id){
        return repository.getTeacherDetails(id);
    }
}    

@Repository
public class ResourceRepository {

    private Map<Integer,Teacher> teacherMap = new HashMap<Integer,Teacher>();

    public Teacher getTeacherDetails(int id){
        Teacher teacher = teacherMap.get(id);
        return teacher;
    }
}

运行应用,并使用 POSTMAN 测试应用编程接口。

custom exception handling in spring boot

从上图可以看出,收到的响应包含异常响应字段,状态代码为 404 未找到。我们暂时没有保存 id 为 1001 的任何详细信息,因此,上述响应已返回给客户端。

结论:在本教程中,我们已经看到了使用 spring-boot 和注释的定制异常处理。



Spring Boot 验证

原文:https://www.studytonight.com/spring-boot/spring-boot-validations

在本教程中,我们将讨论 SpringBoot 验证及其实现。验证用于限制字段的值、大小、范围等。大多数验证通常是在前端使用 Javascript 完成的,但是 spring boot 也提供了一种服务器端验证的方式。

Spring Boot 验证实施:

让我们将之前创建的网站教程. study now . POJO中的Teacher.java更改如下:

public class Teacher {
    private int id;
    private String name;
    private LocalDate joiningDate;
    private String institute;
    private String subject;

    //Setters and Getters
} 

javax.validation 包提供了许多验证注释,使我们能够验证字段。用下面的代码修改Teacher.java:

public class Teacher {

    @Size(max=10,min=5,message="criteria not met")
    private String name;

    @Size(min=3)
    private String institute;

    @Max(value=10)
    private int id;

    private String subject;

    @Past
    private LocalDate joiningDate;

    //Setters and Getters
}
  • @Size注释用于将字段长度限制为指定值。它具有最大最小等属性,分别用于设置最大值和最小值。该注释中的消息属性用于显示验证失败的默认消息。
  • @Max注释用于限制字段的值。在上面的代码中, id 字段可以有最大值 10。
  • @Min注释用于将字段的值限制为最小值。
  • @Past@Future应用于日期,以确保数据分别在过去或未来。

在上图中,我们使用 POSTMAN 发送教师详细信息。注意右下角的 400 不良请求。当我们将Teacher.java类中提到的验证与 postman 中的 JSON 结构进行比较时,字段名应该至少为 5 个字符,因此它导致了 400 个错误请求。

上图表示 400 个坏请求的响应主体。请注意默认消息“不符合标准”,这是在验证 Teacher.java 类中的名称字段时设置属性消息时显示的。让我们测试完成所有验证的应用编程接口。

可以看到,上述请求已经成功返回 200 OK 状态。response entityexceptionhandler有一个在验证失败时调用的方法。我们在 packagecom . tutorial . study south . exception中创建了一个customizedexception handler,它扩展了response entityexceptionhandler类。我们需要覆盖响应异常处理程序类的方法,如下所示:

@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
HttpHeaders headers, HttpStatus status, WebRequest request) {

    System.out.println("Validation failed");
    return super.handleMethodArgumentNotValid(ex,headers, status,request);

}

让我们再次测试 API,如下所示。

由于上图中的请求失败,它调用覆盖handleMethodArgumentNotValid方法显示控制台消息,如下所示:

结论:在本教程中,我们已经看到了在 spring boot 中使用不同注释的验证实现。



Spring Boot 云部署

原文:https://www.studytonight.com/spring-boot/spring-boot-cloud-deployment

在本教程中,我们将在云环境中部署 spring-boot 应用。应用开发通常经历三个阶段,即开发测试和生产部署。我们将在 Heroku 云上部署应用。

托管我们服务的云注册

我们需要在提供托管云服务的 heroku 上注册: 注册/登录 后登录使用 Heroku 服务。

在云上部署 Spring Boot 应用

Heroku 为云上不同的部署提供服务,我们需要 Git ( 在你的本地机器上安装 Git)和 Heroku CLI(命令行界面)安装在机器上。登录后,我们将被重定向到 heroku 仪表板,类似于下图 18.1:

deploying spring boot application on heroku

上面的仪表板显示了部署在云上的可用应用,要部署新应用,请单击右上角的新建按钮,该按钮显示了下图所示的两个选项。

deploying spring boot application on heroku

点击创建新应用选项,该选项会将您重定向至如下所示的屏幕:

deploying spring boot application on heroku

输入 App 名称后,会显示消息是否可用(您必须为您的 App 选择一个唯一的名称),所选区域如上图所示。点击创建应用后,将显示以下屏幕,描述要遵循的程序。如上所述,Heroku CLI 更倾向于在 Heroku 上部署应用,可以从这里安装- Heroku CLI

下面的屏幕截图显示了部署时应遵循的说明。

deploying spring boot application on heroku

切换到创建我们项目的工作区,并在该位置打开 CMD 。键入命令 heroku 登录(确保系统中正确安装了 GIT 和 herkou CLI)。它显示如下图所示的信息,并输入任意键。

deploying spring boot application on heroku

浏览器上将打开一个新窗口,要求用户登录。由于我们已经登录,登录屏幕将类似于下图。

deploying spring boot application on heroku

deploying spring boot application on heroku

上图显示了登录后将在 CMD 上显示的认证过程,如图 18.6 所示。CMD 是在切换到工作区后打开的,如果是其他目录,请确保将目录更改到工作区。

deploying spring boot application on heroku

上图 18.8 是创建项目的工作区内容。

deploying spring boot application on heroku

按照上图所示的上述命令进行操作:

  • git init = >初始化指定目录中的 Git 存储库。
  • heroku git:remote -a studytonight = >与英雄库云建立远程。
  • git add . = >添加部署所需的所有文件。
  • git commit = >添加文件后提交。
  • 我们需要使用 git push heroku master 命令将项目推送到 Heroku 云。

deploying spring boot application on heroku

上图 18.11 显示了部署成功后的最终部署消息,访问我们云上应用的链接是https://studytonight.herokuapp.com,可以用来击中 Rest 端点。

让我们在云上测试应用,如下所示。我们已经启用了显示应用的可用资源端点的 swagger。

deploying spring boot application on heroku

注意图 18.12 中 heroku 云提供的网址。

结论:在本教程中,我们已经看到了 spring-boot 项目在 heroku 云上的部署。该应用有许多特定于云的状态,如 Hibernate、唤醒、睡眠,这些状态特定于 heroku 云,并且取决于使用该应用的活跃用户数量


    • *
posted @ 2024-10-24 18:15  绝不原创的飞龙  阅读(2)  评论(0编辑  收藏  举报