commit
20566a4bca
2
pom.xml
2
pom.xml
|
@ -790,6 +790,7 @@
|
|||
<module>spring-mvc-kotlin</module>
|
||||
<module>spring-mvc-simple</module>
|
||||
<module>spring-mvc-simple-2</module>
|
||||
<module>spring-mvc-views</module>
|
||||
<module>spring-mvc-velocity</module>
|
||||
<module>spring-mvc-webflow</module>
|
||||
<module>spring-mvc-xml</module>
|
||||
|
@ -1393,6 +1394,7 @@
|
|||
<module>spring-mvc-kotlin</module>
|
||||
<module>spring-mvc-simple</module>
|
||||
<module>spring-mvc-simple-2</module>
|
||||
<module>spring-mvc-views</module>
|
||||
<module>spring-mvc-velocity</module>
|
||||
<module>spring-mvc-webflow</module>
|
||||
<module>spring-mvc-xml</module>
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
<?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>
|
||||
<artifactId>spring-mvc-views</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<name>spring-mvc-views</name>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-spring-5</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../parent-spring-5</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<javax.servlet.jsp-api.version>2.3.3</javax.servlet.jsp-api.version>
|
||||
<javax.servlet-api.version>4.0.1</javax.servlet-api.version>
|
||||
<spring.version>5.2.1.RELEASE</spring.version>
|
||||
<spring.security.version>5.2.1.RELEASE</spring.security.version>
|
||||
<spring.data.version>2.2.2.RELEASE</spring.data.version>
|
||||
<cglib.version>2.2.2</cglib.version>
|
||||
<hsqldb.version>2.5.0</hsqldb.version>
|
||||
<hibernate.version>5.4.9.Final</hibernate.version>
|
||||
<deploy-path>enter-location-of-server</deploy-path>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>${javax.servlet-api.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet.jsp</groupId>
|
||||
<artifactId>javax.servlet.jsp-api</artifactId>
|
||||
<version>${javax.servlet.jsp-api.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>jstl</artifactId>
|
||||
<version>${jstl.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-jpa</artifactId>
|
||||
<version>${spring.data.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
<version>${hibernate.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hsqldb</groupId>
|
||||
<artifactId>hsqldb</artifactId>
|
||||
<version>${hsqldb.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>${spring.security.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<version>${spring.security.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-taglibs</artifactId>
|
||||
<version>${spring.security.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>spring-mvc-theme</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>2.0.2</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>${maven-war-plugin.version}</version>
|
||||
<configuration>
|
||||
<warSourceDirectory>src/main/webapp</warSourceDirectory>
|
||||
<warName>spring-mvc-views</warName>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
<outputDirectory>${deploy-path}</outputDirectory>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,44 @@
|
|||
package com.baeldung.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
@EnableJpaRepositories(basePackages = "com.baeldung")
|
||||
public class DataSourceConfig {
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
|
||||
return builder.setType(EmbeddedDatabaseType.HSQL)
|
||||
.addScripts("db/sql/create-db.sql", "db/sql/insert-data.sql")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
|
||||
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
|
||||
em.setDataSource(dataSource);
|
||||
em.setPackagesToScan("com.baeldung.domain");
|
||||
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
|
||||
return em;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
|
||||
return new JpaTransactionManager(emf);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
|
||||
return new PersistenceExceptionTranslationPostProcessor();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package com.baeldung.config;
|
||||
|
||||
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
|
||||
|
||||
public class InitSecurity extends AbstractSecurityWebApplicationInitializer {
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package com.baeldung.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
@EnableWebSecurity
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
DataSource dataSource;
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.jdbcAuthentication()
|
||||
.passwordEncoder(passwordEncoder())
|
||||
.dataSource(dataSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
|
||||
http.csrf()
|
||||
.disable()
|
||||
.authorizeRequests()
|
||||
.antMatchers("/anonymous*").anonymous()
|
||||
.antMatchers("/login*").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.formLogin()
|
||||
.and()
|
||||
.logout()
|
||||
.logoutUrl("/logout.do")
|
||||
.invalidateHttpSession(true)
|
||||
.clearAuthentication(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(WebSecurity web) throws Exception {
|
||||
web.ignoring().antMatchers("/themes/**");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package com.baeldung.config;
|
||||
|
||||
import com.baeldung.theme.resolver.UserPreferenceThemeResolver;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.ui.context.support.ResourceBundleThemeSource;
|
||||
import org.springframework.web.servlet.ThemeResolver;
|
||||
import org.springframework.web.servlet.config.annotation.*;
|
||||
import org.springframework.web.servlet.theme.ThemeChangeInterceptor;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan(basePackages="com.baeldung")
|
||||
@EnableWebMvc
|
||||
public class ThemeMVCConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/themes/**").addResourceLocations("classpath:/themes/");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(themeChangeInterceptor());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ThemeChangeInterceptor themeChangeInterceptor() {
|
||||
ThemeChangeInterceptor interceptor = new ThemeChangeInterceptor();
|
||||
interceptor.setParamName("theme");
|
||||
return interceptor;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ResourceBundleThemeSource resourceBundleThemeSource() {
|
||||
ResourceBundleThemeSource themeSource = new ResourceBundleThemeSource();
|
||||
themeSource.setFallbackToSystemLocale(true);
|
||||
return themeSource;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ThemeResolver themeResolver() {
|
||||
UserPreferenceThemeResolver themeResolver = new UserPreferenceThemeResolver();
|
||||
themeResolver.setDefaultThemeName("light");
|
||||
return themeResolver;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void configureViewResolvers(ViewResolverRegistry resolverRegistry) {
|
||||
resolverRegistry.jsp();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.baeldung.config;
|
||||
|
||||
import org.springframework.web.WebApplicationInitializer;
|
||||
import org.springframework.web.context.ContextLoaderListener;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRegistration;
|
||||
|
||||
public class WebInitializer implements WebApplicationInitializer {
|
||||
@Override
|
||||
public void onStartup(javax.servlet.ServletContext servletContext) throws ServletException {
|
||||
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
|
||||
context.register(DataSourceConfig.class);
|
||||
context.register(ThemeMVCConfig.class);
|
||||
|
||||
|
||||
servletContext.addListener(new ContextLoaderListener(context));
|
||||
servletContext.setInitParameter("spring.profiles.active", "database");
|
||||
|
||||
ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
|
||||
|
||||
servlet.setLoadOnStartup(1);
|
||||
servlet.addMapping("/");
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.baeldung.controllers;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
@Controller
|
||||
public class AppController {
|
||||
|
||||
@RequestMapping("/")
|
||||
public String home() {
|
||||
return "index";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package com.baeldung.domain;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "preferences")
|
||||
public class UserPreference {
|
||||
@Id
|
||||
private String username;
|
||||
|
||||
private String theme;
|
||||
|
||||
public String getTheme() {
|
||||
return theme;
|
||||
}
|
||||
|
||||
public void setTheme(String theme) {
|
||||
this.theme = theme;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package com.baeldung.repository;
|
||||
|
||||
import com.baeldung.domain.UserPreference;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
|
||||
public interface UserPreferenceRepository extends PagingAndSortingRepository<UserPreference, String> {
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package com.baeldung.theme.resolver;
|
||||
|
||||
import com.baeldung.domain.UserPreference;
|
||||
import com.baeldung.repository.UserPreferenceRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.servlet.ThemeResolver;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Optional;
|
||||
|
||||
public class UserPreferenceThemeResolver implements ThemeResolver {
|
||||
|
||||
public static final String THEME_REQUEST_ATTRIBUTE_NAME = UserPreferenceThemeResolver.class.getName() + ".THEME";
|
||||
|
||||
@Autowired(required = false)
|
||||
Authentication authentication;
|
||||
|
||||
@Autowired
|
||||
UserPreferenceRepository userPreferenceRepository;
|
||||
|
||||
private String defaultThemeName;
|
||||
|
||||
public String getDefaultThemeName() {
|
||||
return defaultThemeName;
|
||||
}
|
||||
|
||||
public void setDefaultThemeName(String defaultThemeName) {
|
||||
this.defaultThemeName = defaultThemeName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolveThemeName(HttpServletRequest request) {
|
||||
String themeName = findThemeFromRequest(request).orElse(findUserPreferredTheme().orElse(getDefaultThemeName()));
|
||||
request.setAttribute(THEME_REQUEST_ATTRIBUTE_NAME, themeName);
|
||||
return themeName;
|
||||
}
|
||||
|
||||
private Optional<String> findUserPreferredTheme() {
|
||||
Authentication authentication = SecurityContextHolder.getContext()
|
||||
.getAuthentication();
|
||||
UserPreference userPreference = getUserPreference(authentication).orElse(new UserPreference());
|
||||
return Optional.ofNullable(userPreference.getTheme());
|
||||
}
|
||||
|
||||
private Optional<String> findThemeFromRequest(HttpServletRequest request) {
|
||||
return Optional.ofNullable((String) request.getAttribute(THEME_REQUEST_ATTRIBUTE_NAME));
|
||||
}
|
||||
|
||||
private Optional<UserPreference> getUserPreference(Authentication authentication) {
|
||||
return isAuthenticated(authentication) ? userPreferenceRepository.findById(((User) authentication.getPrincipal()).getUsername()) : Optional.empty();
|
||||
}
|
||||
|
||||
private boolean isAuthenticated(Authentication authentication) {
|
||||
return authentication != null && authentication.isAuthenticated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setThemeName(HttpServletRequest request, HttpServletResponse response, String theme) {
|
||||
Authentication authentication = SecurityContextHolder.getContext()
|
||||
.getAuthentication();
|
||||
if (isAuthenticated(authentication)) {
|
||||
request.setAttribute(THEME_REQUEST_ATTRIBUTE_NAME, theme);
|
||||
UserPreference userPreference = getUserPreference(authentication).orElse(new UserPreference());
|
||||
userPreference.setUsername(((User) authentication.getPrincipal()).getUsername());
|
||||
userPreference.setTheme(StringUtils.hasText(theme) ? theme : null);
|
||||
userPreferenceRepository.save(userPreference);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
styleSheet=themes/black.css
|
||||
background=black
|
|
@ -0,0 +1,2 @@
|
|||
styleSheet=themes/black.css
|
||||
background=black
|
|
@ -0,0 +1,17 @@
|
|||
create table users (
|
||||
username varchar(50) not null primary key,
|
||||
password varchar(256) not null,
|
||||
enabled boolean not null
|
||||
);
|
||||
|
||||
|
||||
create table authorities (
|
||||
username varchar(50) not null,
|
||||
authority varchar(50) not null
|
||||
);
|
||||
|
||||
|
||||
create table preferences (
|
||||
username varchar(50) not null,
|
||||
theme varchar(50)
|
||||
);
|
|
@ -0,0 +1,6 @@
|
|||
insert into users values('john', '$2a$10$cjcbIX/aLe12PpGZ.vQfweLiB7K1QTC5enTk3oD0deCMdtj2Sx.im', 1);
|
||||
insert into users values('admin', '$2a$10$cjcbIX/aLe12PpGZ.vQfweLiB7K1QTC5enTk3oD0deCMdtj2Sx.im', 1);
|
||||
|
||||
insert into authorities values('john', 'USER');
|
||||
insert into authorities values('admin', 'USER');
|
||||
insert into authorities values('admin', 'ADMIN');
|
|
@ -0,0 +1,2 @@
|
|||
styleSheet=themes/white.css
|
||||
background=black
|
|
@ -0,0 +1,2 @@
|
|||
styleSheet=themes/white.css
|
||||
background=black
|
|
@ -0,0 +1,8 @@
|
|||
body {
|
||||
justify-content : center;
|
||||
background-color : black;
|
||||
color : white;
|
||||
text-align : center;
|
||||
margin-left : 15%;
|
||||
margin-right : 15%;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
body {
|
||||
justify-content : center;
|
||||
background-color : white;
|
||||
color : black;
|
||||
text-align : center;
|
||||
margin-left : 15%;
|
||||
margin-right : 15%;
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
|
||||
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
|
||||
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<link rel="stylesheet" href="<spring:theme code='styleSheet'/>"/>
|
||||
<title>Themed Application</title>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>Themed Application</h1>
|
||||
<hr />
|
||||
</header>
|
||||
<section>
|
||||
<h2>Spring MVC Theme Demo</h2>
|
||||
<security:authorize access="isAuthenticated()">
|
||||
<h4>User : <security:authentication property="principal.username" /></h4>
|
||||
</security:authorize>
|
||||
<form action="<c:url value='/'/>" method="POST" name="themeChangeForm" id="themeChangeForm">
|
||||
<div>
|
||||
<h4>
|
||||
Change Theme
|
||||
</h4>
|
||||
</div>
|
||||
<select id="theme" name="theme" onChange="submitForm()">
|
||||
<option value="">Reset</option>
|
||||
<option value="light">Light</option>
|
||||
<option value="dark">Dark</option>
|
||||
</select>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<form action="<c:url value='/logout.do'/>" method="POST" name="logoutForm">
|
||||
<button type="submit" name="submit">Sign Out</button>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
function submitForm() {
|
||||
document.themeChangeForm.submit();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue