I understand a servlet has URL mappings so that when a URL is
requested, the associated servlet takes the request, processes it and
possibly forwards to a JSP.
Correct but remember that only the doGet method is accessible directly. (i.e. you can run the doGet method of a servlet by typing it into the browser)
When I request the URL ending with ".../Login" I want to display a
form with username and password fields and a Login button.
You can use the doGet method of the Login servlet to forward to the jsp:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
RequestDispatcher rd = request.getRequestDispatcher("login.jsp");
rd.forward(request, response);
}
So you can now either access the login page form either directly /login.jsp or via the doGet method of our Login Servlet /Login
For example you could have a link somewhere like this:
<a href="/Login">Login</a>
My question is do I need 2 URLs for this operation, one of which would
be ".../Login" and the other ".../Login/Result" for instance, and when
the button is clicked, a post request would be sent to the second one?
In that case I would need two servlets. The first one would simply
forward to the JSP which contains the form, and that form would have:
No, that would be over complicating it and would make your application harder to manage. You can use the same Login Servlet to both redirect the user to the login page (doGet) and handle the results (doPost).
When the button is clicked, I want a success or failure page to be displayed.
Instead of having a failure jsp, why not just keep it on the login page? If a user types in their password incorrectly by mistake more than once, it would be annoying for them to keep having to go back to the login page no? What most websites do is that they will show the error message on the login page itself, so they can easily just type their details in again without having to click back. And you don't need a dedicated success jsp, the success page would just be the dashboard/homepage/welcomepage.
Here's a nice example of the above:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//get the parameters submitted by the form
String user_name = request.getParameter("username");
String user_pass = request.getParameter("password");
String url = ""; //Create a string literal that we will modify based on if the details are correct or not.
UserDao udao = new UserDao(); //class containing all the database methods pertaining to the user table.
if(udao.isValid(user_name, user_pass)){ //UserDao has a method called isValid which returns a boolean.
//details are valid so forward to success page
url = "welcome.jsp"; //set the url welcome.jsp because the details are correct.
//here you set your session variables and do whatever else you want to do
HttpSession session = (request.getSession());
session.setAttribute("username", user_name); // i can access this variable now in any jsp with: ${username}
}else{
//details are not valid so lets forward them back to the login page with an error message
String error = "Username or password is incorrect!";
request.setAttribute("error", error);
url = "login.jsp"; //set the url login.jsp because the details are incorrect.
}
RequestDispatcher rd = request.getRequestDispatcher(url); //the url we set based on if details are correct or not
rd.forward(request, response);
}
Your jsp might look something like this:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<jsp:include flush="true" page="includes/header.jsp"></jsp:include>
<form action="../Login" method="post">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit" value="Submit">
</form>
<!-- you can handle the error here also -->
<h1>${error}</h1>
<jsp:include flush="true" page="includes/footer.jsp"></jsp:include>
The isValid method inside the UserDao class would look something like this:
public boolean isValid(String username, String userpass){
boolean status = false;
PreparedStatement pst = null;
ResultSet rs = null;
try(Connection conn= DBConnection.getConnection()){
pst = conn.prepareStatement("select * from user where username=? and userpass=?;");
pst.setString(1, username);
pst.setString(2, userpass);
rs = pst.executeQuery();
status = rs.next();
} catch (SQLException e) {
e.printStackTrace();
}
return status;
}
Hope that helps understand it better, if you have any questions feel free to ask.
Note: one of the answers uses scriptlets in their jsp (those <% %> things) . This is highly discouraged! If you want to start on a good path do not use scriptlets! More info on why here:
How to avoid Java code in JSP files?