CodeGym /وبلاگ جاوا /Random-FA /ایجاد یک برنامه وب ساده با استفاده از servlet ها و JSP ها...
John Squirrels
مرحله
San Francisco

ایجاد یک برنامه وب ساده با استفاده از servlet ها و JSP ها (قسمت 1)

در گروه منتشر شد
دانش لازم برای درک مقاله: شما قبلاً کم و بیش Java Core را کشف کرده اید و می خواهید به فناوری های JavaEE و برنامه نویسی وب نگاه کنید . برای شما منطقی است که در حال حاضر در حال مطالعه جستجوی مجموعه های جاوا باشید که به موضوعات نزدیک به مقاله می پردازد.
ایجاد یک برنامه وب ساده با استفاده از servlet ها و JSP ها (قسمت 1) - 1
این مطالب ادامه منطقی مقاله من ایجاد ساده ترین پروژه وب در IntelliJ Idea Enterprise است . در آن مقاله، نحوه ایجاد یک الگوی پروژه وب کارآمد را نشان دادم. این بار به شما نشان خواهم داد که چگونه با استفاده از Java Servlet API و JavaServer Pages API یک برنامه وب ساده اما کاملاً جذاب ایجاد کنید . برنامه ما یک صفحه اصلی با دو پیوند خواهد داشت:
  • پیوند به یک صفحه برای افزودن کاربران؛
  • یک لینک به لیست کاربران
مانند قبل، من از IntelliJ Idea Enterprise Edition ، Apache Maven (فقط برخی از وابستگی ها را به هم متصل خواهیم کرد) و Apache Tomcat استفاده خواهم کرد . در پایان، ما برنامه خود را با استفاده از چارچوب W3.CSS "زیباسازی" خواهیم کرد . ما فرض می کنیم که شما قبلاً یک پروژه خالی دارید که اکنون به آن اضافه می کنیم. اگر نه، مقاله اول را اجرا کنید و یکی بسازید. فقط چند دقیقه طول میکشه :)

کمی در مورد ساختار برنامه آینده ما

صفحه اصلی ما (/) یک صفحه HTML ایستا معمولی با یک هدر و دو لینک/دکمه خواهد بود:
  • یک کاربر جدید اضافه کنید (به / افزودن هدایت می شود )؛
  • مشاهده لیست کاربران (به / لیست هدایت می شود ).
تامکت درخواست‌های این آدرس‌ها را دریافت می‌کند و آنها را به یکی از دو سروری که می‌خواهیم بسازیم ارسال می‌کند (مپینگ را در web.xml مشخص می‌کنیم ). سپس servlet ها درخواست ها را پردازش می کنند، داده ها را آماده می کنند (یا داده ها را ذخیره می کنند، اگر کاربر اضافه می کنیم)، و کنترل را به فایل های JSP مناسب منتقل می کنند ، که سپس نتیجه را "رندر" می کند. ما داده ها را در یک لیست وانیلی ساده (فهرست) ذخیره می کنیم.

یک صفحه اصلی ثابت ایجاد کنید

اگر index.jsp را در پوشه وب خود دارید، آن را حذف کنید. در عوض، یک فایل HTML ساده به نام index.html در این پوشه ایجاد کنید:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My super project!</title>
</head>
<body>
    <!-- header -->
    <div>
        <h1>Super app!<//h1>
    </div>

    <div>       <!-- content -->
        <div>    <!-- button holder -->
            <button onclick="location.href='/list'">List users<//button>
            <button onclick="location.href='/add'">Add user<//button>
        </div>
    </div>
</body>
</html>
اینجا هیچ چیز پیچیده ای نیست در تگ عنوان ، عنوان صفحه خود را نشان می دهیم. در بدنه صفحه، دو div اصلی داریم: header و content . بخش محتوا شامل یک نگهدارنده برای دکمه های ما است. و در آنجا دو دکمه داریم که با یک کلیک شما را به آدرس مربوطه می برد. شما می توانید پروژه را اجرا کنید و ببینید که اکنون چگونه به نظر می رسد. اگر روی دکمه ها کلیک کنید، صفحات خطای 404 را دریافت می کنید ، زیرا ما صفحات مربوطه هنوز وجود نداریم. اما می توان گفت که دکمه ها کار می کنند. توجه داشته باشید که این جهانی ترین رویکرد نیست: اگر جاوا اسکریپت در مرورگر خاموش باشد، این دکمه ها کار نخواهند کرد. اما ما فرض می کنیم که هیچ کس جاوا اسکریپت را غیرفعال نمی کند. :) بدیهی است که شما می توانید با لینک های ساده از پس آن بر بیایید، اما من دکمه ها را ترجیح می دهم. شما می توانید آن را هر طور که ترجیح می دهید انجام دهید. و نگران این واقعیت نباشید که نمونه های من دیوهای زیادی خواهند داشت . بعداً آنها را با استایل پر می کنیم و همه چیز زیباتر به نظر می رسد. :)

فایل های JSP را برای ارائه نتیجه ایجاد کنید

در همان فهرست وب ، یک پوشه ایجاد کنید که در آن فایل‌های JSP خود را اضافه می‌کنیم . من آن را " نماها " نامیدم، اما یک بار دیگر می توانید بداهه بداهه کنید. در این پوشه، دو فایل JSP ایجاد می کنیم:
  • add.jsp - صفحه ای برای افزودن کاربران؛
  • list.jsp - صفحه ای برای نمایش لیست کاربران.
هدرهای صفحه مناسب را به آنها اختصاص دهید. چیزی مانند « افزودن کاربر جدید » و « لیست کاربران »، و ما آن را به همین صورت رها می کنیم.

دو servlet ایجاد کنید

Servlets درخواست هایی را که Tomcat برای آنها ارسال می کند دریافت و پردازش می کند. در پوشه src/main/java ، بسته برنامه را ایجاد کنید ، جایی که کد منبع خود را قرار می دهیم. بسته های دیگر نیز به آنجا می روند. بنابراین، برای جلوگیری از ایجاد این بسته‌ها در داخل یکدیگر، مقداری کلاس در بسته برنامه ایجاد می‌کنیم (بعداً آن را حذف خواهیم کرد). اکنون سه بسته مختلف در بسته برنامه ایجاد کنید :
  • entities - موجودیت‌های ما (کلاسی که اشیاء کاربر را توصیف می‌کند) به اینجا می‌روند.
  • مدل - اینجا جایی است که مدل ما پیش می رود (در این مورد کمی بعد صحبت خواهیم کرد).
  • servlets - و اینجا جایی است که servlet های ما می روند.
پس از انجام این کار، می توانید با آرامش آن کلاس را از بسته برنامه حذف کنید (البته اگر آن را ایجاد کرده باشید). در بسته servlets دو کلاس ایجاد کنید:
  • AddServlet - درخواست های ارسال شده به / add را پردازش می کند .
  • ListServlet - درخواست های ارسال شده به / list را پردازش می کند .

اتصال وابستگی ها در Maven

Tomcat 9. * مشخصات Servlet 4.0 و JavaServer Pages 2.3 را پیاده سازی می کند . این همان چیزی است که در خط دوم پاراگراف اول مستندات رسمی Tomcat 9 بیان شده است. یعنی اگر شما هم مثل من از این نسخه Tomcat استفاده می کنید ، کدی که می نویسید و اجرا می کنید از این نسخه ها استفاده می کند. اما ما دوست داریم این مشخصات را در پروژه خود داشته باشیم تا کد ما که از آنها استفاده می کند حداقل با موفقیت کامپایل شود. و برای انجام این کار، باید آنها را در پروژه خود بارگذاری کنیم. اینجاست که Maven به کمک می آید.

قانون کلی این است: اگر نیاز دارید با استفاده از Maven چیزی را به پروژه خود متصل کنید:

  • به وب سایت مخزن از Maven بروید.
  • نسخه مورد نیاز کتابخانه مورد نیاز را پیدا کنید.
  • کد وابستگی را دریافت کنید که باید در pom.xml خود جایگذاری شود.
  • چسباندن :)
شروع کنیم. ابتدا فایل POM را آماده کنید . جایی بعد از ورودی /version ، اما قبل از /project ، موارد زیر را وارد کنید:
<dependencies>

</dependencies>
ما این کار را انجام می دهیم تا نشان دهیم که وابستگی های مورد نیاز را در این تگ ها فهرست می کنیم. اکنون به mvnrepository.com بروید . یک فیلد جستجو در بالا وجود دارد. برای شروع، " servlet " را جستجو کنید . اولین نتیجه که بیش از هفت هزار بار استفاده شده است برای ما مناسب است. به یاد داشته باشید، ما به نسخه 4.0 (برای Tomcat 9 ) نیاز داریم. نسخه‌های دیگر ممکن است برای پیاده‌سازی‌های قدیمی‌تر مناسب باشند. این یک نسخه نسبتاً جدید است، بنابراین کاربردهای زیادی وجود ندارد. اما ما به آن نیاز داریم. صفحه ای باز می شود که در آن می توانید کد این وابستگی را برای مدیران بسته های مختلف دریافت کنید یا به سادگی آن را دانلود کنید. اما از آنجایی که می خواهیم آن را با استفاده از Maven وصل کنیم، کد موجود در تب Maven را انتخاب می کنیم. ما در بخش وابستگی فایل POM خود کپی و جایگذاری می کنیم. اگر اعلانی دریافت کردید که از شما می‌پرسد آیا می‌خواهید وارد کردن خودکار را در گوشه سمت راست پایین IDEA فعال کنید ، ادامه دهید و با آن موافقت کنید. اگر تصادفاً امتناع کردید، به " تنظیمات " بروید و وارد کردن خودکار را به صورت دستی روشن کنید: تنظیمات (Ctrl + Alt + S) -> ساخت، اجرا، استقرار -> Maven -> واردات . این به شما امکان می دهد فایل POM و فایل های پیکربندی IDEA را برای این پروژه همگام نگه دارید. با پیروی از همین اصل، صفحات JavaServer 2.3 را پیدا کرده و به آن متصل خواهیم کرد (جستجوی "JSP"). و از آنجایی که ما قبلاً Maven را راه‌اندازی کرده‌ایم، اجازه دهید به آن بگوییم که فایل‌های منبع ما از نحو جاوا 8 پیروی می‌کنند و باید آنها را در بایت کد آن نسخه کامپایل کنیم. پس از تمام این مراحل، pom.xml ما چیزی شبیه به این خواهد شد:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         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>cc.codegym.info.fatfaggy</groupId>
    <artifactId>my-super-project</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compile.source>1.8</maven.compile.source>
        <maven.compile.target>1.8</maven.compile.target>
    </properties>

    <dependencies>
        <!-- Servlet API 4.0 for tomcat 9 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.0</version>
            <scope>provided</scope>
        </dependency>

        <!-- JavaServer Pages API 2.3 for tomcat 9 -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

</project>

سرولت های ما را به سرولت های واقعی تبدیل کنید

در حال حاضر، جفت servlet هایی که ایجاد کردیم در واقع کلاس های معمولی هستند. هیچ کارکردی ندارند اما اکنون Servlet API را به پروژه خود متصل کرده ایم و بر این اساس می توانیم از کلاس های آن استفاده کنیم. برای اینکه servlet های خود را واقعی کنیم، تنها کاری که باید انجام دهیم این است که آنها را به ارث بردن کلاس HttpServlet تبدیل کنیم .

نقشه برداری یا نشانه گذاری

حال خوب است که به نوعی به Tomcat بگوییم که درخواست‌های آدرس / add توسط AddServlet ما پردازش می‌شود و درخواست‌های آدرس / list توسط ListServlet رسیدگی می‌شود . این فرآیند نقشه برداری (نشانه گذاری) نامیده می شود. این کار در web.xml با استفاده از همان اصل انجام می شود:
  • برای شروع، servlet را توصیف کنید (نامی ارائه کنید و مسیر خود کلاس را مشخص کنید).
  • سپس این servlet را به یک آدرس خاص متصل کنید (نام servlet را که ما به آن دادیم مشخص کنید و آدرسی را که درخواست های آن باید به این سرورلت ارسال شود را مشخص کنید).
سرولت را توضیح دهید:
<servlet>
    <servlet-name>add</servlet-name>
    <servlet-class>app.servlets.AddServlet</servlet-class>
</servlet>
حالا آن را به آدرس زیر متصل کنید:
<servlet-mapping>
    <servlet-name>add</servlet-name>
    <url-pattern>/add</url-pattern>
</servlet-mapping>
همانطور که می بینید، servlet-name در هر دو مورد یکسان است. در نتیجه، تامکت می داند که اگر درخواستی برای /add دریافت شود، باید به app.servlets.AddServlet ارسال شود. ما همین کار را با سرور دوم انجام می دهیم. در پایان، web.xml ما تقریباً دارای محتوای زیر است:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         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"
         version="3.1">

    <!-- add servlet -->
    <servlet>
        <servlet-name>add</servlet-name>
        <servlet-class>app.servlets.AddServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>add</servlet-name>
        <url-pattern>/add</url-pattern>
    </servlet-mapping>

    <!-- list servlet -->
    <servlet>
        <servlet-name>list</servlet-name>
        <servlet-class>app.servlets.ListServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>list</servlet-name>
        <url-pattern>/list</url-pattern>
    </servlet-mapping>
</web-app>
به هر حال، ما نشانه گذاری برای صفحه اصلی (/) ایجاد نکردیم. واقعیت این است که ما در این مورد به آن نیاز نداریم. صفحه اصلی ما یک فایل HTML ساده است که فقط دو دکمه را نمایش می دهد. هیچ محتوای پویا ندارد، بنابراین ما نیازی به ایجاد یک servlet جداگانه برای درخواست‌های از / نداریم که کاری جز اجرای فوروارد به برخی از JSP (که همچنین باید ایجاد شود) انجام نمی‌دهد تا دو دکمه برای ما بکشد. ما به این نیاز نداریم یک صفحه ثابت برای ما مناسب است. وقتی تامکت درخواستی را دریافت می‌کند، بررسی می‌کند که آیا یک سرولت واحد وجود دارد که می‌تواند درخواست آن آدرس را پردازش کند، و سپس می‌بیند که این آدرس در واقع حاوی فایل HTML آماده‌ای است که آن را ارائه می‌کند. ما می‌توانیم برنامه‌مان را دوباره اجرا کنیم (سرور را راه‌اندازی مجدد کنیم یا آن را مجدداً راه‌اندازی کنیم - هر چیزی که شما ترجیح می‌دهید) و مطمئن شویم که صفحه اصلی رندر شده است، هیچ چیز خراب نشده است، و وقتی روی دکمه‌ها کلیک می‌کنیم، انتقال‌ها اتفاق می‌افتد (اگرچه دوباره با خطا مواجه می‌شویم). ضمناً، در حالی که قبلاً خطای 404 می‌گرفتیم، اکنون با خطای 405 مواجه می‌شویم. یعنی نگاشت کار می‌کرد و سرولت‌ها پیدا شدند، اما روش مناسبی برای رسیدگی به درخواست نداشتند.

انحراف کوتاه: "زیر کاپوت" چه اتفاقی می افتد؟

احتمالاً قبلاً به نحوه عملکرد برنامه ما در تامکت فکر کرده اید. در آنجا چه اتفاقی می افتد؟ و متد ()main کجاست؟ به محض اینکه در مرورگر خود به localhost:8080 بروید، مرورگر با استفاده از پروتکل HTTP درخواستی را به این آدرس ارسال می کند. امیدوارم قبلاً متوجه شده باشید که انواع مختلفی از درخواست ها وجود دارد و محبوب ترین آنها GET و POST هستند. هر درخواستی باید پاسخ داده شود. انتظار می رود درخواست GET پاسخ کد HTML آماده برای استفاده را دریافت کند که به مرورگر بازگردانده می شود. سپس مرورگر همه حروف زیبا، دکمه ها و فرم ها را جایگزین کد می کند. درخواست POST کمی جالب تر است، زیرا حاوی اطلاعاتی نیز می باشد. به عنوان مثال، فرض کنید در یک فرم ثبت نام یا ورود در یک وب سایت اطلاعات کاربری را وارد کرده و روی «ارسال» کلیک کنید. این باعث می شود که یک درخواست POST با اطلاعات شخصی شما به سرور ارسال شود. سرور این اطلاعات را دریافت می کند، آن را پردازش می کند و برخی از پاسخ ها را برمی گرداند (به عنوان مثال، یک صفحه HTML با نمایه شما). تفاوت اصلی بین آنها این است که درخواست های GET فقط برای بازیابی داده ها از سرور استفاده می شوند، در حالی که درخواست های POST حاوی برخی اطلاعات هستند (و داده های روی سرور می توانند تغییر کنند). به عنوان مثال، زمانی که عکس خود را در سرور آپلود می کنید، در یک درخواست POST به آنجا منتقل می شود و سرور آن را به پایگاه داده اضافه می کند، یعنی تغییری رخ می دهد. حالا به تامکت برگردیم. وقتی درخواستی از مشتری دریافت می کند، به آدرس نگاه می کند. بررسی می‌کند که آیا یک servlet مناسب برای پردازش درخواست‌های آن آدرس (یا یک منبع موجود که می‌تواند فوراً برگردانده شود) وجود دارد یا خیر. اگر چیزی برای بازگشت پیدا نکرد، به جای صفحه HTML با خطای 404 پاسخ می دهد. اما اگر سرولت مناسبی را پیدا کند که در آن آدرس "نشسته" باشد، سپس به نوع درخواست (GET، POST یا چیز دیگری) نگاه می کند و از سرورلت می پرسد که آیا متدی دارد که بتواند این نوع پرس و جو را انجام دهد. اگر servlet بگوید که نمی داند چگونه این نوع را مدیریت کند، Tomcat یک کد 405 را برمی گرداند. و این دقیقاً همان چیزی است که در پروژه ما اتفاق افتاد. اما اگر یک سرولت مناسب پیدا شود و روش مناسبی داشته باشد، Tomcat یک شی servlet ایجاد می کند و آن را روی یک موضوع جدید شروع می کند.(که به آن اجازه می دهد به تنهایی اجرا شود)، و تامکت به کار خود ادامه می دهد و درخواست ها را می پذیرد و ارسال می کند. علاوه بر این، Tomcat دو شیء دیگر ایجاد می کند: یک HttpServletRequest (که من به اختصار آن را "درخواست" می نامم)، و یک HttpServletResponse (که من آن را "پاسخ" می نامم). تمام داده های دریافتی از درخواست مشتری را در اولین شی قرار می دهد، بنابراین می توان همه آن داده ها را از آن استخراج کرد. و بعد از همه اینها، این دو شیء را به متد مناسب سرولتی که روی یک نخ مجزا راه اندازی شده بود، منتقل می کند. به محض اینکه servlet کار خود را تمام کرد و پاسخی آماده برای ارسال به مشتری داشت، پرچمی را به سمت تامکت تکان می‌دهد و می‌گوید "تمام شد. همه چیز آماده است". تامکت پاسخ را دریافت کرده و برای مشتری ارسال می کند. این به Tomcat اجازه می‌دهد تا درخواست‌ها را دریافت کند و پاسخ‌ها را بدون حواس‌پرتی ارسال کند، و تمام کار توسط servlet‌هایی که روی رشته‌های جداگانه اجرا می‌شوند انجام می‌شود. این بدان معناست که وقتی ما کد servlet را می نویسیم، تعیین می کنیم که چه کاری انجام شود. و شما می توانید متد ()main را در داخل خود تامکت در نظر بگیرید (بله، در جاوا نوشته شده است)، و زمانی که ما تامکت را "راه اندازی" می کنیم، متد main() شروع می شود. ایجاد یک برنامه وب ساده با استفاده از servlets و JSP (قسمت 1) - 2

از servlet ها برای گرفتن متدهای GET و ارسال پاسخ های بسیار ساده استفاده کنید

در حال حاضر، سرورهای ما هیچ روش مناسبی (GET) ندارند، بنابراین تامکت خطای 405 را برمی‌گرداند. بیایید آنها را ایجاد کنیم! کلاس HttpServlet، که سرورهای ما به ارث می برند، متدهای مختلفی را اعلام می کند. برای اختصاص کد خاصی به متدها، به سادگی آنها را لغو می کنیم. در این مورد، ما باید doGet()متد را در هر دو سرور رد کنیم.
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

}
همانطور که می بینید، این روش دو آرگومان می گیرد: req (درخواست) و resp (پاسخ). اینها همان اشیایی هستند که تامکت هنگام فراخوانی متد مناسب در سرورلت برای ما ایجاد و پر می کند. برای شروع، ما ساده ترین پاسخ ها را ایجاد می کنیم. برای این کار، شی resp را می گیریم و یک شی PrintWriter از آن می گیریم. این نوع شی برای نوشتن پاسخ استفاده می شود. ما از آن برای خروجی یک رشته ساده استفاده می کنیم.
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    PrintWriter writer = resp.getWriter();
    writer.println("GET method from AddServlet");
}
ما کاری مشابه را در ListServlet انجام خواهیم داد و سپس سرور خود را مجددا راه اندازی می کنیم. همانطور که می بینید، همه چیز کار می کند! وقتی روی دکمه ها کلیک می کنید، صفحاتی با متنی که ما با PrintWriter "نوشتیم" دریافت می کنید. اما فایل‌های JSP که برای تولید صفحات دارای پاسخ آماده کرده‌ایم، استفاده نمی‌شوند. این فقط به این دلیل است که آنها هرگز اعدام نمی شوند. servlet ما خود پاسخ را ایجاد می کند و کار را تمام می کند و به تامکت سیگنال می دهد که آماده پاسخگویی به مشتری است. Tomcat فقط پاسخ را می گیرد و آن را برای مشتری ارسال می کند. اجازه دهید کنترل را از servlet ها به فایل های JSP منتقل کنیم. ما کد متدهای خود را به صورت زیر تغییر می دهیم:
  • ما یک شیء ارسال کننده درخواست را از شی درخواست دریافت می کنیم و آدرس صفحه JSP را که می خواهیم کنترل را به آن منتقل کنیم، ارسال می کنیم.
  • ما از این شی برای انتقال کنترل به صفحه JSP مشخص شده استفاده می کنیم و فراموش نمی کنیم که اشیاء درخواست و پاسخی که از Tomcat دریافت کرده ایم را ارسال کنیم.
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/add.jsp");
    requestDispatcher.forward(req, resp);
}
در تگ بدنه صفحات JSP می توانید چیزی اضافه کنید تا به وضوح ببینیم کدام صفحه نمایش داده می شود. پس از انجام این کار، سرور را مجددا راه اندازی کنید و بررسی کنید. روی دکمه های صفحه اصلی کلیک می کنیم و صفحات باز می شوند، یعنی درخواست ها به سرورلت ها ارسال می شوند. سپس کنترل به صفحات JSP منتقل می شود که اکنون در حال ارائه هستند. فعلاً همین است. در قسمت بعدی این مقاله، ما روی عملکرد اپلیکیشن خود کار خواهیم کرد.
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION