JavaRush /Java 博客 /Random-ZH /Maven、Spring、MySQL、Hibernate 和第一个 CRUD 应用程序简介(第 1 部分)
Макс
第 41 级

Maven、Spring、MySQL、Hibernate 和第一个 CRUD 应用程序简介(第 1 部分)

已在 Random-ZH 群组中发布
下午好。在这篇文章中,我想分享我在创建一个简单的 CRUD 应用程序的过程中第一次接触到 Maven、Spring、Hibernate、MySQL 和 Tomcat 等东西。这是 4 的第一部分。本文主要面向那些已经完成 30-40 级,但尚未超越纯 Java 并刚刚开始(或即将开始)进入开放世界的人所有这些技术、框架和其他陌生的词语。 Maven、Spring、MySQL、Hibernate 和第一个 CRUD 应用程序简介(第 1 部分)- 1

内容:

介绍

通过研究各种使用它们的示例,我开始熟悉对我来说陌生的技术和框架,因为通常当我使用成熟的应用程序示例看到它的实际运行时,我才能最好地理解它。通常,此类示例是CRUD应用程序(创建读取更新删除),互联网上充满了此类不同复杂程度的示例。问题是,他们通常不会详细解释如何、做了什么以及为什么做了,为什么添加了这样那样的依赖项,为什么需要这样那样的类等等。在大多数情况下,他们会采用一个完全完成的应用程序,带有最终的 POM 文件和类的最终版本,然后简单地运行每个应用程序,而不关注对有经验的人来说可能看似显而易见的小事情。我看过很多这样的例子,通常很清楚一切是如何运作的,但他们是如何做到这一点的并不完全清楚。因此,我认为这样的例子是有用的,不是从经验丰富的开发人员的角度来看,而是从从未接触过 Spring、Hibernate 和其他东西的初学者的角度来看。
Знакомство с Maven, Spring, MySQL, Hibernate и первое CRUD приложение (часть 1) - 2
我将尝试尽可能详细地描述(在我的理解允许的范围内)我创建 CRUD 应用程序的整个路径,从最简单的 Hello World 级别开始。首先,我这样做是为了自己,因为当你尝试描述、讲述、解释某件事时,它会更好地在你的头脑中被吸收和组织。但如果这对某人有用并帮助他们解决问题,我会非常高兴。在此示例中,让我们尝试使用MavenTomcatSpringHibernateMySQL创建一个简单的 CRUD 应用程序。初步步骤如安装MavenMySQL、使用Ultimate版本的 idea 等。我想不用详细描述了,这个应该没有问题。值得注意的是,在这个示例中,配置将使用 Java 类(称为 JavaConfig)进行配置,而不使用 xml。

创建项目

所以,由于我是新手,我们不会使用任何晦涩的原型。Spring Initializr 听起来还是太可怕了。因此,我们将创建一个最普通的简单Maven项目。我没有域名,所以在 groupid 中我只写testgroup,在 artifactid 中我写名字,例如filmography(这将是电影列表)。我们创建一个项目,并Enable auto-import在有想法时做出选择。得益于此,每次我们对 POM 文件(项目对象模型,该文件描述了 Maven 项目的整个结构)进行任何更改时,所有内容都会立即自动应用到项目中。如果我们已经拥有这些库,或者如果我们使用一些以前没有处理过的新依赖项,那么 Maven 将简单地通过 Internet 从中央存储库下载它们。Maven还有下载源代码和文档的功能(Download Sources and/or Documentation)。这也很方便,如果对某个类或方法有不清楚的地方,可以去源码看看里面是如何工作的。让我们添加一些细节。这将是一个 Web 应用程序,我们将使用Tomcat。要将应用程序部署到 Tomcat,您需要将其以 war 存档(Web 应用程序资源,Web 应用程序的特殊格式)的形式传输到 Tomcat。为此,请将以下行添加到 POM 文件中,以便将应用程序编译到 war 存档中:
<packaging>war</packaging>
好吧,您还需要一个专门的 Web 源目录,在我们的例子中将有jsp页面和一些 Web 资源。让我们创建一个main目录webapp。它的名称和定位main方式应该与 完全相同javaresources因为这是标准的 Maven 目录结构。一旦我们安装了该包war并确定这是一个 Web 项目,该目录webapp将自动标记为 Web 应用程序源(上面会有一个蓝点),并且与 Web 相关的所有内容都将在此文件夹中搜索。一会儿。默认情况下,Maven 使用语言版本 1.5,但我想使用版本 1.8 - Java 8(您可以采用 10 或 11,但仍然没有计划使用其中的任何功能,因此将其设为 8 )。这个问题可以很简单地解决,我们在 Google 中编写类似“Maven java 8”的内容,然后查看需要添加到 POM 文件中的内容,以便 Maven 编译我们的类以获得所需的版本。结果,我们有以下结果: Знакомство с Maven, Spring, MySQL, Hibernate и первое CRUD приложение (часть 1) - 3

Spring MVC 连接

你必须从某个地方开始。按照计划,我们将连接数据库并使用Hibernate,但这一切目前听起来有点太可怕了。我们需要先做一些更简单的事情。Spring MVC,这个已经比较好了,我们已经熟悉MVC模式很久了,课程中一半的大型任务都用到了它。从这里我们将开始跳舞。要使用 Spring MVC 创建 Web 应用程序,我们还需要一个 Servlet-API,即 请求-响应交互将在其帮助下发生的东西。让我们尝试连接这个。我们去 Google,在Maven 存储库中查找必要的依赖项,并将它们添加到pom.xml. Знакомство с Maven, Spring, MySQL, Hibernate и первое CRUD приложение (часть 1) - 4在外部库部分,您可以看到不仅加载了spring-webmvc,还加载了一堆其他东西。那些。我们不需要另外包含spring corecontextbeans等的依赖项。我们需要的一切都与spring-webmvc一起被拉起。

我们需要做一个小小的免责声明。通常建议仍然为每个使用的库单独添加依赖项,即使它们已经与已添加的库捆绑在一起,因为 这可以帮助避免一些问题和故障。

一个简单的例子。假设我们添加了一个使用某些 API 的依赖项,同时它将拉出该 API 的某种实现。然后我们添加了另一个使用相同 API 的依赖项,并为此提取了一些实现,但这次有所不同。因此,我们将拥有同一 API 的 2 种不同实现。而如果我们自己想在某个地方使用这个API的某些方法,那么就会出现一个问题,因为系统不会知道要使用哪个实现,它会随机选择,也许不是我们期望的。如果您明确指定其中一个实现的依赖关系,那么将优先考虑它。

然而,这并不是一个严格的建议;它主要适用于使用来自不同公司的许多不同库的大型项目。我们不会在这里这样做,以免加载过多的 POM 文件;预计不会出现问题。但尽管如此,仍然值得牢记这一点。

还有一点注意。provided依赖是什么意思javax.servlet-apiScope是依赖项的范围,provided这意味着依赖项在编译和测试应用程序的阶段将可用,但不会被存档。事实上,为了部署应用程序,我们将使用 servlet 容器 Tomcat,并且它内部已经有这样的库,因此无需将它们传输到那里并给存档带来不必要的负载。展望未来,出于同样的原因,我们将不使用通常的方法main,因为它已经存在于 Tomcat 中。

创建页面和控制器

现在让我们尝试做一些简单的东西。首先,让我们创建一个webapp额外的目录,例如pages,我们的视图将存储在其中,即 jsp 页面,并创建几个页面。例如,我们将来需要一个页面来显示电影列表,films.jsp也许我们可以制作一个单独的页面进行编辑,就这样吧editPage.jsp。我们暂时不会在其中填写任何严肃的内容;只是为了测试,我们将在一个页面上创建到另一个页面的链接。 现在我们需要一个处理请求的类,即 控制器。让我们添加一个新的包controller并在其中创建一个类FilmController(一般来说,没有必要将所有内容都打包在不同的包中,这个应用程序会非常小且简单,但是在正常的项目中可以有很多控制器,配置类,模型等等,所以即使从小项目开始,最好立即习惯以有序和结构化的方式做所有事情,这样就不会出现混乱)。在此类中,我们将创建一些方法来返回我们的视图以响应请求。
package testgroup.filmography.controller;

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

@Controller
public class FilmController {

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public ModelAndView allFilms() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("films");
        return modelAndView;
    }

    @RequestMapping(value = "/edit", method = RequestMethod.GET)
    public ModelAndView editPage() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("editPage");
        return modelAndView;
    }
}
重点是什么?Spring MVC 有一个东西叫做DispatcherServlet. 这就像主控制器一样,所有传入请求都经过它,然后将它们传递到特定控制器。该注释@Controller只是告诉 Spring MVC 这个类是一个控制器(嗯,一般来说是逻辑的),调度程序将检查注释@RequestMapping以调用适当的方法。该注释@RequestMapping允许您指定控制器方法的地址,通过该地址它们将在客户端(浏览器)中可用。它也可以应用于控制器类来设置所有方法的根地址。该方法的allFilms()参数value设置为“ /”,因此当在浏览器中输入http://host:port/组合时(即默认为http://localhost:8080/http ://127.0 .0.1:8080/)。该参数method指定支持什么类型的请求(GET、POST、PUT 等)。由于这里我们只接收数据,所以使用GET。稍后,当添加和编辑的方法出现时,已经有POST请求了。(顺便说一句,您可以等效地使用注释等来代替@RequestMapping指示方法的注释))。在我们的方法中,我们创建一个对象并设置需要返回的视图的名称。 @GetMapping@PostMapping@GetMapping@RequestMapping(method = RequestMethod.GETModelAndView

配置

让我们继续设置配置。让我们在包中创建config一个类WebConfig。它将只有一个返回 type 对象的方法ViewResolver,这是按名称查找表示所需的接口。
package testgroup.filmography.config;

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.view.InternalResourceViewResolver;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "testgroup.filmography")
public class WebConfig {

    @Bean
    ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/pages/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }
}
@Configurationbean告诉Spring这个类是一个配置类,包含组件的定义和依赖关系。Bean是由 Spring 管理的对象。该注释用于定义 bean @Bean@EnableWebMvc允许您从WebMvcConfigurationSupport. 例如,您还可以实现一个WebMvcConfigurer具有大量方法的接口,并根据您的喜好自定义所有内容,但我们还不需要深入讨论,标准设置就足够了。 @ComponentScan告诉 Spring 在哪里寻找它应该管理的组件,即 用注释@Component或其派生标记的类,例如@Controller@Repository@Service。这些注释自动定义类 bean。在该方法中,viewResolver()我们创建其实现并确定在webapp. 因此,当我们在控制器方法中设置名称“ films”时,视图将被发现为“ /pages/films.jsp”所以,我们有一个配置类,但现在它只是某种单独的类,它不会以任何方式影响我们的应用程序。我们需要在 Spring 上下文中注册此配置。为此你需要一个类AbstractAnnotationConfigDispatcherServletInitializer。在包中,config我们创建它的后继者,例如AppInitializer,并实现它的方法。
package testgroup.filmography.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[0];
    }

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

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}
最后一个方法注册地址,还有另外 2 个方法用于注册配置类。ViewResolver定义 等的Web 配置位于getServletConfigClasses(). 最好在文档和各种指南中阅读所有这些内容,但在我们的例子中,还没有必要深入研究这一点,WebConfig原则上,我们的可以RootClasses在两者中定义,您甚至可以同时定义两者,它仍然可以工作。还有一件事。当从表单发送带有俄语字符的值时,结果可能是乱码,这可能会出现编码问题。为了解决这个问题,我们将添加一个过滤器来预处理请求。我们转到AppInitializer类并重写该方法getServletFilters,在该方法中我们指示所需的编码,当然,它应该与其他地方相同,如页面和数据库中:
protected Filter[] getServletFilters() {
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        characterEncodingFilter.setForceEncoding(true);
        return new Filter[] {characterEncodingFilter};
    }
好了,一切似乎都已设置完毕,您可以尝试运行它,看看会发生什么。 运行->运行->编辑配置->添加新配置-> Tomcat 服务器->本地 接下来,您需要选择要部署的工件。这个想法本身就会给出一个提示:Warning: Noartifactsmarkedfordeployment。单击“修复”按钮并选择...:战争爆发。或者您可以转到Deployment -> add -> Artifact -> ...: warexpededЗнакомство с Maven, Spring, MySQL, Hibernate и первое CRUD приложение (часть 1) - 5您还需要转到“部署”并将Applecation 上下文字段(这将是应用程序在浏览器中可用的 url 地址的一部分)设置为“ /”。 然后我们的应用程序将立即在http://localhost:8080/Знакомство с Maven, Spring, MySQL, Hibernate и первое CRUD приложение (часть 1) - 6上可用(但您也可以在那里指定一些内容,例如“ ”,然后您只需将其添加到所有地址,即例如不会有“http://localhost:8080/edit”,但它将是“http://localhost:8080/filmography/edit”)。单击“运行”并等待其启动。这就是我得到的: 一切似乎都很好,但有一个警告。事实是,我们的页面现在可以公开访问,并且可以通过在地址栏中写入路径来直接访问。我们输入http://localhost:8080/pages/films.jsp,现在我们在控制器不知情的情况下收到了我们的页面。不知怎的,这不是很正确,所以我们将创建一个特殊的目录。里面的内容将对公众隐藏,只能通过控制器访问。我们将带有视图 ( )的目录放置在 中,并相应地将其添加到前缀中: /filmographyЗнакомство с Maven, Spring, MySQL, Hibernate и первое CRUD приложение (часть 1) - 7webappWEB-INFpagesWEB-INFViewResolver
viewResolver.setPrefix("/WEB-INF/pages/");
现在我们的页面位于http://localhost:8080,但是如果我们直接尝试访问http://localhost:8080/WEB-INF/pages/films.jsp ,我们会收到 404 错误。好吧,太棒了,我们有最简单的网络应用程序,正如他们所说的“Hello World”。目前项目结构如下:
Знакомство с Maven, Spring, MySQL, Hibernate и первое CRUD приложение (часть 1) - 8

模型

我们已经有了视图和控制器,但在 MVC 中还有第三个字母,因此为了完成图片,我们还将添加一个模型。在包中,model让我们创建一个类Film,例如,具有以下字段:int idString title(标题)、int year(发行年份)、String genre(流派)和boolean watched(即您是否已经看过这部电影)。
package testgroup.filmography.model;

public class Film {
    private int id;
    private String title;
    private int year;
    private String genre;
    private boolean watched;
// + Getters and setters
}
没什么特别的,只是一个普通的类、私有字段、getter 和 setter。此类的对象也称为POJO(Plain Old Java Object),即 “简单的java对象”。现在让我们尝试创建这样一个对象并将其显示在页面上。现在,我们不会太担心如何创建它并初始化它。为了尝试一下,让我们直接在控制器中愚蠢地创建它,例如,如下所示:
public class FilmController {
    private static Film film;

    static {
        film = new Film();
        film.setTitle("Inception");
        film.setYear(2010);
        film.setGenre("sci-fi");
        film.setWatched(true);
    }
ModelAndView使用以下方法将此对象添加到我们的对象中addObject
@RequestMapping(method = RequestMethod.GET)
    public ModelAndView allFilms() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("films");
        modelAndView.addObject("film", film);
        return modelAndView;
    }
现在我们可以在页面上显示这个对象。films.jsp我们将编写代替 Hello World 的内容,并且此处将替换${film}与属性名称“”相对应的对象。film让我们尝试运行它,看看发生了什么(为了清楚地输出对象,Film重新定义了类toString()):
Знакомство с Maven, Spring, MySQL, Hibernate и первое CRUD приложение (часть 1) - 9

模型-视图-控制器

到了这个阶段,我们似乎已经拥有了一个成熟的 Spring MVC 应用程序。在继续之前,最好再次查看所有内容并弄清楚它是如何运作的。在网上你可以找到很多关于这方面的图片和图表,我喜欢这个:
Знакомство с Maven, Spring, MySQL, Hibernate и первое CRUD приложение (часть 1) - 10
当我们在浏览器行中编写一个请求时,它被接受Dispatcher Servlet,然后它会找到一个合适的控制器来处理这个请求HandlerMapping(这是一个用于选择控制器的接口,检查哪个可用的控制器有接受这样一个地址的方法) ,调用合适的方法并Controller返回有关视图的信息,然后调度程序使用ViewResolver'a 按名称找到所需的视图,之后将模型数据传输到此视图,我们将页面作为输出。像这样的东西。 待续... Maven、Spring、MySQL、Hibernate 简介和第一个 CRUD 应用程序(第 1 部分) Maven、Spring、MySQL、Hibernate 简介和第一个 CRUD 应用程序(第 2 部分) Maven、Spring、MySQL、Hibernate 简介和第一个 CRUD 应用程序(第 3 部分) Maven、Spring、MySQL、Hibernate 简介和第一个 CRUD 应用程序(第 4 部分)
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION