في هذا الدليل التعليمي لـ Spring MVC، سنتعلم كيفية تطوير تطبيقات الويب باستخدام Spring Tool Suite. يُستخدم إطار عمل Spring MVC على نطاق واسع لـ
تطبيقات الويب جافا.
تمامًا مثل إطار عمل Struts، يعتمد Spring MVC أيضًا على تقنيات Servlet و JSP لـ Java EE وينفذ نمط تصميم النموذج–العرض–التحكم.
دليل تعليمي لـ Spring MVC
لقد رأينا سابقًا كيف يعمل حقن الاعتماد في Spring وفي هذا البرنامج التعليمي سنتعلم كيفية إنشاء تطبيق ويب بسيط باستخدام إطار عمل Spring MVC. يمكننا استخدام بيئة تطوير متكاملة مثل Eclipse أو IntelliJ لتطوير مشاريع Spring ، ولكن شركة SpringSource توفر بيئة تطوير مستندة إلى Eclipse تسمى Spring Tool Suite (STS) والتي تأتي مع خادم VMware vFabric tc المدمج الذي يعتمد على حاوية Apache Tomcat ومحسّن لتطبيقات Spring. سأستخدم STS لبرنامج تعليمي عن Spring MVC وبرامج تعليمية أخرى في المستقبل ، لأنه يسهل حياة المطور عن طريق توفير الميزات التالية:
- دعم إنشاء تطبيقات Spring الأساسية (MVC ، Rest ، Batch وما إلى ذلك) ، وهذا مفيد للبدء في المشروع من البداية. سنرى قريبًا في هذا البرنامج التعليمي عن Spring MVC مدى سهولة إنشاء مشروع Spring MVC.
- يوفر ميزات مفيدة مثل إنشاء ملفات تكوين Spring ، وتحليل ملفات التكوين والفئات لتوفير معلومات مفيدة حولها.
- التحقق التلقائي من صحة تطبيق Spring
- دعم إعادة تنظيم المشروع بسهولة ، حيث يتم انعكاس التغييرات في ملفات التكوين أيضًا.
- مساعدة في الكود ليس فقط للفئات ولكن أيضًا لملفات التكوين ، أحب هذه الميزة كثيرًا لأننا في معظم الأحيان نحتاج إلى معرفة ما يمكننا استخدامه وتفاصيله.
- أفضل دعم للبرمجة الموجهة نحو الجوانب (AOP) من خلال تكامل AspectJ.
نظرًا لجميع الميزات التي يقدمها STS، تم بيعي لها وقررت استخدامها في تطبيق Spring، وحتى الآن أنا سعيد جدًا بها. قم بتنزيل STS من صفحة التنزيل الرسمية لـ STS وقم بتثبيته. أنا استخدم STS 3.4.0.RELEASE الذي يستند إلى إصدار Eclipse 4.3.1. إذا كنت لا ترغب في استخدام STS وترغب في الحصول على مزاياه في Eclipse الحالي، فيجب عليك تثبيت الإضافة الخاصة به من متجر Eclipse. استخدم الصورة أدناه كمرجع وتأكد من اختيار الإصدار الصحيح لتثبيت STS. الإضافة أدناه مفيدة لـ Eclipse Kepler.
إذا كنت لا ترغب في استخدام خادم SpringSource، يمكنك نشر التطبيق في أي حاوية Java EE أخرى مثل Tomcat أو JBoss وما إلى ذلك. في هذا الدليل التعليمي، سأستخدم الخادم الذي يأتي مع STS، ولكنني قد قمت بفحص التطبيق عن طريق تصديره كملف WAR إلى خادم Tomcat منفصل وكان يعمل بشكل جيد. الآن بمجرد أن بيئة الخادم والبيئة التطويرية جاهزة، دعونا نقم بإنشاء مشروعنا الأول باستخدام Spring MVC. الخطوات أدناه صالحة لكل من STS و Eclipse مع إضافات STS.
إنشاء تطبيق Spring MVC في STS أو Eclipse
الخطوة 1: قم بإنشاء مشروع جديد باستخدام الربيع من القائمة. الخطوة 2: في نافذة المشروع الجديد، قم بإعطاء اسم “SpringMVCExample” واختر القالب “مشروع Spring MVC”. إذا كنت تستخدم هذا القالب للمرة الأولى، فستقوم STS بتنزيله من موقع SpringSource. إذا كنت ترغب، يمكنك إضافة المشروع إلى أي مجموعة عمل.
الخطوة 3: عندما يتم تنزيل القالب، في الشاشة التالية تحتاج إلى تقديم اسم الحزمة على المستوى العلوي. ستستخدم هذه الحزمة كحزمة أساسية لمكونات Spring.
الخطوة 4: بمجرد إنشاء المشروع باستخدام قالب Spring MVC، سيبدو كما في الصورة أدناه.
لا تقلق إذا لم تر User.java class أو login.jsp وملفات user.jsp، فقد تمت إضافتها من قبلي لاحقًا. إذا لم يتم تجميع المشروع الخاص بك ورأيت بعض الأخطاء، قم بتشغيل Maven/Update Project. تأكد من تحديد خيارات “تحديث إجباري للصور الفورية/الإصدارات”، راجع الصورة أدناه.
يبدو المشروع العام مثل أي تطبيق ويب يعتمد على Maven مع بعض ملفات تكوين Spring. الآن حان الوقت لتحليل الأجزاء المختلفة من المشاريع وتوسيعها قليلاً.
تبعيات Spring MVC
يبدو ملف pom.xml الذي أنشأناه كما يلي.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.journaldev</groupId>
<artifactId>SpringMVCExample</artifactId>
<name>SpringMVCExample</name>
<packaging>war</packaging>
<version>1.0.0-BUILD-SNAPSHOT</version>
<properties>
<java-version>1.6</java-version>
<org.springframework-version>4.0.0.RELEASE</org.springframework-version>
<org.aspectj-version>1.7.4</org.aspectj-version>
<org.slf4j-version>1.7.5</org.slf4j-version>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>
<!-- @Inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<additionalProjectnatures>
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
</additionalProjectnatures>
<additionalBuildcommands>
<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
</additionalBuildcommands>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>org.test.int1.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
ستكون artifactId سياق الخادم لتطبيق الويب، لذا يمكنك تغييره إذا أردت شيئًا آخر. هناك عدد قليل من الخصائص المحددة لإطار Spring، وAspectJ، وإصدارات SLF4j، وجدت أنها لم تعكس أحدث الإصدارات، لذا قمت بتغييرها إلى أحدث إصدار مستقر حتى الآن. تعتبر تبعيات المشروع التي أهتم بها هي؛
- spring-context: تبعية النواة لـ Spring. لاحظ استبعاد تسجيلات Commons لصالح SLF4J.
- spring-webmvc: فناجين Spring لدعم MVC
- aspectjrt: مرجع API لـ AspectJ
- SLF4J و Log4j: لأغراض التسجيل، Spring من السهل جدًا تكوينه لـ log4j أو واجهة برمجة التطبيقات للتسجيل في Java بسبب تكامل SLF4J.
- javax.inject – واجهة JSR330 API لحقن التبعيات
هناك بعض التبعيات الأخرى المضافة، مثل Servlet و JSP و JSTL و JUnit API ولكن بالنسبة لتطبيق البداية، يمكننا تجاهلها.
برنامج تعليمي حول Spring MVC – تكوين Log4j
يبدو ملف log4j.xml الذي تم إنشاؤه كما يلي.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="https://jakarta.apache.org/log4j/">
<!-- Appenders -->
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p: %c - %m%n" />
</layout>
</appender>
<!-- Application Loggers -->
<logger name="com.journaldev.spring">
<level value="info" />
</logger>
<!-- 3rdparty Loggers -->
<logger name="org.springframework.core">
<level value="info" />
</logger>
<logger name="org.springframework.beans">
<level value="info" />
</logger>
<logger name="org.springframework.context">
<level value="info" />
</logger>
<logger name="org.springframework.web">
<level value="info" />
</logger>
<!-- Root Logger -->
<root>
<priority value="warn" />
<appender-ref ref="console" />
</root>
</log4j:configuration>
لاحظ أنه يتم طباعة كل شيء على وحدة التحكم، يمكننا بسهولة إضافة مراقبين لتوجيه تسجيل البيانات إلى ملفات.
برنامج تعليمي حول Spring MVC – تكوين وصف النشر
دعنا نرى ملف web.xml الخاص بنا ونحلله.
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="https://java.sun.com/xml/ns/javaee"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
ContextLoaderListener
يربط دورة حياة ApplicationContext
بدورة حياة ServletContext
ويقوم بتلقائياً بإنشاء ApplicationContext
. ApplicationContext
هو المكان للحاصلين من Spring ويمكننا توفير تكوينه من خلال المعلمة contextConfigLocation . يوفر ملف root-context.xml تفاصيل التكوين لـ WebApplicationContext. DispatcherServlet
هو فئة المتحكم لتطبيق Spring MVC ويتم التعامل مع جميع طلبات العميل من خلال هذا السيرفلت. يتم تحميل التكوين من ملف servlet-context.xml.
برنامج تعليمي عن Spring MVC – ملفات التكوين
ملف root-context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
</beans>
يمكننا تعريف البنود المشتركة هنا، حاليًا ليس هناك شيء فيه. كود ملف servlet-context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="https://www.springframework.org/schema/mvc"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="https://www.springframework.org/schema/beans"
xmlns:context="https://www.springframework.org/schema/context"
xsi:schemaLocation="https://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.journaldev.spring" />
</beans:beans>
هكذا يبدو الملف القياسي لتكوين Spring، فقط تخيل كتابة كل هذا بنفسك وستبدأ في الإعجاب بأداة STS. تُستخدم عنصر annotation-driven لإبلاغ سيرفلت المحاكي بأن التعليمات ستُستخدم لتكوين البنود. عنصر resources يحدد الموقع الذي يمكننا وضع الملفات الثابتة مثل الصور وصفحات HTML وما إلى ذلك التي لا نريد الحصول عليها من خلال إطار Spring. InternalResourceViewResolver
هو مُحلل العرض، يمكننا توفير موقع صفحات العرض من خلال خصائص البادئة واللاحقة. لذا يجب أن تكون جميع صفحات الـ JSP في دليل /WEB-INF/views/. يُستخدم عنصر context:component-scan لتوفير موقع الحزمة الأساسية لفحص فئات السيرفلت. تذكر قيمة الحزمة الرئيسية المعطاة في وقت إنشاء المشروع، إنها نفس القيمة المستخدمة هنا.
فئة تحكم Spring MVC
تم إنشاء الصف الرئيسي (HomeController) تلقائيًا مع طريقة home()، على الرغم من أنني قمت بتوسيعه قليلاً عن طريق إضافة طرق loginPage() و login(). تُستخدم تعليقة
package com.journaldev.spring;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* Handles requests for the application home page.
*/
@Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
/**
* Simply selects the home view to render by returning its name.
*/
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.info("Welcome home! The client locale is {}.", locale);
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
return "home";
}
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String loginPage(Locale locale, Model model) {
return "login";
}
@RequestMapping(value = "/home", method = RequestMethod.POST)
public String login(@Validated User user, Model model) {
model.addAttribute("userName", user.getUserName());
return "user";
}
}
@Controller للإشارة إلى أنها صف تحكم ويب. يُستخدم تعليقة @RequestMapping مع الصفوف والأساليب لتوجيه طلب العميل إلى طريقة المعالجة المحددة. لاحظ أن طرق المعالجة تعيد سلسلة نصية، ويجب أن يكون اسم صفحة المشاهدة المستخدمة كاستجابة. كما يمكن رؤية أن لدينا ثلاثة طرق تعيد سلاسل نصية مختلفة، لذا يجب علينا إنشاء صفحات JSP بنفس الاسم. لاحظ أن طريقة login() ستتم استدعاؤها باستخدام HTTP الطريقة POST، لذا نتوقع بعض بيانات النموذج هنا. لذا لدينا نموذج User وتم تحديده للتحقق باستخدام تعليقة @Validated. يحتوي كل طريقة على Model كوسيط ويمكننا تعيين السمات لاستخدامها لاحقًا في صفحات استجابة JSP.
نماذج Spring MVC
تُستخدم النماذج لاحتواء متغيرات النموذج، يبدو نموذج المستخدم (User) لدينا كما يلي.
package com.journaldev.spring;
public class User {
private String userName;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
A simple java bean with the variable name and its getter and setter methods.
دروس Spring MVC – صفحات المشاهدة
لدينا ثلاث صفحات JSP مثلما يلي. كود home.jsp:
<%@ taglib uri="https://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
<title>Home</title>
</head>
<body>
<h1>
Hello world!
</h1>
<P> The time on the server is ${serverTime}. </P>
</body>
</html>
لاحظ استخدام لغة تعبير JSP للحصول على قيم السمات. كود login.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Login Page</title>
</head>
<body>
<form action="home" method="post">
<input type="text" name="userName"><br>
<input type="submit" value="Login">
</form>
</body>
</html>
A simple JSP page for the user to provide the userName as input. Notice that form variable name is same as User class variable name. Also, form action is “home” and method is “post”. It’s clear that HomeController login() method will handle this request. user.jsp code:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>User Home Page</title>
</head>
<body>
<h3>Hi ${userName}</h3>
</body>
</html>
صفحة رئيسية بسيطة للمستخدم حيث يتم عرض اسم المستخدم، لاحظ أننا نقوم بتعيين هذه السمة في طريقة الدخول.
تجربة تطبيق Spring MVC
تطبيقنا جاهز للتنفيذ، قم بتشغيله على خادم VMware tc أو أي خادم خدمة طلب سيرفلت آخر تفضل به، ستحصل على الصفحات التالية كاستجابة.
هذا كل شيء بالنسبة لدورة تعليم Spring MVC، يمكنك أن ترى مدى سهولة إنشاء تطبيق Spring MVC باستخدام إضافات STS. حجم الشيفرة قليل جدًا ومعظم التكوين يتم من خلال Spring MVC بحيث يمكننا التركيز على منطق الأعمال. قم بتنزيل مشروع Spring MVC التوضيحي من الرابط أدناه وقم بتجربته.
Source:
https://www.digitalocean.com/community/tutorials/spring-mvc-tutorial