Merge pull request #8123 from sandy03934/BAEL-3283

Bael 3283
This commit is contained in:
Josh Cummings 2019-11-30 00:14:11 -07:00 committed by GitHub
commit 20566a4bca
20 changed files with 526 additions and 0 deletions

View File

@ -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>

120
spring-mvc-views/pom.xml Normal file
View File

@ -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>

View File

@ -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();
}
}

View File

@ -0,0 +1,6 @@
package com.baeldung.config;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class InitSecurity extends AbstractSecurityWebApplicationInitializer {
}

View File

@ -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/**");
}
}

View File

@ -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();
}
}

View File

@ -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("/");
}
}

View File

@ -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";
}
}

View File

@ -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;
}
}

View File

@ -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> {
}

View File

@ -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);
}
}
}

View File

@ -0,0 +1,2 @@
styleSheet=themes/black.css
background=black

View File

@ -0,0 +1,2 @@
styleSheet=themes/black.css
background=black

View File

@ -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)
);

View File

@ -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');

View File

@ -0,0 +1,2 @@
styleSheet=themes/white.css
background=black

View File

@ -0,0 +1,2 @@
styleSheet=themes/white.css
background=black

View File

@ -0,0 +1,8 @@
body {
justify-content : center;
background-color : black;
color : white;
text-align : center;
margin-left : 15%;
margin-right : 15%;
}

View File

@ -0,0 +1,8 @@
body {
justify-content : center;
background-color : white;
color : black;
text-align : center;
margin-left : 15%;
margin-right : 15%;
}

View File

@ -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>