Building a Login System in Java: JSP, Servlet and JDBC with MySQL
Building a Login System in Java: JSP, Servlet and JDBC with MySQL
Hello, in this tutorial we will build a complete login system using JSP, Servlets and JDBC, running on Apache Tomcat from Eclipse, with MySQL provided by XAMPP. By the end you will have a working app with registration, login, a session-based welcome page and logout.
Before the code, here is how the pieces fit together. JSP pages are what the user sees (the forms and messages). Servlets hold the logic (checking the login, saving a new user). JDBC is how Java talks to the MySQL database. If you have used a restaurant, JSP is the menu and the table, the servlet is the chef, and the database is the pantry.
What you need
- JDK installed
- Eclipse IDE for Enterprise Java and Web Developers
- Apache Tomcat 10 or above, registered in Eclipse
- XAMPP (it provides MySQL and phpMyAdmin)
- MySQL Connector/J (the JDBC driver, downloaded in Step 4)
Step 1: Create the database
Open the XAMPP Control Panel and click Start next to MySQL. Then open http://localhost/phpmyadmin, click New, name the database logindemo and click Create.
Now click on logindemo, open the SQL tab, and run this:
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
password VARCHAR(50) NOT NULL,
email VARCHAR(100)
);
INSERT INTO users (username, password, email)
VALUES ('admin', 'admin123', 'admin@test.com');The id column numbers each user automatically. The UNIQUE on username means two people cannot register with the same name, and we will use that later to detect duplicates. The INSERT adds a test user so we can log in right away. Click the users table and open Browse to confirm the admin row is there.
Step 2: Create the Dynamic Web Project
In Eclipse, go to File → New → Dynamic Web Project. Name it LoginDemo, select your Tomcat under Target Runtime, keep “Generate web.xml deployment descriptor” checked, and click Finish.
Depending on your Eclipse version, the web content folder is called either WebContent or src/main/webapp. Wherever this tutorial says WebContent, use whichever one you see in your project.
Step 3: Understand the folder structure
Here is where every file we create will live:
LoginDemo
├── src
│ ├── db
│ │ └── DBConnection.java
│ └── servlet
│ ├── LoginServlet.java
│ ├── RegisterServlet.java
│ └── LogoutServlet.java
└── WebContent
├── login.jsp
├── register.jsp
├── welcome.jsp
└── WEB-INF
├── lib
│ └── mysql-connector-j-8.x.x.jar
└── web.xmlStep 4: Add the MySQL JDBC driver
Java cannot talk to MySQL on its own, so we need the driver. Go to dev.mysql.com/downloads/connector/j, choose “Platform Independent”, and download the ZIP archive. Extract it and find the file mysql-connector-j-8.x.x.jar.
Now do two things, and both are required:
- Drag the JAR into
WebContent/WEB-INF/libin Eclipse. - Right-click the project → Build Path → Configure Build Path → Libraries → Add JARs, and select the JAR from
WebContent/WEB-INF/lib.
Expand “Referenced Libraries” in the Project Explorer and check that the JAR is listed. If you skip either step, you will get a ClassNotFoundException for the driver.
Step 5: The database connection class
Right-click src → New → Package, name it db. Then right-click the package → New → Class, and name it DBConnection.
package db;
import java.sql.Connection;
import java.sql.DriverManager;
public class DBConnection {
public static Connection getConnection() {
Connection con = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
con = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/logindemo?useSSL=false&serverTimezone=UTC",
"root",
""
);
} catch (ClassNotFoundException e) {
System.out.println("MySQL JDBC Driver not found!");
e.printStackTrace();
} catch (Exception e) {
System.out.println("Connection failed!");
e.printStackTrace();
}
return con;
}
}We keep the connection code in one place so every servlet can reuse it. Class.forName loads the driver, and DriverManager.getConnection opens the connection. The URL has three useful parts: localhost:3306 is where MySQL runs, logindemo is our database, and root with a blank password is XAMPP’s default login. If you changed the MySQL password, update it here.
The class name is DBConnection with a capital D and B. Java is case-sensitive, and spelling it DbConnection anywhere else causes a NoClassDefFoundError at runtime.
To test the connection, temporarily add this method inside the class:
public static void main(String[] args) {
Connection con = getConnection();
System.out.println(con != null ? "Connected successfully!" : "Connection failed.");
}Right-click the file → Run As → Java Application. When you see “Connected successfully!”, delete this method, because it is not part of the web app.
Step 6: The login page
Right-click WebContent → New → JSP File, and name it login.jsp.
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>Login Page</title>
</head>
<body>
<h2>Login</h2>
<form action="LoginServlet" method="post">
Username: <input type="text" name="username" required/><br/><br/>
Password: <input type="password" name="password" required/><br/><br/>
<input type="submit" value="Login"/>
</form>
<p>New user? <a href="register.jsp">Register here</a></p>
<% if(request.getAttribute("error") != null) { %>
<p style="color:red;"><%= request.getAttribute("error") %></p>
<% } %>
</body>
</html>The form sends its data to LoginServlet. We use method="post" so the password does not appear in the URL. The name attributes (username, password) must match exactly what the servlet reads later. The last block shows an error message in red, but only when the servlet has set one.
Step 7: The registration page
Create register.jsp in the same way:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>Register Page</title>
</head>
<body>
<h2>Register</h2>
<form action="RegisterServlet" method="post">
Username: <input type="text" name="username" required/><br/><br/>
Password: <input type="password" name="password" required/><br/><br/>
Email: <input type="email" name="email" required/><br/><br/>
<input type="submit" value="Register"/>
</form>
<p>Already have an account? <a href="login.jsp">Login here</a></p>
</body>
</html>This is the same idea as the login form, with one extra field for the email. It posts to RegisterServlet.
Step 8: The welcome page
Create welcome.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>Welcome</title>
</head>
<body>
<%
if (session.getAttribute("user") == null) {
response.sendRedirect("login.jsp");
}
%>
<h2>Welcome, <%= session.getAttribute("user") %>!</h2>
<a href="LogoutServlet">Logout</a>
</body>
</html>This page checks the session first. If nobody is logged in, session.getAttribute("user") is null and the visitor is sent back to the login page. Otherwise it greets the user by name and shows a logout link.
Step 9: The login servlet
Right-click src → New → Servlet. Use the package servlet and the class name LoginServlet, keep the mapping as /LoginServlet, and tick only doPost.
package servlet;
import java.io.IOException;
import java.sql.*;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.*;
import db.DBConnection;
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
Connection con = DBConnection.getConnection();
String query = "SELECT * FROM users WHERE username=? AND password=?";
try {
PreparedStatement ps = con.prepareStatement(query);
ps.setString(1, username);
ps.setString(2, password);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
HttpSession session = request.getSession();
session.setAttribute("user", username);
response.sendRedirect("welcome.jsp");
} else {
request.setAttribute("error", "Invalid username or password");
request.getRequestDispatcher("login.jsp").forward(request, response);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}Let’s go through it. The imports start with jakarta.servlet, which is right for Tomcat 10 and above. On Tomcat 9 or older, use javax.servlet instead, and never mix the two.
We read the username and password from the form, open a connection, and run a SELECT using a PreparedStatement. The ? placeholders are filled in by setString, which protects us from SQL injection. Never build a query by joining raw strings. Also note that prepareStatement is called on the connection (con.prepareStatement), not on its own.
If rs.next() finds a matching row, the login is valid. We create a session, store the username in it, and redirect to the welcome page. If not, we set an error message and forward back to the login page.
These two ways of moving to another page behave differently:
sendRedirect (used on success) | forward (used on failure) | |
|---|---|---|
| Browser URL | Changes | Stays the same |
| New request from browser? | Yes | No |
| Why we use it here | Clean URL, no resubmission on refresh | Keeps the error message with the request |
Step 10: The registration servlet
Create another servlet with the package servlet, the class name RegisterServlet, the mapping /RegisterServlet, and only doPost ticked.
package servlet;
import java.io.IOException;
import java.sql.*;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.*;
import db.DBConnection;
@WebServlet("/RegisterServlet")
public class RegisterServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
String email = request.getParameter("email");
Connection con = DBConnection.getConnection();
String query = "INSERT INTO users (username, password, email) VALUES (?, ?, ?)";
try {
PreparedStatement ps = con.prepareStatement(query);
ps.setString(1, username);
ps.setString(2, password);
ps.setString(3, email);
ps.executeUpdate();
response.sendRedirect("login.jsp");
} catch (SQLException e) {
e.printStackTrace();
request.setAttribute("error", "Registration failed. Username may already exist.");
request.getRequestDispatcher("register.jsp").forward(request, response);
}
}
}This one inserts a new row. We use executeUpdate() for INSERT, UPDATE and DELETE, and executeQuery() for SELECT. Because username is UNIQUE in the table, a duplicate username throws an SQLException, which we catch and show as a friendly message on the registration page.
Step 11: The logout servlet
Create a servlet with the class name LogoutServlet and the mapping /LogoutServlet. This time tick only doGet, because the logout link is a plain <a href>, which sends a GET request.
package servlet;
import java.io.IOException;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.*;
@WebServlet("/LogoutServlet")
public class LogoutServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession(false);
if (session != null) session.invalidate();
response.sendRedirect("login.jsp");
}
}getSession(false) returns the existing session without creating a new one. If a session exists, invalidate() destroys it, so the user must log in again to see the welcome page.
Step 12: Run and test
Right-click the project → Run As → Run on Server, select Tomcat, and click Finish. Open Chrome or Firefox and visit:
http://localhost:8080/LoginDemo/login.jsp
Comments
Post a Comment