Thymeleaf decorator (#747)
* Expression-Based Access Control PermitAll, hasRole, hasAnyRole etc. I modified classes regards to Security * Added test cases for Spring Security Expressions * Handler Interceptor - logging example * Test for logger interceptor * Removed conflicted part * UserInterceptor (adding user information to model) * Spring Handler Interceptor - session timers * Spring Security CSRF attack protection with Thymeleaf * Fix and(); * Logger update * Changed config for Thymeleaf * Thymeleaf Natural Processing and Inlining * Expression Utility Objects, Thymeleaf * listOfStudents edited * Thymeleaf layout decorators
This commit is contained in:
		
							parent
							
								
									15f5a9eca1
								
							
						
					
					
						commit
						08c9791cb4
					
				| @ -67,6 +67,12 @@ | |||||||
| 			<artifactId>thymeleaf-spring4</artifactId> | 			<artifactId>thymeleaf-spring4</artifactId> | ||||||
| 			<version>${org.thymeleaf-version}</version> | 			<version>${org.thymeleaf-version}</version> | ||||||
| 		</dependency> | 		</dependency> | ||||||
|  | 		<!-- https://mvnrepository.com/artifact/nz.net.ultraq.thymeleaf/thymeleaf-layout-dialect --> | ||||||
|  | 		<dependency> | ||||||
|  | 			<groupId>nz.net.ultraq.thymeleaf</groupId> | ||||||
|  | 			<artifactId>thymeleaf-layout-dialect</artifactId> | ||||||
|  | 			<version>2.0.4</version> | ||||||
|  | 		</dependency> | ||||||
| 		<!-- Logging --> | 		<!-- Logging --> | ||||||
| 		<dependency> | 		<dependency> | ||||||
| 			<groupId>org.slf4j</groupId> | 			<groupId>org.slf4j</groupId> | ||||||
|  | |||||||
| @ -22,6 +22,9 @@ import org.thymeleaf.templateresolver.ITemplateResolver; | |||||||
| import com.baeldung.thymeleaf.formatter.NameFormatter; | import com.baeldung.thymeleaf.formatter.NameFormatter; | ||||||
| import com.baeldung.thymeleaf.utils.ArrayUtil; | import com.baeldung.thymeleaf.utils.ArrayUtil; | ||||||
| 
 | 
 | ||||||
|  | import nz.net.ultraq.thymeleaf.LayoutDialect; | ||||||
|  | import nz.net.ultraq.thymeleaf.decorators.strategies.GroupingStrategy; | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| @Configuration | @Configuration | ||||||
| @EnableWebMvc | @EnableWebMvc | ||||||
| @ -70,6 +73,7 @@ public class WebMVCConfig extends WebMvcConfigurerAdapter implements Application | |||||||
| 
 | 
 | ||||||
| 	private TemplateEngine templateEngine(ITemplateResolver templateResolver) { | 	private TemplateEngine templateEngine(ITemplateResolver templateResolver) { | ||||||
|         SpringTemplateEngine engine = new SpringTemplateEngine(); |         SpringTemplateEngine engine = new SpringTemplateEngine(); | ||||||
|  |         engine.addDialect(new LayoutDialect(new GroupingStrategy())); | ||||||
|         engine.setTemplateResolver(templateResolver); |         engine.setTemplateResolver(templateResolver); | ||||||
|         return engine; |         return engine; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -0,0 +1,16 @@ | |||||||
|  | package com.baeldung.thymeleaf.controller; | ||||||
|  | 
 | ||||||
|  | import org.springframework.stereotype.Controller; | ||||||
|  | import org.springframework.ui.Model; | ||||||
|  | import org.springframework.web.bind.annotation.RequestMapping; | ||||||
|  | import org.springframework.web.bind.annotation.RequestMethod; | ||||||
|  | 
 | ||||||
|  | @Controller | ||||||
|  | public class LayoutDialectController { | ||||||
|  | 	 | ||||||
|  | 	@RequestMapping(value = "/layout", method = RequestMethod.GET) | ||||||
|  |     public String getNewPage(Model model) { | ||||||
|  |         return "content.html"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										16
									
								
								spring-thymeleaf/src/main/webapp/WEB-INF/views/content.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								spring-thymeleaf/src/main/webapp/WEB-INF/views/content.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | |||||||
|  | <!DOCTYPE html> | ||||||
|  | <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" | ||||||
|  | 	layout:decorate="~{template.html}"> | ||||||
|  | <head> | ||||||
|  | <title>Layout Dialect Example</title> | ||||||
|  | </head> | ||||||
|  | <body> | ||||||
|  | 	<section layout:fragment="custom-content"> | ||||||
|  | 		<p>This is a custom content that you can provide</p> | ||||||
|  | 	</section> | ||||||
|  | 	<footer> | ||||||
|  | 		<p layout:fragment="custom-footer">This is some footer content | ||||||
|  | 			that you can change</p> | ||||||
|  | 	</footer> | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
| @ -6,7 +6,7 @@ | |||||||
| </head> | </head> | ||||||
| <script type="text/javascript" | <script type="text/javascript" | ||||||
| 	src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script> | 	src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script> | ||||||
| <script th:inline="javascript"> | <script> | ||||||
| 	$(document).ready(function() { | 	$(document).ready(function() { | ||||||
| 		$.ajax({ | 		$.ajax({ | ||||||
| 			url : "/spring-thymeleaf/js", | 			url : "/spring-thymeleaf/js", | ||||||
|  | |||||||
							
								
								
									
										20
									
								
								spring-thymeleaf/src/main/webapp/WEB-INF/views/template.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								spring-thymeleaf/src/main/webapp/WEB-INF/views/template.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | |||||||
|  | <!DOCTYPE html> | ||||||
|  | <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"> | ||||||
|  | <head> | ||||||
|  | <title layout:title-pattern="$LAYOUT_TITLE - $CONTENT_TITLE">Baeldung</title> | ||||||
|  | <script type="text/javascript" | ||||||
|  | 	src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script> | ||||||
|  | </head> | ||||||
|  | <body> | ||||||
|  | 	<header> | ||||||
|  | 		<h1>New dialect example</h1> | ||||||
|  | 	</header> | ||||||
|  | 	<section layout:fragment="custom-content"> | ||||||
|  | 		<p>Your page content goes here</p> | ||||||
|  | 	</section> | ||||||
|  | 	<footer> | ||||||
|  | 		<p>My custom footer</p> | ||||||
|  | 		<p layout:fragment="custom-footer">Your custom footer here</p> | ||||||
|  | 	</footer> | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
| @ -0,0 +1,58 @@ | |||||||
|  | package com.baeldung.thymeleaf.controller; | ||||||
|  | 
 | ||||||
|  | import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; | ||||||
|  | import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; | ||||||
|  | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; | ||||||
|  | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | ||||||
|  | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; | ||||||
|  | 
 | ||||||
|  | import javax.servlet.Filter; | ||||||
|  | 
 | ||||||
|  | import org.junit.Before; | ||||||
|  | import org.junit.Test; | ||||||
|  | import org.junit.runner.RunWith; | ||||||
|  | import org.springframework.beans.factory.annotation.Autowired; | ||||||
|  | import org.springframework.mock.web.MockHttpSession; | ||||||
|  | import org.springframework.test.context.ContextConfiguration; | ||||||
|  | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; | ||||||
|  | import org.springframework.test.context.web.WebAppConfiguration; | ||||||
|  | import org.springframework.test.web.servlet.MockMvc; | ||||||
|  | import org.springframework.test.web.servlet.request.RequestPostProcessor; | ||||||
|  | import org.springframework.test.web.servlet.setup.MockMvcBuilders; | ||||||
|  | import org.springframework.web.context.WebApplicationContext; | ||||||
|  | 
 | ||||||
|  | import com.baeldung.thymeleaf.config.InitSecurity; | ||||||
|  | import com.baeldung.thymeleaf.config.WebApp; | ||||||
|  | import com.baeldung.thymeleaf.config.WebMVCConfig; | ||||||
|  | import com.baeldung.thymeleaf.config.WebMVCSecurity; | ||||||
|  | 
 | ||||||
|  | @RunWith(SpringJUnit4ClassRunner.class) | ||||||
|  | @WebAppConfiguration | ||||||
|  | @ContextConfiguration(classes = { WebApp.class, WebMVCConfig.class, WebMVCSecurity.class, InitSecurity.class }) | ||||||
|  | public class LayoutDialectControllerTest { | ||||||
|  | 
 | ||||||
|  | 	@Autowired | ||||||
|  |     WebApplicationContext wac; | ||||||
|  |     @Autowired | ||||||
|  |     MockHttpSession session; | ||||||
|  | 
 | ||||||
|  |     private MockMvc mockMvc; | ||||||
|  | 
 | ||||||
|  |     @Autowired | ||||||
|  |     private Filter springSecurityFilterChain; | ||||||
|  | 
 | ||||||
|  |     protected RequestPostProcessor testUser() { | ||||||
|  |         return user("user1").password("user1Pass").roles("USER"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Before | ||||||
|  |     public void setup() { | ||||||
|  |         mockMvc = MockMvcBuilders.webAppContextSetup(wac).addFilters(springSecurityFilterChain).build(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 	@Test | ||||||
|  | 	public void testGetDates() throws Exception{ | ||||||
|  | 		mockMvc.perform(get("/layout").with(testUser()).with(csrf())).andExpect(status().isOk()).andExpect(view().name("content.html")); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user