We are going to use Thymeleaf templates for our View layer. Thymeleaf offers facelets style templating mechanism. Basically we need 2 layout templates, one for unauthorized views like Login/ForgotPassword etc and another for authorized users.
Setup AdminLTE Theme Resources
We are going to start with basic template and include what is necessary instead of dumping everything that comes with the theme.- Copy AdminLTE-2.3.0/bootstrap into jcart-admin/src/main/resources/static/assets folder.
- Copy AdminLTE-2.3.0/dist into jcart-admin/src/main/resources/static/assets folder. You can keep dist/js/app.min.js and delete rest of the files from js directory.
- Copy AdminLTE-2.3.0/plugins/jQuery into jcart-admin/src/main/resources/static/assets/plugins folder.
Note: I don't want to dump all the HTML content along with CSS styles on this post itself. Instead I will put only the key parts of the HTML content and give a link to the complete file on GitHub repository https://github.com/sivaprasadreddy/jcart.
GuestLayout Template
Create the guest layout thymeleaf template jcart-admin/src/main/resources/templates/layout/guestLayout.html as follows:<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="utf-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <title layout:title-pattern="$DECORATOR_TITLE - $CONTENT_TITLE">JCart Admin</title> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"/> <link rel="stylesheet" th:href="@{/assets/bootstrap/css/bootstrap.min.css}"/> <link rel="stylesheet" th:href="@{https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css}"/> <link rel="stylesheet" th:href="@{https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css}"/> <link rel="stylesheet" th:href="@{/assets/dist/css/AdminLTE.min.css}"/> </head> <body> <div layout:fragment="content"> <!-- Your Page Content Here --> </div> <script th:src="@{'/assets/plugins/jQuery/jQuery-2.1.4.min.js'}"></script> <script th:src="@{'/assets/bootstrap/js/bootstrap.min.js'}"></script> </body> </html>This is guest layout skeleton page. Observe the place holder <div layout:fragment="content"> ... </div> for the content to be dynamically included at runtime.
Login Page
Create login view page jcart-admin/src/main/resources/templates/public/login.html<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" layout:decorator="layout/guestLayout"> <head> <title>Log in</title> </head> <body> <div layout:fragment="content"> <form action="home" th:action="@{/login}" method="post"> <p><input type="email" class="form-control" name="username" placeholder="Email"/></p> <p><input type="password" class="form-control" name="password" placeholder="Password"/></p> <p><button type="submit" class="btn btn-primary btn-block btn-flat" th:text="#{label.login}">LogIn</button></p> <div th:if="${param.error}"> <p><span th:text="#{error.login_failed}">Invalid Email and Password.</span></p> </div> <div th:if="${param.logout}"> <p><span th:text="#{info.logout_success}">You have been logged out.</span></p> </div> <div th:if="${msg!=null}"> <p><span th:text="${msg}"></span></p> </div> </form> <a href="forgotPwd" th:href="@{/forgotPwd}" th:text="#{label.forgot_password}">I forgot my password</a><br/> </div> </body> </html>
Things to observe here:
Using ResourceBundles for Internationalization (I18N)
Create the default ResourceBundle jcart-admin/src/main/resources/messages.properties. For now we are supporting only English Locale.label.jcart_admin=JCart Admin label.email=Email label.password=Password label.login=Login label.submit=Submit label.forgot_password=I forgot my password info.logout_success=You have been logged out error.login_failed=Invalid Email and PasswordNow create JCartAdminApplication.java which is starting point for our Administration application.
package com.sivalabs.jcart;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class JCartAdminApplication
{
public static void main(String[] args)
{
SpringApplication.run(JCartAdminApplication.class, args);
}
}
WebMVC Configuration
Create a Spring WebMVC Configuration class to configure things like ViewControllers, Interceptors etc.@Configuration public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { super.addViewControllers(registry); registry.addViewController("/login").setViewName("public/login"); registry.addRedirectViewController("/", "/home"); } }Now we can run JCartAdminApplication as a Java Application and point your browser to http://localhost:8080/login
Authorized Users Layout
Create the main layout thymeleaf template jcart-admin/src/main/resources/templates/layout/mainLayout.html as follows:<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="utf-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <title layout:title-pattern="$DECORATOR_TITLE - $CONTENT_TITLE">JCart Admin</title> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"/> <link rel="stylesheet" th:href="@{/assets/bootstrap/css/bootstrap.min.css}"/> <link rel="stylesheet" th:href="@{https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css}"/> <link rel="stylesheet" th:href="@{https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css}"/> <link rel="stylesheet" th:href="@{/assets/dist/css/AdminLTE.min.css}"/> <link rel="stylesheet" th:href="@{/assets/dist/css/skins/skin-blue.min.css}"/> </head> <body> <div class="wrapper"> <!-- Main Header --> <header class="main-header"> <!-- Logo --> <a href="#" th:href="@{/home}" class="logo"> ... </a> <!-- Header Navbar --> <nav class="navbar navbar-static-top" role="navigation"> ... </nav> </header> <!-- Left side column. contains the logo and sidebar --> <aside class="main-sidebar"> <!-- sidebar: style can be found in sidebar.less --> <section class="sidebar"> <!-- Sidebar user panel (optional) --> <div class="user-panel"> ... </div> <!-- Sidebar Menu --> <ul class="sidebar-menu"> <li><a href="#" th:href="@{'/home'}"><i class="fa fa-home"></i> <span>Home</span></a></li> <li><a href="#" th:href="@{'/categories'}"><i class="fa fa-folder-open"></i> <span>Categories</span></a></li> <li><a href="#" th:href="@{'/products'}"><i class="fa fa-file"></i> <span>Products</span></a></li> <li><a href="#" th:href="@{'/orders'}"><i class="fa fa-cart-arrow-down"></i> <span>Orders</span></a></li> <li><a href="#" th:href="@{'/customers'}"><i class="fa fa-smile-o"></i> <span>Customers</span></a></li> <li><a href="#" th:href="@{'/users'}"><i class="fa fa-users"></i> Users</a></li> <li><a href="#" th:href="@{'/roles'}"><i class="fa fa-user"></i> Roles</a></li> <li><a href="#" th:href="@{'/permissions'}"><i class="fa fa-shield"></i> Permissions</a></li> </ul> </section> </aside> <!-- Content Wrapper. Contains page content --> <div class="content-wrapper"> <!-- Content Header (Page header) --> <div layout:fragment="pageHeader"> <section class="content-header"> <h1>Header Title</h1> </section> </div> <!-- Main content --> <section class="content"> <div layout:fragment="content"> <!-- Your Page Content Here --> </div> </section> </div> <!-- Main Footer --> <footer class="main-footer"> ... </footer> </div> <script th:src="@{'/assets/plugins/jQuery/jQuery-2.1.4.min.js'}"></script> <script th:src="@{'/assets/bootstrap/js/bootstrap.min.js'}"></script> <script th:src="@{'/assets/dist/js/app.min.js'}"></script> </body> </html>
Create Home page thymeleaf view jcart-admin/src/main/resources/templates/home.html as follows:
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" layout:decorator="layout/mainLayout"> <head> <title>Home</title> </head> <body> <div layout:fragment="pageHeader"> <section class="content-header"> <h1> JCart Administration <small>Manage JCart Site Content</small> </h1> </section> </div> <div layout:fragment="content"> <p>Welcome User!</p> </div> </body> </html>
Create a simple controller to display Home page.
@Controller public class HomeController { @RequestMapping("/home") public String home(Model model) { return "home"; } }Now you can run JCartAdminApplication as a Java Application and point your browser to http://localhost:8080/home.
ResourceBundle for Hibernate Validation Errors
If you observe the JPA entities, we are using Hibernate Validation annotations for some of our Entity fields. SpringMVC has support for JSR-303 Bean Validation API. But by default Hibernate Validation looks for ValidationMessages.properties file in root classpath for failure message keys. If you want to use messages.properties for both I18N and Hibernate Validation error messages you can register the Validator Bean as follows:@Configuration public class WebConfig extends WebMvcConfigurerAdapter { ... ... @Autowired private MessageSource messageSource; @Override public Validator getValidator() { LocalValidatorFactoryBean factory = new LocalValidatorFactoryBean(); factory.setValidationMessageSource(messageSource); return factory; } }
Now we have the layout templates ready and basic MVC configuration is in place. Next we will look into how to configure Spring Security.
No comments:
Post a Comment